Comment: | Pulled in refactoring done on v1.70 branch |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | v1.70-refactor01 | v1.70-defunct-try |
Files: | files | file ages | folders |
SHA1: |
4ace5420349612ff6da86c8f691ce292 |
User & Date: | matt on 2019-12-15 22:47:22 |
Other Links: | branch diff | manifest | tags |
2019-12-15
| ||
22:55 | Added missing use of mtargs in commonmod. check-in: 87ba620600 user: matt tags: v1.70-refactor01, v1.70-defunct-try | |
22:47 | Pulled in refactoring done on v1.70 branch check-in: 4ace542034 user: matt tags: v1.70-refactor01, v1.70-defunct-try | |
22:39 | Added missing mtconfigf to dashboard.scm check-in: 4585ec5c6e user: matt tags: v1.70-defunct-try | |
2019-12-12
| ||
20:58 | Added or to line 2464 in runs-inc.scm to keep going if no runname. This bypassess the real issue where runname is being lost. Also bypassed all server/network code. check-in: 3f5da1ddca user: matt tags: v1.70-refactor01, v1.70-defunct-try | |
Modified Makefile from [3b8892abb7] to [ce31b5458b].
︙ | ︙ | |||
27 28 29 30 31 32 33 | # removed from MSRCFILES: ftail.scm # module source files MSRCFILES = dbmod.scm rmtmod.scm commonmod.scm apimod.scm \ archivemod.scm clientmod.scm envmod.scm ezstepsmod.scm itemsmod.scm \ keysmod.scm launchmod.scm odsmod.scm processmod.scm runconfigmod.scm \ runsmod.scm servermod.scm subrunmod.scm tasksmod.scm testsmod.scm \ | | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | # removed from MSRCFILES: ftail.scm # module source files MSRCFILES = dbmod.scm rmtmod.scm commonmod.scm apimod.scm \ archivemod.scm clientmod.scm envmod.scm ezstepsmod.scm itemsmod.scm \ keysmod.scm launchmod.scm odsmod.scm processmod.scm runconfigmod.scm \ runsmod.scm servermod.scm subrunmod.scm tasksmod.scm testsmod.scm \ pkts.scm mtargs.scm mtconfigf.scm ducttape-lib.scm megamod.scm GMSRCFILES = dcommonmod.scm vgmod.scm treemod.scm # Eggs to install (straightforward ones) EGGS=matchable readline apropos base64 regex-literals format \ regex-case test coops trace csv dot-locking posix-utils posix-extras \ directory-utils hostinfo tcp-server rpc csv-xml fmt json md5 awful \ http-client spiffy uri-common intarweb spiffy-request-vars \ |
︙ | ︙ | |||
57 58 59 60 61 62 63 | GMOFILES = $(addprefix mofiles/,$(GMSRCFILES:%.scm=%.o)) # compiled import files GMOIMPFILES = $(GMSRCFILES:%.scm=%.import.o) %.import.o : %.import.scm csc -unit $*.import -c $*.import.scm -o $*.import.o | > > > | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | GMOFILES = $(addprefix mofiles/,$(GMSRCFILES:%.scm=%.o)) # compiled import files GMOIMPFILES = $(GMSRCFILES:%.scm=%.import.o) %.import.o : %.import.scm csc -unit $*.import -c $*.import.scm -o $*.import.o # mofiles/ducttape-lib.o : ducttape-lib.scm ducttape/*scm # csc -I ducttape -J -c ducttape-lib.scm -o mofiles/ducttape-lib.o mofiles/%.o %.import.scm : %.scm mkdir -p mofiles csc $(CSCOPTS) -J -c $< -o mofiles/$*.o # a.import.o : a.import.scm a.o # csc -unit a.import -c a.import.scm -o $*.o ADTLSCR=mt_laststep mt_runstep mt_ezstep |
︙ | ︙ | |||
85 86 87 88 89 90 91 | ARCHSTR=$(shell if [[ -e /usr/bin/sw_vers ]]; then /usr/bin/sw_vers -productVersion; else lsb_release -sr; fi) # ARCHSTR=$(shell bash -c "echo \$$MACHTYPE") PNGFILES = $(shell cd docs/manual;ls *png) #all : $(PREFIX)/bin/.$(ARCHSTR) mtest dboard mtut ndboard | | | | | | | | | | | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | ARCHSTR=$(shell if [[ -e /usr/bin/sw_vers ]]; then /usr/bin/sw_vers -productVersion; else lsb_release -sr; fi) # ARCHSTR=$(shell bash -c "echo \$$MACHTYPE") PNGFILES = $(shell cd docs/manual;ls *png) #all : $(PREFIX)/bin/.$(ARCHSTR) mtest dboard mtut ndboard # IMPORTO = apimod.import.o dbmod.import.o itemsmod.import.o \ # odsmod.import.o runsmod.import.o testsmod.import.o \ # archivemod.import.o keysmod.import.o processmod.import.o \ # servermod.import.o clientmod.import.o envmod.import.o \ # launchmod.import.o rmtmod.import.o subrunmod.import.o \ # commonmod.import.o ezstepsmod.import.o megamod.import.o \ # runconfigmod.import.o tasksmod.import.o pkts.import.o all : $(PREFIX)/bin/.$(ARCHSTR) mtest dboard mtut tcmt # why were the files mofiles/ftail.o mofiles/rmtmod.o mofiles/commonmod.o listed on this target when MOFILES are there? # Removed non module .o files (i.e. $(OFILES) mtest: readline-fix.scm megatest.o $(MOFILES) $(MOIMPFILES) mofiles/ducttape-lib.o csc $(CSCOPTS) $(MOFILES) $(MOIMPFILES) megatest.o -o mtest showmtesthash: @echo $(MTESTHASH) # removing $(GOFILES) dboard : dashboard.o $(MOFILES) $(MOIMPFILES) $(GMOFILES) $(GMOIMPFILES) csc $(CSCOPTS) dashboard.o $(MOFILES) $(MOIMPFILES) $(GMOFILES) $(GMOIMPFILES) -o dboard ndboard : newdashboard.scm $(GOFILES) csc $(CSCOPTS) $(GOFILES) newdashboard.scm -o ndboard mtut: $(MOFILES) megatest-fossil-hash.scm mtut.scm csc $(CSCOPTS) $(MOFILES) mtut.scm -o mtut |
︙ | ︙ | |||
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | #multi-dboard : multi-dboard.scm $(OFILES) $(GOFILES) # csc $(CSCOPTS) $(OFILES) $(GOFILES) multi-dboard.scm -o multi-dboard # # $(PREFIX)/bin/revtagfsl : utils/revtagfsl.scm # csc utils/revtagfsl.scm -o $(PREFIX)/bin/revtagfsl # Special dependencies for the includes tests.o db.o launch.o runs.o dashboard-tests.o dashboard-context-menu.o dashboard-guimonitor.o dashboard-main.o monitor.o dashboard.o \ archive.o megatest.o : db_records.scm migrate-fix.scm tests.o runs.o dashboard.o dashboard-tests.o dashboard-context-menu.o dashboard-main.o : run_records.scm db.o ezsteps.o keys.o launch.o megatest.o monitor.o runs-for-ref.o runs.o tests.o : key_records.scm tests.o tasks.o dashboard-tasks.o : task_records.scm runs.o : test_records.scm megatest.o : megatest-fossil-hash.scm rmt.scm client.scm common.scm configf.scm dashboard-guimonitor.scm dashboard-tests.scm dashboard.scm db.scm dcommon.scm ezsteps.scm fs-transport.scm http-transport.scm index-tree.scm items.scm keys.scm launch.scm megatest.scm monitor.scm mt.scm newdashboard.scm runconfig.scm runs.scm server.scm tdb.scm tests.scm tree.scm : common_records.scm common_records.scm : altdb.scm vg.o dashboard.o : vg_records.scm mofiles/dcommonmod.o dcommon.o : run_records.scm migrate-fix.scm # Temporary while transitioning to new routine # runs.o : run-tests-queue-classic.scm run-tests-queue-new.scm # for the modularized stuff mofiles/commonmod.o : megatest-fossil-hash.scm mofiles/dbmod.o : mofiles/commonmod.o mofiles/keysmod.o mofiles/tasksmod.o mofiles/odsmod.o | > > > > > > > > > > > > > > > > > > > | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | #multi-dboard : multi-dboard.scm $(OFILES) $(GOFILES) # csc $(CSCOPTS) $(OFILES) $(GOFILES) multi-dboard.scm -o multi-dboard # # $(PREFIX)/bin/revtagfsl : utils/revtagfsl.scm # csc utils/revtagfsl.scm -o $(PREFIX)/bin/revtagfsl #====================================================================== # Special dependencies for the includes #====================================================================== tests.o db.o launch.o runs.o dashboard-tests.o dashboard-context-menu.o dashboard-guimonitor.o dashboard-main.o monitor.o dashboard.o \ archive.o megatest.o : db_records.scm migrate-fix.scm tests.o runs.o dashboard.o dashboard-tests.o dashboard-context-menu.o dashboard-main.o : run_records.scm db.o ezsteps.o keys.o launch.o megatest.o monitor.o runs-for-ref.o runs.o tests.o : key_records.scm tests.o tasks.o dashboard-tasks.o : task_records.scm runs.o : test_records.scm megatest.o : megatest-fossil-hash.scm rmt.scm client.scm common.scm configf.scm dashboard-guimonitor.scm dashboard-tests.scm dashboard.scm db.scm dcommon.scm ezsteps.scm fs-transport.scm http-transport.scm index-tree.scm items.scm keys.scm launch.scm megatest.scm monitor.scm mt.scm newdashboard.scm runconfig.scm runs.scm server.scm tdb.scm tests.scm tree.scm : common_records.scm common_records.scm : altdb.scm vg.o dashboard.o : vg_records.scm mofiles/dcommonmod.o dcommon.o : run_records.scm migrate-fix.scm # special include based modules mofiles/pkts.o : pkts/pkts.scm mofiles/mtargs.o : mtargs/mtargs.scm mofiles/mtconfigf.o : mtconfigf/mtconfigf.scm # mofile/ducttape-lib.o : ducttape/ducttape-lib.scm # Temporary while transitioning to new routine # runs.o : run-tests-queue-classic.scm run-tests-queue-new.scm # for the modularized stuff mofiles/commonmod.o : megatest-fossil-hash.scm mofiles/dbmod.o : mofiles/commonmod.o mofiles/keysmod.o mofiles/tasksmod.o mofiles/odsmod.o |
︙ | ︙ | |||
218 219 220 221 222 223 224 225 226 227 228 229 | mofiles/processmod.o \ mofiles/runconfigmod.o \ mofiles/runsmod.o \ mofiles/servermod.o \ mofiles/subrunmod.o \ mofiles/tasksmod.o \ mofiles/testsmod.o \ *-inc.scm mofiles/dcommonmod.o : \ mofiles/vgmod.o \ mofiles/treemod.o \ | > > > > | > | 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | mofiles/processmod.o \ mofiles/runconfigmod.o \ mofiles/runsmod.o \ mofiles/servermod.o \ mofiles/subrunmod.o \ mofiles/tasksmod.o \ mofiles/testsmod.o \ mofiles/pkts.o \ mofiles/mtargs.o \ mofiles/mtconfigf.o \ mofiles/ducttape-lib.o \ *-inc.scm mofiles/dcommonmod.o : \ mofiles/vgmod.o \ mofiles/treemod.o \ mofiles/ezstepsmod.o \ mofiles/mtargs.o # $(MOFILES) : mofiles/commonmod.o megatest-fossil-hash.scm : $(SRCFILES) megatest.scm *_records.scm echo "(define megatest-fossil-hash \"$(MTESTHASH)\")" > megatest-fossil-hash.new if ! diff -q megatest-fossil-hash.new megatest-fossil-hash.scm ; then echo copying .new to .scm;cp -f megatest-fossil-hash.new megatest-fossil-hash.scm;fi |
︙ | ︙ |
Modified dashboard.scm from [e29ff98288] to [53e0f92bae].
︙ | ︙ | |||
21 22 23 24 25 26 27 | (use format) (require-library iup) (import (prefix iup iup:)) (use canvas-draw) (import canvas-draw-iup) | | | < > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | (use format) (require-library iup) (import (prefix iup iup:)) (use canvas-draw) (import canvas-draw-iup) ;; (use ducttape-lib) (use sqlite3 srfi-1 posix regex regex-case srfi-69 typed-records sparse-vectors srfi-18 #;(prefix mtconfigf configf:) ) (import (prefix sqlite3 sqlite3:)) ;; (declare (uses common)) ;; (declare (uses margs)) ;; (declare (uses keys)) ;; (declare (uses items)) ;; (declare (uses db)) |
︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | (declare (uses dbmod)) (import dbmod) (declare (uses testsmod)) (import testsmod) (declare (uses dcommonmod)) (import dcommonmod) (include "common_records.scm") (include "db_records.scm") (include "run_records.scm") (include "task_records.scm") ;; (include "megatest-fossil-hash.scm") ;; comes from megamod (include "vg_records.scm") ;; invoke the imports (declare (uses commonmod.import)) (declare (uses testsmod.import)) (declare (uses rmtmod.import)) (declare (uses runsmod.import)) (declare (uses megamod.import)) (declare (uses dcommonmod.import)) (configf:set-debug-printers debug:print debug:print-info debug:print-error *default-log-port*) (configf:add-eval-string "(import megamod)(import commonmod)") (define help (conc "Megatest Dashboard, documentation at http://www.kiatoa.com/fossils/megatest | > > > > > > > > > > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | (declare (uses dbmod)) (import dbmod) (declare (uses testsmod)) (import testsmod) (declare (uses dcommonmod)) (import dcommonmod) (declare (uses mtargs)) (import (prefix mtargs args:)) (declare (uses ducttape-lib)) (import ducttape-lib) (declare (uses mtconfigf)) (import (prefix mtconfigf configf:)) (include "common_records.scm") (include "db_records.scm") (include "run_records.scm") (include "task_records.scm") ;; (include "megatest-fossil-hash.scm") ;; comes from megamod (include "vg_records.scm") ;; invoke the imports (declare (uses commonmod.import)) (declare (uses testsmod.import)) (declare (uses rmtmod.import)) (declare (uses runsmod.import)) (declare (uses megamod.import)) (declare (uses dcommonmod.import)) (declare (uses mtargs.import)) (declare (uses ducttape-lib.import)) (declare (uses mtconfigf.import)) (configf:set-debug-printers debug:print debug:print-info debug:print-error *default-log-port*) (configf:add-eval-string "(import megamod)(import commonmod)") (define help (conc "Megatest Dashboard, documentation at http://www.kiatoa.com/fossils/megatest |
︙ | ︙ |
Modified dcommonmod.scm from [80c862d803] to [fdab2018b7].
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ;;====================================================================== (declare (unit dcommonmod)) (declare (uses commonmod)) (declare (uses testsmod)) (declare (uses megamod)) (module dcommonmod * (import scheme chicken data-structures extras) (import (prefix sqlite3 sqlite3:) posix typed-records srfi-18 srfi-69 format ports srfi-1 | > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ;;====================================================================== (declare (unit dcommonmod)) (declare (uses commonmod)) (declare (uses testsmod)) (declare (uses megamod)) (declare (uses mtargs)) (module dcommonmod * (import scheme chicken data-structures extras) (import (prefix sqlite3 sqlite3:) posix typed-records srfi-18 srfi-69 format ports srfi-1 |
︙ | ︙ | |||
84 85 86 87 88 89 90 91 92 93 94 95 96 97 | (import commonmod) (import testsmod) (import megamod) (import canvas-draw) (import canvas-draw-iup) (use (prefix iup iup:)) (define *tim* (iup:timer)) ;; (use (prefix ulex ulex:)) (include "common_records.scm") (include "db_records.scm") | > | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | (import commonmod) (import testsmod) (import megamod) (import canvas-draw) (import canvas-draw-iup) (use (prefix iup iup:)) (import (prefix mtargs args:)) (define *tim* (iup:timer)) ;; (use (prefix ulex ulex:)) (include "common_records.scm") (include "db_records.scm") |
︙ | ︙ |
Added ducttape-lib.scm version [ee2ef474af].
> > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ;;====================================================================== ;; Copyright 2019, Matthew Welland. ;; ;; This file is part of Megatest. ;; ;; Megatest is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; Megatest is distributed in the hope that 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 Megatest. If not, see <http://www.gnu.org/licenses/>. ;;====================================================================== (declare (unit ducttape-lib)) (include "ducttape/ducttape-lib.scm") |
Added ducttape/Makefile version [9efb623beb].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | help: @echo "" @echo "make targets:" @echo "=============" @echo "install - build and install general_lib egg as icfadm" @echo "test - run unit tests on ducttape-lib.scm (tests code, not egg)" @echo "eggs-info - show chicken-install commands to get eggs upon which ducttape-lib depends" @echo "test_example - compile an example scm against installed general_lib egg" @echo "clean - remove binaries and other build artifacts" @echo "" clean: rm -f *.so *.import.scm test_ducttape test_example foo *.c *.o install: chicken-install test: echo '(handle-exceptions exn (begin (print-call-chain) (exit 1)) (load "ducttape-lib.scm") (inote "hello")) (exit 0)' | csi chicken-install -no-install csc test_ducttape.scm ./test_ducttape rm -f foo test_example: @csc test_example.scm @./test_example @rm test_example eggs-info: @echo chicken-install ansi-escape-sequences @echo chicken-install slice @echo chicken-install rfc3339 |
Added ducttape/README version [bc9be285fc].
> > > > > > > > | 1 2 3 4 5 6 7 8 | This directory holds the "ducttape" chicken scheme egg used by megatest. Run "make test" to ensure this egg works on your system. Run "make install" as your admin user with chicken on your $PATH to install this egg. |
Added ducttape/ducttape-lib.import.scm version [31a238cf76].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | ;;;; ducttape-lib.import.scm - GENERATED BY CHICKEN 4.10.0 -*- Scheme -*- (eval '(import scheme chicken extras ports data-structures posix regex ansi-escape-sequences test srfi-1 irregex slice srfi-13 rfc3339 directory-utils uuid-lib filepath srfi-19 srfi-19 test regex)) (##sys#register-compiled-module 'ducttape-lib (list) '((runs-ok . ducttape-lib#runs-ok) (ducttape-debug-level . ducttape-lib#ducttape-debug-level) (ducttape-debug-regex-filter . ducttape-lib#ducttape-debug-regex-filter) (ducttape-silent-mode . ducttape-lib#ducttape-silent-mode) (ducttape-quiet-mode . ducttape-lib#ducttape-quiet-mode) (ducttape-log-file . ducttape-lib#ducttape-log-file) (ducttape-color-mode . ducttape-lib#ducttape-color-mode) (iputs-preamble . ducttape-lib#iputs-preamble) (script-name . ducttape-lib#script-name) (idbg . ducttape-lib#idbg) (ierr . ducttape-lib#ierr) (iwarn . ducttape-lib#iwarn) (inote . ducttape-lib#inote) (iputs . ducttape-lib#iputs) (re-match? . ducttape-lib#re-match?) (keyword-skim . ducttape-lib#keyword-skim) (skim-cmdline-opts-noarg-by-regex . ducttape-lib#skim-cmdline-opts-noarg-by-regex) (skim-cmdline-opts-withargs-by-regex . ducttape-lib#skim-cmdline-opts-withargs-by-regex) (concat-lists . ducttape-lib#concat-lists) (ducttape-process-command-line . ducttape-lib#ducttape-process-command-line) (ducttape-append-logfile . ducttape-lib#ducttape-append-logfile) (ducttape-activate-logfile . ducttape-lib#ducttape-activate-logfile) (isys . ducttape-lib#isys) (do-or-die . ducttape-lib#do-or-die) (counter-maker . ducttape-lib#counter-maker) (dir-is-writable? . ducttape-lib#dir-is-writable?) (mktemp . ducttape-lib#mktemp) (get-tmpdir . ducttape-lib#get-tmpdir) (sendmail . ducttape-lib#sendmail) (find-exe . ducttape-lib#find-exe) (zeropad . ducttape-lib#zeropad) (string-leftpad . ducttape-lib#string-leftpad) (string-rightpad . ducttape-lib#string-rightpad) (seconds->isodate . ducttape-lib#seconds->isodate) (seconds->wwdate . ducttape-lib#seconds->wwdate) (seconds->wwdate-values . ducttape-lib#seconds->wwdate-values) (isodate->seconds . ducttape-lib#isodate->seconds) (isodate->wwdate . ducttape-lib#isodate->wwdate) (wwdate->seconds . ducttape-lib#wwdate->seconds) (wwdate->isodate . ducttape-lib#wwdate->isodate) (current-wwdate . ducttape-lib#current-wwdate) (current-isodate . ducttape-lib#current-isodate)) (list) (list)) ;; END OF FILE |
Added ducttape/ducttape-lib.meta version [a22283c9d8].
> > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 | ;;; ducttape-lib.meta -*- Hen -*- ((egg "ducttape-lib.egg") (synopsis "Miscellaneous tool and standard print routines.") (category env) (author "Brandon Barclay") (doc-from-wiki) (license "GPL-2") ;; srfi-69, posix, srfi-18 (depends regex) (test-depends test) ; suspicious - (files "ducttape-lib") ) |
Added ducttape/ducttape-lib.scm version [59b0a2f94a].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 | (module ducttape-lib ( runs-ok ducttape-debug-level ducttape-debug-regex-filter ducttape-silent-mode ducttape-quiet-mode ducttape-log-file ducttape-color-mode iputs-preamble script-name idbg ierr iwarn inote iputs re-match? ; launch-repl keyword-skim skim-cmdline-opts-noarg-by-regex skim-cmdline-opts-withargs-by-regex get-cli-arg get-cli-switch concat-lists ducttape-process-command-line ducttape-append-logfile ducttape-activate-logfile isys do-or-die counter-maker dir-is-writable? mktemp get-tmpdir sendmail find-exe zeropad string-leftpad string-rightpad seconds->isodate seconds->wwdate seconds->wwdate-values isodate->seconds isodate->wwdate wwdate->seconds wwdate->isodate current-wwdate current-isodate *this-exe-dir* *this-exe-name* *this-exe-fullpath* ) (import scheme chicken extras ports data-structures ) (use posix regex ansi-escape-sequences test srfi-1 irregex slice srfi-13 rfc3339) ;;scsh-process ;; dropping scsh-process, it was clobbering posix's process and process* (use directory-utils uuid-lib filepath srfi-19 ) ; linenoise ;; plugs a hole in posix-extras in latter chicken versions (use posix-extras pathname-expand files) (define ##sys#expand-home-path pathname-expand) (define (realpath x) (resolve-pathname (pathname-expand (or x "/dev/null")) )) ;; (include "mimetypes.scm") ; provides ext->mimetype ;; (include "workweekdate.scm") ;; gathered from macosx: ;; cat /etc/apache2/mime.types | grep -v '^#' | perl -ne 'print "(\"$2\" . \"$1\")\n" if /(\S+)\s+(\S+)/' > mimetypes.scm ;; + manual manipulation (define ducttape_ext2mimetype '(("ez" . "application/andrew-inset") ("aw" . "application/applixware") ("atom" . "application/atom+xml") ("atomcat" . "application/atomcat+xml") ("atomsvc" . "application/atomsvc+xml") ("ccxml" . "application/ccxml+xml") ("cdmia" . "application/cdmi-capability") ("cdmic" . "application/cdmi-container") ("cdmid" . "application/cdmi-domain") ("cdmio" . "application/cdmi-object") ("cdmiq" . "application/cdmi-queue") ("cu" . "application/cu-seeme") ("davmount" . "application/davmount+xml") ("dbk" . "application/docbook+xml") ("dssc" . "application/dssc+der") ("xdssc" . "application/dssc+xml") ("ecma" . "application/ecmascript") ("emma" . "application/emma+xml") ("epub" . "application/epub+zip") ("exi" . "application/exi") ("pfr" . "application/font-tdpfr") ("gml" . "application/gml+xml") ("gpx" . "application/gpx+xml") ("gxf" . "application/gxf") ("stk" . "application/hyperstudio") ("ink" . "application/inkml+xml") ("ipfix" . "application/ipfix") ("jar" . "application/java-archive") ("ser" . "application/java-serialized-object") ("class" . "application/java-vm") ("js" . "application/javascript") ("json" . "application/json") ("jsonml" . "application/jsonml+json") ("lostxml" . "application/lost+xml") ("hqx" . "application/mac-binhex40") ("cpt" . "application/mac-compactpro") ("mads" . "application/mads+xml") ("mrc" . "application/marc") ("mrcx" . "application/marcxml+xml") ("ma" . "application/mathematica") ("mathml" . "application/mathml+xml") ("mbox" . "application/mbox") ("mscml" . "application/mediaservercontrol+xml") ("metalink" . "application/metalink+xml") ("meta4" . "application/metalink4+xml") ("mets" . "application/mets+xml") ("mods" . "application/mods+xml") ("m21" . "application/mp21") ("mp4s" . "application/mp4") ("doc" . "application/msword") ("mxf" . "application/mxf") ("bin" . "application/octet-stream") ("oda" . "application/oda") ("opf" . "application/oebps-package+xml") ("ogx" . "application/ogg") ("omdoc" . "application/omdoc+xml") ("onetoc" . "application/onenote") ("oxps" . "application/oxps") ("xer" . "application/patch-ops-error+xml") ("pdf" . "application/pdf") ("pgp" . "application/pgp-encrypted") ("asc" . "application/pgp-signature") ("prf" . "application/pics-rules") ("p10" . "application/pkcs10") ("p7m" . "application/pkcs7-mime") ("p7s" . "application/pkcs7-signature") ("p8" . "application/pkcs8") ("ac" . "application/pkix-attr-cert") ("cer" . "application/pkix-cert") ("crl" . "application/pkix-crl") ("pkipath" . "application/pkix-pkipath") ("pki" . "application/pkixcmp") ("pls" . "application/pls+xml") ("ai" . "application/postscript") ("cww" . "application/prs.cww") ("pskcxml" . "application/pskc+xml") ("rdf" . "application/rdf+xml") ("rif" . "application/reginfo+xml") ("rnc" . "application/relax-ng-compact-syntax") ("rl" . "application/resource-lists+xml") ("rld" . "application/resource-lists-diff+xml") ("rs" . "application/rls-services+xml") ("gbr" . "application/rpki-ghostbusters") ("mft" . "application/rpki-manifest") ("roa" . "application/rpki-roa") ("rsd" . "application/rsd+xml") ("rss" . "application/rss+xml") ("rtf" . "application/rtf") ("sbml" . "application/sbml+xml") ("scq" . "application/scvp-cv-request") ("scs" . "application/scvp-cv-response") ("spq" . "application/scvp-vp-request") ("spp" . "application/scvp-vp-response") ("sdp" . "application/sdp") ("setpay" . "application/set-payment-initiation") ("setreg" . "application/set-registration-initiation") ("shf" . "application/shf+xml") ("smi" . "application/smil+xml") ("rq" . "application/sparql-query") ("srx" . "application/sparql-results+xml") ("gram" . "application/srgs") ("grxml" . "application/srgs+xml") ("sru" . "application/sru+xml") ("ssdl" . "application/ssdl+xml") ("ssml" . "application/ssml+xml") ("tei" . "application/tei+xml") ("tfi" . "application/thraud+xml") ("tsd" . "application/timestamped-data") ("plb" . "application/vnd.3gpp.pic-bw-large") ("psb" . "application/vnd.3gpp.pic-bw-small") ("pvb" . "application/vnd.3gpp.pic-bw-var") ("tcap" . "application/vnd.3gpp2.tcap") ("pwn" . "application/vnd.3m.post-it-notes") ("aso" . "application/vnd.accpac.simply.aso") ("imp" . "application/vnd.accpac.simply.imp") ("acu" . "application/vnd.acucobol") ("atc" . "application/vnd.acucorp") ("air" . "application/vnd.adobe.air-application-installer-package+zip") ("fcdt" . "application/vnd.adobe.formscentral.fcdt") ("fxp" . "application/vnd.adobe.fxp") ("xdp" . "application/vnd.adobe.xdp+xml") ("xfdf" . "application/vnd.adobe.xfdf") ("ahead" . "application/vnd.ahead.space") ("azf" . "application/vnd.airzip.filesecure.azf") ("azs" . "application/vnd.airzip.filesecure.azs") ("azw" . "application/vnd.amazon.ebook") ("acc" . "application/vnd.americandynamics.acc") ("ami" . "application/vnd.amiga.ami") ("apk" . "application/vnd.android.package-archive") ("cii" . "application/vnd.anser-web-certificate-issue-initiation") ("fti" . "application/vnd.anser-web-funds-transfer-initiation") ("atx" . "application/vnd.antix.game-component") ("mpkg" . "application/vnd.apple.installer+xml") ("m3u8" . "application/vnd.apple.mpegurl") ("swi" . "application/vnd.aristanetworks.swi") ("iota" . "application/vnd.astraea-software.iota") ("aep" . "application/vnd.audiograph") ("mpm" . "application/vnd.blueice.multipass") ("bmi" . "application/vnd.bmi") ("rep" . "application/vnd.businessobjects") ("cdxml" . "application/vnd.chemdraw+xml") ("mmd" . "application/vnd.chipnuts.karaoke-mmd") ("cdy" . "application/vnd.cinderella") ("cla" . "application/vnd.claymore") ("rp9" . "application/vnd.cloanto.rp9") ("c4g" . "application/vnd.clonk.c4group") ("c11amc" . "application/vnd.cluetrust.cartomobile-config") ("c11amz" . "application/vnd.cluetrust.cartomobile-config-pkg") ("csp" . "application/vnd.commonspace") ("cdbcmsg" . "application/vnd.contact.cmsg") ("cmc" . "application/vnd.cosmocaller") ("clkx" . "application/vnd.crick.clicker") ("clkk" . "application/vnd.crick.clicker.keyboard") ("clkp" . "application/vnd.crick.clicker.palette") ("clkt" . "application/vnd.crick.clicker.template") ("clkw" . "application/vnd.crick.clicker.wordbank") ("wbs" . "application/vnd.criticaltools.wbs+xml") ("pml" . "application/vnd.ctc-posml") ("ppd" . "application/vnd.cups-ppd") ("car" . "application/vnd.curl.car") ("pcurl" . "application/vnd.curl.pcurl") ("dart" . "application/vnd.dart") ("rdz" . "application/vnd.data-vision.rdz") ("uvf" . "application/vnd.dece.data") ("uvt" . "application/vnd.dece.ttml+xml") ("uvx" . "application/vnd.dece.unspecified") ("uvz" . "application/vnd.dece.zip") ("fe_launch" . "application/vnd.denovo.fcselayout-link") ("dna" . "application/vnd.dna") ("mlp" . "application/vnd.dolby.mlp") ("dpg" . "application/vnd.dpgraph") ("dfac" . "application/vnd.dreamfactory") ("kpxx" . "application/vnd.ds-keypoint") ("ait" . "application/vnd.dvb.ait") ("svc" . "application/vnd.dvb.service") ("geo" . "application/vnd.dynageo") ("mag" . "application/vnd.ecowin.chart") ("nml" . "application/vnd.enliven") ("esf" . "application/vnd.epson.esf") ("msf" . "application/vnd.epson.msf") ("qam" . "application/vnd.epson.quickanime") ("slt" . "application/vnd.epson.salt") ("ssf" . "application/vnd.epson.ssf") ("es3" . "application/vnd.eszigno3+xml") ("ez2" . "application/vnd.ezpix-album") ("ez3" . "application/vnd.ezpix-package") ("fdf" . "application/vnd.fdf") ("mseed" . "application/vnd.fdsn.mseed") ("seed" . "application/vnd.fdsn.seed") ("gph" . "application/vnd.flographit") ("ftc" . "application/vnd.fluxtime.clip") ("fm" . "application/vnd.framemaker") ("fnc" . "application/vnd.frogans.fnc") ("ltf" . "application/vnd.frogans.ltf") ("fsc" . "application/vnd.fsc.weblaunch") ("oas" . "application/vnd.fujitsu.oasys") ("oa2" . "application/vnd.fujitsu.oasys2") ("oa3" . "application/vnd.fujitsu.oasys3") ("fg5" . "application/vnd.fujitsu.oasysgp") ("bh2" . "application/vnd.fujitsu.oasysprs") ("ddd" . "application/vnd.fujixerox.ddd") ("xdw" . "application/vnd.fujixerox.docuworks") ("xbd" . "application/vnd.fujixerox.docuworks.binder") ("fzs" . "application/vnd.fuzzysheet") ("txd" . "application/vnd.genomatix.tuxedo") ("ggb" . "application/vnd.geogebra.file") ("ggt" . "application/vnd.geogebra.tool") ("gex" . "application/vnd.geometry-explorer") ("gxt" . "application/vnd.geonext") ("g2w" . "application/vnd.geoplan") ("g3w" . "application/vnd.geospace") ("gmx" . "application/vnd.gmx") ("kml" . "application/vnd.google-earth.kml+xml") ("kmz" . "application/vnd.google-earth.kmz") ("gqf" . "application/vnd.grafeq") ("gac" . "application/vnd.groove-account") ("ghf" . "application/vnd.groove-help") ("gim" . "application/vnd.groove-identity-message") ("grv" . "application/vnd.groove-injector") ("gtm" . "application/vnd.groove-tool-message") ("tpl" . "application/vnd.groove-tool-template") ("vcg" . "application/vnd.groove-vcard") ("hal" . "application/vnd.hal+xml") ("zmm" . "application/vnd.handheld-entertainment+xml") ("hbci" . "application/vnd.hbci") ("les" . "application/vnd.hhe.lesson-player") ("hpgl" . "application/vnd.hp-hpgl") ("hpid" . "application/vnd.hp-hpid") ("hps" . "application/vnd.hp-hps") ("jlt" . "application/vnd.hp-jlyt") ("pcl" . "application/vnd.hp-pcl") ("pclxl" . "application/vnd.hp-pclxl") ("sfd-hdstx" . "application/vnd.hydrostatix.sof-data") ("mpy" . "application/vnd.ibm.minipay") ("afp" . "application/vnd.ibm.modcap") ("irm" . "application/vnd.ibm.rights-management") ("sc" . "application/vnd.ibm.secure-container") ("icc" . "application/vnd.iccprofile") ("igl" . "application/vnd.igloader") ("ivp" . "application/vnd.immervision-ivp") ("ivu" . "application/vnd.immervision-ivu") ("igm" . "application/vnd.insors.igm") ("xpw" . "application/vnd.intercon.formnet") ("i2g" . "application/vnd.intergeo") ("qbo" . "application/vnd.intu.qbo") ("qfx" . "application/vnd.intu.qfx") ("rcprofile" . "application/vnd.ipunplugged.rcprofile") ("irp" . "application/vnd.irepository.package+xml") ("xpr" . "application/vnd.is-xpr") ("fcs" . "application/vnd.isac.fcs") ("jam" . "application/vnd.jam") ("rms" . "application/vnd.jcp.javame.midlet-rms") ("jisp" . "application/vnd.jisp") ("joda" . "application/vnd.joost.joda-archive") ("ktz" . "application/vnd.kahootz") ("karbon" . "application/vnd.kde.karbon") ("chrt" . "application/vnd.kde.kchart") ("kfo" . "application/vnd.kde.kformula") ("flw" . "application/vnd.kde.kivio") ("kon" . "application/vnd.kde.kontour") ("kpr" . "application/vnd.kde.kpresenter") ("ksp" . "application/vnd.kde.kspread") ("kwd" . "application/vnd.kde.kword") ("htke" . "application/vnd.kenameaapp") ("kia" . "application/vnd.kidspiration") ("kne" . "application/vnd.kinar") ("skp" . "application/vnd.koan") ("sse" . "application/vnd.kodak-descriptor") ("lasxml" . "application/vnd.las.las+xml") ("lbd" . "application/vnd.llamagraphics.life-balance.desktop") ("lbe" . "application/vnd.llamagraphics.life-balance.exchange+xml") ("123" . "application/vnd.lotus-1-2-3") ("apr" . "application/vnd.lotus-approach") ("pre" . "application/vnd.lotus-freelance") ("nsf" . "application/vnd.lotus-notes") ("org" . "application/vnd.lotus-organizer") ("scm" . "application/vnd.lotus-screencam") ("lwp" . "application/vnd.lotus-wordpro") ("portpkg" . "application/vnd.macports.portpkg") ("mcd" . "application/vnd.mcd") ("mc1" . "application/vnd.medcalcdata") ("cdkey" . "application/vnd.mediastation.cdkey") ("mwf" . "application/vnd.mfer") ("mfm" . "application/vnd.mfmp") ("flo" . "application/vnd.micrografx.flo") ("igx" . "application/vnd.micrografx.igx") ("mif" . "application/vnd.mif") ("daf" . "application/vnd.mobius.daf") ("dis" . "application/vnd.mobius.dis") ("mbk" . "application/vnd.mobius.mbk") ("mqy" . "application/vnd.mobius.mqy") ("msl" . "application/vnd.mobius.msl") ("plc" . "application/vnd.mobius.plc") ("txf" . "application/vnd.mobius.txf") ("mpn" . "application/vnd.mophun.application") ("mpc" . "application/vnd.mophun.certificate") ("xul" . "application/vnd.mozilla.xul+xml") ("cil" . "application/vnd.ms-artgalry") ("cab" . "application/vnd.ms-cab-compressed") ("xls" . "application/vnd.ms-excel") ("xlam" . "application/vnd.ms-excel.addin.macroenabled.12") ("xlsb" . "application/vnd.ms-excel.sheet.binary.macroenabled.12") ("xlsm" . "application/vnd.ms-excel.sheet.macroenabled.12") ("xltm" . "application/vnd.ms-excel.template.macroenabled.12") ("eot" . "application/vnd.ms-fontobject") ("chm" . "application/vnd.ms-htmlhelp") ("ims" . "application/vnd.ms-ims") ("lrm" . "application/vnd.ms-lrm") ("thmx" . "application/vnd.ms-officetheme") ("cat" . "application/vnd.ms-pki.seccat") ("stl" . "application/vnd.ms-pki.stl") ("ppt" . "application/vnd.ms-powerpoint") ("ppam" . "application/vnd.ms-powerpoint.addin.macroenabled.12") ("pptm" . "application/vnd.ms-powerpoint.presentation.macroenabled.12") ("sldm" . "application/vnd.ms-powerpoint.slide.macroenabled.12") ("ppsm" . "application/vnd.ms-powerpoint.slideshow.macroenabled.12") ("potm" . "application/vnd.ms-powerpoint.template.macroenabled.12") ("mpp" . "application/vnd.ms-project") ("docm" . "application/vnd.ms-word.document.macroenabled.12") ("dotm" . "application/vnd.ms-word.template.macroenabled.12") ("wps" . "application/vnd.ms-works") ("wpl" . "application/vnd.ms-wpl") ("xps" . "application/vnd.ms-xpsdocument") ("mseq" . "application/vnd.mseq") ("mus" . "application/vnd.musician") ("msty" . "application/vnd.muvee.style") ("taglet" . "application/vnd.mynfc") ("nlu" . "application/vnd.neurolanguage.nlu") ("ntf" . "application/vnd.nitf") ("nnd" . "application/vnd.noblenet-directory") ("nns" . "application/vnd.noblenet-sealer") ("nnw" . "application/vnd.noblenet-web") ("ngdat" . "application/vnd.nokia.n-gage.data") ("n-gage" . "application/vnd.nokia.n-gage.symbian.install") ("rpst" . "application/vnd.nokia.radio-preset") ("rpss" . "application/vnd.nokia.radio-presets") ("edm" . "application/vnd.novadigm.edm") ("edx" . "application/vnd.novadigm.edx") ("ext" . "application/vnd.novadigm.ext") ("odc" . "application/vnd.oasis.opendocument.chart") ("otc" . "application/vnd.oasis.opendocument.chart-template") ("odb" . "application/vnd.oasis.opendocument.database") ("odf" . "application/vnd.oasis.opendocument.formula") ("odft" . "application/vnd.oasis.opendocument.formula-template") ("odg" . "application/vnd.oasis.opendocument.graphics") ("otg" . "application/vnd.oasis.opendocument.graphics-template") ("odi" . "application/vnd.oasis.opendocument.image") ("oti" . "application/vnd.oasis.opendocument.image-template") ("odp" . "application/vnd.oasis.opendocument.presentation") ("otp" . "application/vnd.oasis.opendocument.presentation-template") ("ods" . "application/vnd.oasis.opendocument.spreadsheet") ("ots" . "application/vnd.oasis.opendocument.spreadsheet-template") ("odt" . "application/vnd.oasis.opendocument.text") ("odm" . "application/vnd.oasis.opendocument.text-master") ("ott" . "application/vnd.oasis.opendocument.text-template") ("oth" . "application/vnd.oasis.opendocument.text-web") ("xo" . "application/vnd.olpc-sugar") ("dd2" . "application/vnd.oma.dd2+xml") ("oxt" . "application/vnd.openofficeorg.extension") ("pptx" . "application/vnd.openxmlformats-officedocument.presentationml.presentation") ("sldx" . "application/vnd.openxmlformats-officedocument.presentationml.slide") ("ppsx" . "application/vnd.openxmlformats-officedocument.presentationml.slideshow") ("potx" . "application/vnd.openxmlformats-officedocument.presentationml.template") ("xlsx" . "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") ("xltx" . "application/vnd.openxmlformats-officedocument.spreadsheetml.template") ("docx" . "application/vnd.openxmlformats-officedocument.wordprocessingml.document") ("dotx" . "application/vnd.openxmlformats-officedocument.wordprocessingml.template") ("mgp" . "application/vnd.osgeo.mapguide.package") ("dp" . "application/vnd.osgi.dp") ("esa" . "application/vnd.osgi.subsystem") ("pdb" . "application/vnd.palm") ("paw" . "application/vnd.pawaafile") ("str" . "application/vnd.pg.format") ("ei6" . "application/vnd.pg.osasli") ("efif" . "application/vnd.picsel") ("wg" . "application/vnd.pmi.widget") ("plf" . "application/vnd.pocketlearn") ("pbd" . "application/vnd.powerbuilder6") ("box" . "application/vnd.previewsystems.box") ("mgz" . "application/vnd.proteus.magazine") ("qps" . "application/vnd.publishare-delta-tree") ("ptid" . "application/vnd.pvi.ptid1") ("qxd" . "application/vnd.quark.quarkxpress") ("bed" . "application/vnd.realvnc.bed") ("mxl" . "application/vnd.recordare.musicxml") ("musicxml" . "application/vnd.recordare.musicxml+xml") ("cryptonote" . "application/vnd.rig.cryptonote") ("cod" . "application/vnd.rim.cod") ("rm" . "application/vnd.rn-realmedia") ("rmvb" . "application/vnd.rn-realmedia-vbr") ("link66" . "application/vnd.route66.link66+xml") ("st" . "application/vnd.sailingtracker.track") ("see" . "application/vnd.seemail") ("sema" . "application/vnd.sema") ("semd" . "application/vnd.semd") ("semf" . "application/vnd.semf") ("ifm" . "application/vnd.shana.informed.formdata") ("itp" . "application/vnd.shana.informed.formtemplate") ("iif" . "application/vnd.shana.informed.interchange") ("ipk" . "application/vnd.shana.informed.package") ("twd" . "application/vnd.simtech-mindmapper") ("mmf" . "application/vnd.smaf") ("teacher" . "application/vnd.smart.teacher") ("sdkm" . "application/vnd.solent.sdkm+xml") ("dxp" . "application/vnd.spotfire.dxp") ("sfs" . "application/vnd.spotfire.sfs") ("sdc" . "application/vnd.stardivision.calc") ("sda" . "application/vnd.stardivision.draw") ("sdd" . "application/vnd.stardivision.impress") ("smf" . "application/vnd.stardivision.math") ("sdw" . "application/vnd.stardivision.writer") ("sgl" . "application/vnd.stardivision.writer-global") ("smzip" . "application/vnd.stepmania.package") ("sm" . "application/vnd.stepmania.stepchart") ("sxc" . "application/vnd.sun.xml.calc") ("stc" . "application/vnd.sun.xml.calc.template") ("sxd" . "application/vnd.sun.xml.draw") ("std" . "application/vnd.sun.xml.draw.template") ("sxi" . "application/vnd.sun.xml.impress") ("sti" . "application/vnd.sun.xml.impress.template") ("sxm" . "application/vnd.sun.xml.math") ("sxw" . "application/vnd.sun.xml.writer") ("sxg" . "application/vnd.sun.xml.writer.global") ("stw" . "application/vnd.sun.xml.writer.template") ("sus" . "application/vnd.sus-calendar") ("svd" . "application/vnd.svd") ("sis" . "application/vnd.symbian.install") ("xsm" . "application/vnd.syncml+xml") ("bdm" . "application/vnd.syncml.dm+wbxml") ("xdm" . "application/vnd.syncml.dm+xml") ("tao" . "application/vnd.tao.intent-module-archive") ("pcap" . "application/vnd.tcpdump.pcap") ("tmo" . "application/vnd.tmobile-livetv") ("tpt" . "application/vnd.trid.tpt") ("mxs" . "application/vnd.triscape.mxs") ("tra" . "application/vnd.trueapp") ("ufd" . "application/vnd.ufdl") ("utz" . "application/vnd.uiq.theme") ("umj" . "application/vnd.umajin") ("unityweb" . "application/vnd.unity") ("uoml" . "application/vnd.uoml+xml") ("vcx" . "application/vnd.vcx") ("vsd" . "application/vnd.visio") ("vis" . "application/vnd.visionary") ("vsf" . "application/vnd.vsf") ("wbxml" . "application/vnd.wap.wbxml") ("wmlc" . "application/vnd.wap.wmlc") ("wmlsc" . "application/vnd.wap.wmlscriptc") ("wtb" . "application/vnd.webturbo") ("nbp" . "application/vnd.wolfram.player") ("wpd" . "application/vnd.wordperfect") ("wqd" . "application/vnd.wqd") ("stf" . "application/vnd.wt.stf") ("xar" . "application/vnd.xara") ("xfdl" . "application/vnd.xfdl") ("hvd" . "application/vnd.yamaha.hv-dic") ("hvs" . "application/vnd.yamaha.hv-script") ("hvp" . "application/vnd.yamaha.hv-voice") ("osf" . "application/vnd.yamaha.openscoreformat") ("osfpvg" . "application/vnd.yamaha.openscoreformat.osfpvg+xml") ("saf" . "application/vnd.yamaha.smaf-audio") ("spf" . "application/vnd.yamaha.smaf-phrase") ("cmp" . "application/vnd.yellowriver-custom-menu") ("zir" . "application/vnd.zul") ("zaz" . "application/vnd.zzazz.deck+xml") ("vxml" . "application/voicexml+xml") ("wgt" . "application/widget") ("hlp" . "application/winhlp") ("wsdl" . "application/wsdl+xml") ("wspolicy" . "application/wspolicy+xml") ("7z" . "application/x-7z-compressed") ("abw" . "application/x-abiword") ("ace" . "application/x-ace-compressed") ("dmg" . "application/x-apple-diskimage") ("aab" . "application/x-authorware-bin") ("aam" . "application/x-authorware-map") ("aas" . "application/x-authorware-seg") ("bcpio" . "application/x-bcpio") ("torrent" . "application/x-bittorrent") ("blb" . "application/x-blorb") ("bz" . "application/x-bzip") ("bz2" . "application/x-bzip2") ("cbr" . "application/x-cbr") ("vcd" . "application/x-cdlink") ("cfs" . "application/x-cfs-compressed") ("chat" . "application/x-chat") ("pgn" . "application/x-chess-pgn") ("nsc" . "application/x-conference") ("cpio" . "application/x-cpio") ("csh" . "application/x-csh") ("deb" . "application/x-debian-package") ("dgc" . "application/x-dgc-compressed") ("dir" . "application/x-director") ("wad" . "application/x-doom") ("ncx" . "application/x-dtbncx+xml") ("dtb" . "application/x-dtbook+xml") ("res" . "application/x-dtbresource+xml") ("dvi" . "application/x-dvi") ("evy" . "application/x-envoy") ("eva" . "application/x-eva") ("bdf" . "application/x-font-bdf") ("gsf" . "application/x-font-ghostscript") ("psf" . "application/x-font-linux-psf") ("otf" . "application/x-font-otf") ("pcf" . "application/x-font-pcf") ("snf" . "application/x-font-snf") ("ttf" . "application/x-font-ttf") ("pfa" . "application/x-font-type1") ("woff" . "application/x-font-woff") ("arc" . "application/x-freearc") ("spl" . "application/x-futuresplash") ("gca" . "application/x-gca-compressed") ("ulx" . "application/x-glulx") ("gnumeric" . "application/x-gnumeric") ("gramps" . "application/x-gramps-xml") ("gtar" . "application/x-gtar") ("hdf" . "application/x-hdf") ("install" . "application/x-install-instructions") ("iso" . "application/x-iso9660-image") ("jnlp" . "application/x-java-jnlp-file") ("latex" . "application/x-latex") ("lzh" . "application/x-lzh-compressed") ("mie" . "application/x-mie") ("prc" . "application/x-mobipocket-ebook") ("m3u8" . "application/x-mpegurl") ("application" . "application/x-ms-application") ("lnk" . "application/x-ms-shortcut") ("wmd" . "application/x-ms-wmd") ("wmz" . "application/x-ms-wmz") ("xbap" . "application/x-ms-xbap") ("mdb" . "application/x-msaccess") ("obd" . "application/x-msbinder") ("crd" . "application/x-mscardfile") ("clp" . "application/x-msclip") ("exe" . "application/x-msdownload") ("mvb" . "application/x-msmediaview") ("wmf" . "application/x-msmetafile") ("mny" . "application/x-msmoney") ("pub" . "application/x-mspublisher") ("scd" . "application/x-msschedule") ("trm" . "application/x-msterminal") ("wri" . "application/x-mswrite") ("nc" . "application/x-netcdf") ("nzb" . "application/x-nzb") ("p12" . "application/x-pkcs12") ("p7b" . "application/x-pkcs7-certificates") ("p7r" . "application/x-pkcs7-certreqresp") ("rar" . "application/x-rar-compressed") ("ris" . "application/x-research-info-systems") ("sh" . "application/x-sh") ("shar" . "application/x-shar") ("swf" . "application/x-shockwave-flash") ("xap" . "application/x-silverlight-app") ("sql" . "application/x-sql") ("sit" . "application/x-stuffit") ("sitx" . "application/x-stuffitx") ("srt" . "application/x-subrip") ("sv4cpio" . "application/x-sv4cpio") ("sv4crc" . "application/x-sv4crc") ("t3" . "application/x-t3vm-image") ("gam" . "application/x-tads") ("tar" . "application/x-tar") ("tcl" . "application/x-tcl") ("tex" . "application/x-tex") ("tfm" . "application/x-tex-tfm") ("texinfo" . "application/x-texinfo") ("obj" . "application/x-tgif") ("ustar" . "application/x-ustar") ("src" . "application/x-wais-source") ("der" . "application/x-x509-ca-cert") ("fig" . "application/x-xfig") ("xlf" . "application/x-xliff+xml") ("xpi" . "application/x-xpinstall") ("xz" . "application/x-xz") ("z1" . "application/x-zmachine") ("xaml" . "application/xaml+xml") ("xdf" . "application/xcap-diff+xml") ("xenc" . "application/xenc+xml") ("xhtml" . "application/xhtml+xml") ("xml" . "application/xml") ("dtd" . "application/xml-dtd") ("xop" . "application/xop+xml") ("xpl" . "application/xproc+xml") ("xslt" . "application/xslt+xml") ("xspf" . "application/xspf+xml") ("mxml" . "application/xv+xml") ("yang" . "application/yang") ("yin" . "application/yin+xml") ("zip" . "application/zip") ("adp" . "audio/adpcm") ("au" . "audio/basic") ("mid" . "audio/midi") ("mp4a" . "audio/mp4") ("m4a" . "audio/mp4a-latm") ("mpga" . "audio/mpeg") ("oga" . "audio/ogg") ("s3m" . "audio/s3m") ("sil" . "audio/silk") ("uva" . "audio/vnd.dece.audio") ("eol" . "audio/vnd.digital-winds") ("dra" . "audio/vnd.dra") ("dts" . "audio/vnd.dts") ("dtshd" . "audio/vnd.dts.hd") ("lvp" . "audio/vnd.lucent.voice") ("pya" . "audio/vnd.ms-playready.media.pya") ("ecelp4800" . "audio/vnd.nuera.ecelp4800") ("ecelp7470" . "audio/vnd.nuera.ecelp7470") ("ecelp9600" . "audio/vnd.nuera.ecelp9600") ("rip" . "audio/vnd.rip") ("weba" . "audio/webm") ("aac" . "audio/x-aac") ("aif" . "audio/x-aiff") ("caf" . "audio/x-caf") ("flac" . "audio/x-flac") ("mka" . "audio/x-matroska") ("m3u" . "audio/x-mpegurl") ("wax" . "audio/x-ms-wax") ("wma" . "audio/x-ms-wma") ("ram" . "audio/x-pn-realaudio") ("rmp" . "audio/x-pn-realaudio-plugin") ("wav" . "audio/x-wav") ("xm" . "audio/xm") ("cdx" . "chemical/x-cdx") ("cif" . "chemical/x-cif") ("cmdf" . "chemical/x-cmdf") ("cml" . "chemical/x-cml") ("csml" . "chemical/x-csml") ("xyz" . "chemical/x-xyz") ("bmp" . "image/bmp") ("cgm" . "image/cgm") ("g3" . "image/g3fax") ("gif" . "image/gif") ("ief" . "image/ief") ("jp2" . "image/jp2") ("jpeg" . "image/jpeg") ("ktx" . "image/ktx") ("pict" . "image/pict") ("png" . "image/png") ("btif" . "image/prs.btif") ("sgi" . "image/sgi") ("svg" . "image/svg+xml") ("tiff" . "image/tiff") ("psd" . "image/vnd.adobe.photoshop") ("uvi" . "image/vnd.dece.graphic") ("sub" . "image/vnd.dvb.subtitle") ("djvu" . "image/vnd.djvu") ("dwg" . "image/vnd.dwg") ("dxf" . "image/vnd.dxf") ("fbs" . "image/vnd.fastbidsheet") ("fpx" . "image/vnd.fpx") ("fst" . "image/vnd.fst") ("mmr" . "image/vnd.fujixerox.edmics-mmr") ("rlc" . "image/vnd.fujixerox.edmics-rlc") ("mdi" . "image/vnd.ms-modi") ("wdp" . "image/vnd.ms-photo") ("npx" . "image/vnd.net-fpx") ("wbmp" . "image/vnd.wap.wbmp") ("xif" . "image/vnd.xiff") ("webp" . "image/webp") ("3ds" . "image/x-3ds") ("ras" . "image/x-cmu-raster") ("cmx" . "image/x-cmx") ("fh" . "image/x-freehand") ("ico" . "image/x-icon") ("pntg" . "image/x-macpaint") ("sid" . "image/x-mrsid-image") ("pcx" . "image/x-pcx") ("pic" . "image/x-pict") ("pnm" . "image/x-portable-anymap") ("pbm" . "image/x-portable-bitmap") ("pgm" . "image/x-portable-graymap") ("ppm" . "image/x-portable-pixmap") ("qtif" . "image/x-quicktime") ("rgb" . "image/x-rgb") ("tga" . "image/x-tga") ("xbm" . "image/x-xbitmap") ("xpm" . "image/x-xpixmap") ("xwd" . "image/x-xwindowdump") ("eml" . "message/rfc822") ("igs" . "model/iges") ("msh" . "model/mesh") ("dae" . "model/vnd.collada+xml") ("dwf" . "model/vnd.dwf") ("gdl" . "model/vnd.gdl") ("gtw" . "model/vnd.gtw") ("mts" . "model/vnd.mts") ("vtu" . "model/vnd.vtu") ("wrl" . "model/vrml") ("x3db" . "model/x3d+binary") ("x3dv" . "model/x3d+vrml") ("x3d" . "model/x3d+xml") ("manifest" . "text/cache-manifest") ("appcache" . "text/cache-manifest") ("ics" . "text/calendar") ("css" . "text/css") ("csv" . "text/csv") ("html" . "text/html") ("n3" . "text/n3") ("txt" . "text/plain") ("dsc" . "text/prs.lines.tag") ("rtx" . "text/richtext") ("sgml" . "text/sgml") ("tsv" . "text/tab-separated-values") ("t" . "text/troff") ("ttl" . "text/turtle") ("uri" . "text/uri-list") ("vcard" . "text/vcard") ("curl" . "text/vnd.curl") ("dcurl" . "text/vnd.curl.dcurl") ("scurl" . "text/vnd.curl.scurl") ("mcurl" . "text/vnd.curl.mcurl") ("sub" . "text/vnd.dvb.subtitle") ("fly" . "text/vnd.fly") ("flx" . "text/vnd.fmi.flexstor") ("gv" . "text/vnd.graphviz") ("3dml" . "text/vnd.in3d.3dml") ("spot" . "text/vnd.in3d.spot") ("jad" . "text/vnd.sun.j2me.app-descriptor") ("wml" . "text/vnd.wap.wml") ("wmls" . "text/vnd.wap.wmlscript") ("s" . "text/x-asm") ("c" . "text/x-c") ("f" . "text/x-fortran") ("java" . "text/x-java-source") ("opml" . "text/x-opml") ("p" . "text/x-pascal") ("nfo" . "text/x-nfo") ("etx" . "text/x-setext") ("sfv" . "text/x-sfv") ("uu" . "text/x-uuencode") ("vcs" . "text/x-vcalendar") ("vcf" . "text/x-vcard") ("3gp" . "video/3gpp") ("3g2" . "video/3gpp2") ("h261" . "video/h261") ("h263" . "video/h263") ("h264" . "video/h264") ("jpgv" . "video/jpeg") ("jpm" . "video/jpm") ("mj2" . "video/mj2") ("ts" . "video/mp2t") ("mp4" . "video/mp4") ("mpeg" . "video/mpeg") ("ogv" . "video/ogg") ("qt" . "video/quicktime") ("uvh" . "video/vnd.dece.hd") ("uvm" . "video/vnd.dece.mobile") ("uvp" . "video/vnd.dece.pd") ("uvs" . "video/vnd.dece.sd") ("uvv" . "video/vnd.dece.video") ("dvb" . "video/vnd.dvb.file") ("fvt" . "video/vnd.fvt") ("mxu" . "video/vnd.mpegurl") ("pyv" . "video/vnd.ms-playready.media.pyv") ("uvu" . "video/vnd.uvvu.mp4") ("viv" . "video/vnd.vivo") ("dv" . "video/x-dv") ("webm" . "video/webm") ("f4v" . "video/x-f4v") ("fli" . "video/x-fli") ("flv" . "video/x-flv") ("m4v" . "video/x-m4v") ("mkv" . "video/x-matroska") ("mng" . "video/x-mng") ("asf" . "video/x-ms-asf") ("vob" . "video/x-ms-vob") ("wm" . "video/x-ms-wm") ("wmv" . "video/x-ms-wmv") ("wmx" . "video/x-ms-wmx") ("wvx" . "video/x-ms-wvx") ("avi" . "video/x-msvideo") ("movie" . "video/x-sgi-movie") ("smv" . "video/x-smv") ("ice" . "x-conference/x-cooltalk"))) (use srfi-19) (use test) ;;(use format) (use regex) ;(declare (unit wwdate)) ;; utility procedures to convert among ;; different ways to express date (wwdate, seconds since epoch, isodate) ;; ;; samples: ;; isodate -> "2016-01-01" ;; wwdate -> "16ww01.5" ;; seconds -> 1451631600 ;; procedures provided: ;; ==================== ;; seconds->isodate ;; seconds->wwdate ;; ;; isodate->seconds ;; isodate->wwdate ;; ;; wwdate->seconds ;; wwdate->isodate ;; srfi-19 used extensively; this doc is better tha the eggref: ;; http://srfi.schemers.org/srfi-19/srfi-19.html ;; Author: brandon.j.barclay@intel.com 16ww18.6 (define (date->seconds date) (inexact->exact (string->number (date->string date "~s")))) (define (seconds->isodate seconds) (let* ((date (seconds->date seconds)) (result (date->string date "~Y-~m-~d"))) result)) (define (isodate->seconds isodate) "Takes a string input of the form 'YY-MM-DD' or 'YYYY-MM-DD' and returns epoch time; for YY, assume after Y2K" (let* ((numlist (map string->number (string-split isodate "-"))) (raw-year (car numlist)) (year (if (< raw-year 100) (+ raw-year 2000) raw-year)) (month (list-ref numlist 1)) (day (list-ref numlist 2)) (date (make-date 0 0 0 0 day month year)) (seconds (date->seconds date))) seconds)) ;; adapted from perl Intel::WorkWeek perl module ;; workweek year consists of numbered weeks starting from week 1 ;; days of week are numbered starting from 0 on sunday ;; weeks begin on sunday- day number 0 and end saturday- day 6 ;; week 1 is defined as the week containing jan 1 of the year ;; workweek year does not match calendar year in workweek 1 ;; since workweek 1 contains jan1 and workweek begins sunday, ;; days prior to jan1 in workweek 1 belong to the next workweek year (define (seconds->wwdate-values seconds) (define (date-difference->seconds d1 d2) (- (date->seconds d1) (date->seconds d2))) (let* ((thisdate (seconds->date seconds)) (thisdow (string->number (date->string thisdate "~w"))) (year (date-year thisdate)) ;; intel workweek 1 begins on sunday of week containing jan1 (jan1 (make-date 0 0 0 0 1 1 year)) (jan1dow (date-week-day jan1)) (ww01 (date-subtract-duration jan1 (seconds->time (* 60 60 24 jan1dow)))) (ww01_delta_seconds (date-difference->seconds thisdate ww01)) (wwnum_initial (inexact->exact (add1 (floor (/ ww01_delta_seconds 24 3600 7) )))) ;; we could be in ww1 of next year (this-saturday (seconds->date (+ seconds (* 60 60 24 (- 6 thisdow))))) (this-week-ends-next-year? (> (date-year this-saturday) year)) (intelyear (if this-week-ends-next-year? (add1 year) year)) (intelweek (if this-week-ends-next-year? 1 wwnum_initial))) (values intelyear intelweek thisdow))) (define (string-leftpad in width pad-char) (let* ((unpadded-str (->string in)) (padlen_temp (- width (string-length unpadded-str))) (padlen (if (< padlen_temp 0) 0 padlen_temp)) (padding (make-string padlen pad-char))) (conc padding unpadded-str))) (define (string-rightpad in width pad-char) (let* ((unpadded-str (->string in)) (padlen_temp (- width (string-length unpadded-str))) (padlen (if (< padlen_temp 0) 0 padlen_temp)) (padding (make-string padlen pad-char))) (conc unpadded-str padding))) (define (zeropad num width) (string-leftpad num width #\0)) (define (seconds->wwdate seconds) (let-values (((intelyear intelweek day-of-week-num) (seconds->wwdate-values seconds))) (let ((intelyear-str (zeropad (->string (if (> intelyear 1999) (- intelyear 2000) intelyear)) 2)) (intelweek-str (zeropad (->string intelweek) 2)) (dow-str (->string day-of-week-num))) (conc intelyear-str "ww" intelweek-str "." dow-str)))) (define (isodate->wwdate isodate) (seconds->wwdate (isodate->seconds isodate))) (define (wwdate->seconds wwdate) (let ((match (string-match "^(\\d+)ww(\\d+).(\\d)$" wwdate))) (if (not match) #f (let* ( (intelyear-raw (string->number (list-ref match 1))) (intelyear (if (< intelyear-raw 100) (+ intelyear-raw 2000) intelyear-raw)) (intelww (string->number (list-ref match 2))) (dayofweek (string->number (list-ref match 3))) (day-of-seconds (* 60 60 24 )) (week-of-seconds (* day-of-seconds 7)) ;; get seconds at ww1.0 (new-years-date (make-date 0 0 0 0 1 1 intelyear)) (new-years-seconds (date->seconds new-years-date)) (new-years-dayofweek (date-week-day new-years-date)) (ww1.0_seconds (- new-years-seconds (* day-of-seconds new-years-dayofweek))) (workweek-adjustment (* week-of-seconds (sub1 intelww))) (weekday-adjustment (* dayofweek day-of-seconds)) (result (+ ww1.0_seconds workweek-adjustment weekday-adjustment))) result)))) (define (wwdate->isodate wwdate) (seconds->isodate (wwdate->seconds wwdate))) (define (current-wwdate) (seconds->wwdate (current-seconds))) (define (current-isodate) (seconds->isodate (current-seconds))) (define (wwdate-tests) (test-group "date conversion tests" (let ((test-table '(("16ww01.5" . "2016-01-01") ("16ww18.5" . "2016-04-29") ("1999ww33.5" . "1999-08-13") ("16ww18.4" . "2016-04-28") ("16ww18.3" . "2016-04-27") ("13ww01.0" . "2012-12-30") ("13ww52.6" . "2013-12-28") ("16ww53.3" . "2016-12-28")))) (for-each (lambda (test-pair) (let ((wwdate (car test-pair)) (isodate (cdr test-pair))) (test (conc "(isodate->wwdate "isodate ") => "wwdate) wwdate (isodate->wwdate isodate)) (test (conc "(wwdate->isodate "wwdate ") => "isodate) isodate (wwdate->isodate wwdate)))) test-table)))) (define (ext->mimetype ext) (let ((x (assoc ext ducttape_ext2mimetype))) (if x (cdr x) "text/plain"))) (define ducttape-lib-version 1.00) (define (toplevel-command sym proc) (lambda () #f)) ;; like shell "which" command (define (find-exe exe) (let* ((path-items (string-split (or (get-environment-variable "PATH") "") ":"))) (let loop ((rest-path-items path-items)) (if (null? rest-path-items) #f (let* ((this-dir (car rest-path-items)) (next-rest (cdr rest-path-items)) (candidate (conc this-dir "/" exe))) (if (file-execute-access? candidate) candidate (loop next-rest))))))) ;;;; define some handy globals ;; resolve fullpath to this script or binary. (define (__get-this-script-fullpath #!key (argv (argv))) (let* ((this-script (cond ((and (> (length argv) 2) (string-match "^(.*/csi|csi)$" (car argv)) (string-match "^-(s|ss|sx|script)$" (cadr argv))) (caddr argv)) (else (car argv)))) ;;(foo (begin (print "hello "(find-exe "/bin/sh") #f))) (fullpath (or (find-exe this-script) (realpath this-script)))) fullpath)) (define *this-exe-fullpath* (__get-this-script-fullpath)) (define *this-exe-dir* (pathname-directory *this-exe-fullpath*)) (define *this-exe-name* (pathname-strip-directory *this-exe-fullpath*)) ;;;; utility procedures ;; begin credit: megatest's process.scm (define (port->list fh ) (if (eof-object? fh) #f (let loop ((curr (read-line fh)) (result '())) (if (not (eof-object? curr)) (loop (read-line fh) (append result (list curr))) result)))) (define (conservative-read port) (let loop ((res "")) (if (not (eof-object? (peek-char port))) (loop (conc res (read-char port))) res))) ;; end credit: megatest's process.scm (define (counter-maker) (let ((acc 0)) (lambda ( #!optional (increment 1) ) (set! acc (+ increment acc)) acc))) (define (port->string port #!optional ) ; todo - add newline (let ((linelist (port->list port))) (if linelist (string-join linelist "\n") ""))) (define (outport->foreach outport foreach-thunk) (let loop ((line (foreach-thunk))) (if line (begin (write-line line outport) (loop (foreach-thunk)) ) (begin ;;http://bugs.call-cc.org/ticket/766 ;;close-[input|output]-port implicitly calling process-wait on process pipe ports. This leads to errors like ;;Error: (process-wait) waiting for child process failed - No child processes: 10872 (close-output-port outport) #f)))) ;; weird - alist-ref arg order changes signature csc vs. csi... explitly defining. (define (my-alist-ref key alist) (let ((res (assoc key alist))) (if res (cdr res) #f))) (define (keyword-skim-alist args alist) (let loop ((result-alist '()) (result-args args) (rest-alist alist)) (cond ((null? rest-alist) (values result-alist result-args)) (else (let ((keyword (caar rest-alist)) (defval (cdar rest-alist))) (let-values (((kwval result-args2) (keyword-skim keyword defval result-args))) (loop (cons (cons keyword kwval) result-alist) result-args2 (cdr rest-alist)))))))) (define (isys command . rest-args) (let-values (((opt-alist args) (keyword-skim-alist rest-args '( ( foreach-stdout-thunk: . #f ) ( foreach-stdin-thunk: . #f ) ( stdin-proc: . #f ) ) ))) (let* ((foreach-stdout-thunk (my-alist-ref foreach-stdout-thunk: opt-alist)) (foreach-stdin-thunk (my-alist-ref foreach-stdin-thunk: opt-alist)) (stdin-proc (if foreach-stdin-thunk (lambda (port) (outport->foreach port foreach-stdin-thunk)) (my-alist-ref stdin-proc: opt-alist)))) ;; TODO: support command is list. (let-values (((stdout stdin pid stderr) (if (null? args) (process* command) (process* command args)))) ;(if foreach-stdin-thunk ; (set! stdin-proc ; (lambda (port) ; (outport->foreach port foreach-stdin-thunk)))) (if stdin-proc (stdin-proc stdin)) (let ((stdout-res (if foreach-stdout-thunk ;; don't accumulate stdout if we have a thunk; probably doing this because stdout is BIG so lets not waste memory (begin (port-for-each foreach-stdout-thunk (lambda () (read-line stdout))) "foreach-stdout-thunk ate stdout" ) (if stdin-proc "foreach-stdin-thunk/stdin-proc blocks stdout" (port->string stdout)))) (stderr-res (if stdin-proc "foreach-stdin-thunk/stdin-proc blocks stdout" (port->string stderr)))) ;; if we've used a stdin-proc, we've closed stdin port, which unfortunately causes a wait-pid internally, causing stdout and stderr ports to auto-close. don't close them again. (so sad - we lost stdout and stderr contents when we write to stdin) ;; see - http://bugs.call-cc.org/ticket/766 (if (not stdin-proc) (close-input-port stdout) (close-input-port stderr)) (let-values (((anotherpid normalexit? exitstatus) (process-wait pid))) (values exitstatus stdout-res stderr-res))))))) (define (do-or-die command #!key nodie (foreach-stdout #f) (stdin-proc #f)) (let-values (((exit-code stdout-str stderr-str) (isys command foreach-stdout-thunk: foreach-stdout stdin-proc: stdin-proc ))) (if (equal? 0 exit-code) stdout-str (begin (ierr (conc "Command > " command " " "< failed with " exit-code " because: \n" stderr-str) ) (if nodie #f (exit exit-code)))))) ;; runs-ok: evaluate expression while suppressing exceptions. ; on caught exception, returns #f ; otherwise, returns expression value (define (runs-ok thunk) (handle-exceptions exn #f (begin (thunk) #t))) ;; concat-lists: result list = lista + listb (define (concat-lists lista listb) ;; ok, I just reimplemented append... (foldr cons listb lista)) ;;; setup general_lib env var parameters ;; show warning/note/error/debug prefixes using ansi colors (define ducttape-color-mode (make-parameter (get-environment-variable "DUCTTAPE_COLORIZE"))) ;; if defined, has number value. if number value > 0, show debug messages ;; value should be decremented in subshells -- idea is raising debug level will show debug messages deeper and deeper in process call stack (define ducttape-debug-level (make-parameter (let ( (raw-debug-level (get-environment-variable "DUCTTAPE_DEBUG_LEVEL")) ) (if raw-debug-level (let ((num-debug-level (runs-ok (string->number raw-debug-level)))) (if (integer? num-debug-level) (begin (let ((new-num-debug-level (- num-debug-level 1))) (if (> new-num-debug-level 0) ;; decrement (setenv "DUCTTAPE_DEBUG_LEVEL" (number->string new-num-debug-level)) (unsetenv "DUCTTAPE_DEBUG_LEVEL"))) num-debug-level) ; it was set and > 0, mode is value (begin (unsetenv "DUCTTAPE_DEBUG_LEVEL") ;; value was invalid, unset it #f))) ; value was invalid, mode is f #f)))) ; var not set, mode is f (define ducttape-debug-mode (if (ducttape-debug-level) #t #f)) ;; ducttape-debug-regex-filter suppresses non-matching debug messages (define ducttape-debug-regex-filter (make-parameter (let ((raw-debug-pattern (get-environment-variable "DUCTTAPE_DEBUG_PATTERN"))) (if raw-debug-pattern raw-debug-pattern ".")))) ;; silent mode suppresses Note and Warning type messages (define ducttape-silent-mode (make-parameter (get-environment-variable "DUCTTAPE_SILENT_MODE"))) ;; quiet mode suppresses Note type messages (define ducttape-quiet-mode (make-parameter (get-environment-variable "DUCTTAPE_QUIET_MODE"))) ;; if log file is defined, warning/note/error/debug messages are appended ;; to named logfile. (define ducttape-log-file (make-parameter (get-environment-variable "DUCTTAPE_LOG_FILE"))) ;;; standard messages printing implementation ; get the name of the current script/binary being run (define (script-name) (car (reverse (string-split (car (argv)) "/")))) (define (ducttape-timestamp) (rfc3339->string (time->rfc3339 (seconds->local-time)))) (define (iputs-preamble msg-type #!optional (suppress-color #f)) (let ((do-color (and (not suppress-color) (ducttape-color-mode) (terminal-port? (current-error-port))))) (case msg-type ((note) (if do-color (set-text (list 'fg-green 'bg-black 'bold) "Note:") "Note:" )) ((warn) (if do-color (set-text (list 'fg-yellow 'bg-black 'bold) "Warning:") "Warning:" )) ((err) (if do-color (set-text (list 'fg-red 'bg-black 'bold) "Error:") "Error:" )) ((dbg) (if do-color (set-text (list 'fg-blue 'bg-magenta) "Debug:") "Debug:" ))))) (define (ducttape-append-logfile msg-type message #!optional (suppress-preamble #f)) (let ((txt (string-join (list (ducttape-timestamp) (script-name) (if suppress-preamble message (string-join (list (iputs-preamble msg-type #t) message) " "))) " | "))) (if (ducttape-log-file) (runs-ok (call-with-output-file (ducttape-log-file) (lambda (output-port) (format output-port "~A ~%" txt) ) #:append)) #t))) (define (ducttape-activate-logfile #!optional (logfile #f)) ;; from python ducttape-lib.py ; message = "START - pid=%d ppid=%d argv=(%s) pwd=%s user=%s host=%s"%(pid,ppid," ".join("'"+x+"'" for x in sys.argv),os.environ['PWD'],os.getenv('USER','nouser'),os.getenv('HOST','nohost') ) (let ((pid (number->string (current-process-id))) (ppid (number->string (parent-process-id))) (argv (string-join (map (lambda (x) (string-join (list "\"" x "\"") "" )) (argv)) " ")) (pwd (or (get-environment-variable "PWD") "nopwd")) (user (or (get-environment-variable "USER") "nouser")) (host (or (get-environment-variable "HOST") "nohost"))) (if logfile (begin (ducttape-log-file logfile) (setenv "DUCTTAPE_LOG_FILE" (ducttape-log-file)))) (ducttape-append-logfile 'note (format #f "START - pid=~A ppid=~A argv=(~A) pwd=~A user=~A host=~A" pid ppid argv pwd user host) #t))) ;; log exit code (define (set-ducttape-log-exit-handler) (let ((orig-exit-handler (exit-handler))) (exit-handler (lambda (exitcode) (ducttape-append-logfile 'note (format #f "Exit ~A by sys.exit" exitcode) #t) (orig-exit-handler exitcode))))) (define (idbg first-message . rest-args) (let* ((debug-level-threshold (if (> (length rest-args) 0) (car rest-args) 1)) (message-list (if (> (length rest-args) 1) (cons first-message (cdr rest-args)) (list first-message)) ) (message (apply conc (map ->string message-list)))) (ducttape-append-logfile 'dbg message) (if (ducttape-debug-level) (if (<= debug-level-threshold (ducttape-debug-level)) (if (string-search (ducttape-debug-regex-filter) message) (begin (format (current-error-port) "~A ~A (~A)~%" (iputs-preamble 'dbg) message (script-name)))))))) (define (ierr message-first . message-rest) (let* ((message (apply conc (map ->string (cons message-first message-rest))))) (ducttape-append-logfile 'err message) (format (current-error-port) "~A ~A (~A)~%" (iputs-preamble 'err) message (script-name)))) (define (iwarn message-first . message-rest) (let* ((message (apply conc (map ->string (cons message-first message-rest))))) (ducttape-append-logfile 'warn message) (if (not (ducttape-silent-mode)) (begin (format (current-error-port) "~A ~A (~A)~%" (iputs-preamble 'warn) message (script-name)))))) (define (inote message-first . message-rest) (let* ((message (apply conc (map ->string (cons message-first message-rest))))) (ducttape-append-logfile 'note message) (if (not (or (ducttape-silent-mode) (ducttape-quiet-mode))) (begin (format (current-error-port) "~A ~A (~A)~%" (iputs-preamble 'note) message (script-name)))))) (define (iputs kind message #!optional (debug-level-threshold 1)) (cond ((member kind (string-split "NOTE/Note/note/n/N" "/")) (inote message)) ((member kind (string-split "Error/ERROR/error/Err/ERR/err/E/e" "/")) (ierr message)) ((member kind (string-split "Warning/WARNING/warning/Warn/WARN/warn/W/w" "/")) (iwarn message)) ((member kind (string-split "Debug/DEBUG/debug/Dbg/DBG/dbg/D/d" "/")) (idbg message debug-level-threshold)))) (define (mkdir-recursive path-so-far hier-list-to-create) (if (null? hier-list-to-create) path-so-far (let* ((next-hier-item (car hier-list-to-create)) (rest-hier-items (cdr hier-list-to-create)) (path-to-mkdir (string-concatenate (list path-so-far "/" next-hier-item)))) (if (runs-ok (lambda () (create-directory path-to-mkdir))) (mkdir-recursive path-to-mkdir rest-hier-items) #f)))) ; ::mkdir-if-not-exists:: ; make a dir recursively if it does not ; already exist. ; on success - returns path ; on fail - returns #f (define (mkdirp-if-not-exists the-dir) (let ( (path-list (string-split the-dir "/"))) (mkdir-recursive "/" path-list))) ; ::mkdir-if-not-exists:: ; make a dir recursively if it does not ; already exist. ; on success - returns path ; on fail - returns #f (define (mkdirp-if-not-exists the-dir) (let ( (path-list (string-split the-dir "/"))) (mkdir-recursive "/" path-list))) (define (dir-is-writable? the-dir) (let ((dummy-file (string-concatenate (list the-dir "/.dummyfile")))) (and (file-exists? the-dir) (cond ((runs-ok (lambda ()(with-output-to-file dummy-file (lambda () (print "foo"))))) (begin (runs-ok (lambda () (delete-file dummy-file) )) the-dir)) (else #f))))) (define (get-tmpdir ) (let* ((tmproot (dir-is-writable? (or (get-environment-variable "TMPDIR") "/tmp"))) (user (or (get-environment-variable "USER") "USER_Envvar_not_set")) (tmppath (string-concatenate (list tmproot "/env21-general-" user )))) (dir-is-writable? (mkdirp-if-not-exists tmppath)))) (define (mktemp #!optional (prefix "general_lib_tmpfile") (dir #f)) (let-values (((fd path) (file-mkstemp (conc (if dir dir (get-tmpdir)) "/" prefix ".XXXXXX")))) (close-output-port (open-output-file* fd)) path)) ;;http://stackoverflow.com/questions/11134857/using-sendmail-for-html-body-and-binary-attachment ;; write send-email using: ;; - isys-foreach-stdin-line ;; - formatting in http://stackoverflow.com/questions/11134857/using-sendmail-for-html-body-and-binary-attachment (define (sendmail to_addr subject body #!key (from_addr "admin") cc_addr bcc_addr more-headers use_html (attach-files-list '()) (images-with-content-id-alist '()) ) (define (sendmail-proc sendmail-port) (define (wl line-str) (write-line line-str sendmail-port)) (define (get-uuid) (string-upcase (uuid->string (uuid-generate)))) (let ((mailpart-uuid (get-uuid)) (mailpart-body-uuid (get-uuid))) (define (boundary) (wl (conc "--" mailpart-uuid))) (define (body-boundary) (wl (conc "--" mailpart-body-uuid))) (define (email-mime-header) (wl (conc "From: " from_addr)) (wl (conc "To: " to_addr)) (if cc_addr (wl (conc "Cc: " cc_addr))) (if bcc_addr (wl (conc "Bcc: " bcc_addr))) (if more-headers (wl more-headers)) (wl (conc "Subject: " subject)) (wl "MIME-Version: 1.0") (wl (conc "Content-Type: multipart/mixed; boundary=\"" mailpart-uuid "\"")) (wl "") (boundary) (wl (conc "Content-Type: multipart/alternative; boundary=\"" mailpart-body-uuid "\"")) (wl "") ) (define (email-text-body) (body-boundary) (wl "Content-Type: text/plain; charset=ISO-8859-1") (wl "Content-Disposition: inline") (wl "") (wl body) (body-boundary)) (define (email-html-body) (body-boundary) (wl "Content-Type: text/plain; charset=ISO-8859-1") (wl "") (wl "You need to enable HTML option for email") (body-boundary) (wl "Content-Type: text/html; charset=ISO-8859-1") (wl "Content-Disposition: inline") (wl "") (wl body) (body-boundary)) (define (attach-file file #!key (content-id #f)) (let* ((filename (filepath:take-file-name file)) (ext-with-dot (filepath:take-extension file)) (ext (string-take-right ext-with-dot (- (string-length ext-with-dot) 1))) (mimetype (ext->mimetype ext)) (uuencode-command (conc "uuencode " file " " filename))) (boundary) (wl (conc "Content-Type: " mimetype "; name=\"" filename "\"")) (wl "Content-Transfer-Encoding: uuencode") (if content-id (wl (conc "Content-Id: " content-id))) (wl (conc "Content-Disposition: attachment; filename=\"" filename "\"")) (wl "") (do-or-die uuencode-command foreach-stdout: (lambda (line) (wl line))))) (define (embed-image file+content-id) (let ((file (car file+content-id)) (content-id (cdr file+content-id))) (attach-file file content-id: content-id))) ;; send the email (email-mime-header) (if use_html (email-html-body) (email-text-body)) (for-each attach-file attach-files-list) (for-each embed-image images-with-content-id-alist) (boundary) (close-output-port sendmail-port))) (do-or-die "/usr/sbin/sendmail -t" stdin-proc: sendmail-proc)) ;;;; process command line options ;; get command line switches (have no subsequent arg; eg. [-foo]) ;; assumes these are switches without arguments ;; will return list of matches ;; removes matches from command-line-arguments parameter (define (skim-cmdline-opts-noarg-by-regex switch-pattern) (let* ( (irr (irregex switch-pattern)) (matches (filter (lambda (x) (irregex-match irr x)) (command-line-arguments))) (non-matches (filter (lambda (x) (not (member x matches))) (command-line-arguments)))) (command-line-arguments non-matches) matches)) (define (keyword-skim keyword default args #!optional (eqpred equal?)) (let loop ( (kwval default) (args-remaining args) (args-to-return '()) ) (cond ((null? args-remaining) (values (if (list? kwval) (reverse kwval) kwval) (reverse args-to-return))) ((and (> (length args-remaining) 1) (eqpred keyword (car args-remaining))) (if (list? default) (if (equal? default kwval) (loop (list (cadr args-remaining)) (cddr args-remaining) args-to-return) (loop (cons (cadr args-remaining) kwval) (cddr args-remaining) args-to-return)) (loop (cadr args-remaining) (cddr args-remaining) args-to-return))) (else (loop kwval (cdr args-remaining) (cons (car args-remaining) args-to-return)))))) (define (get-cli-arg arg #!key (default #f) (is-list #f)) (let* ((temp (skim-cmdline-opts-withargs-by-regex arg))) (if (> (length temp) 0) (if is-list temp (car temp)) default))) (define (get-cli-switch arg) (let ((temp (skim-cmdline-opts-noarg-by-regex arg))) (if (> (length temp) 0) (car temp) #f))) ;; get command line switches (have a subsequent arg; eg. [-foo bar]) ;; assumes these are switches without arguments ;; will return list of arguments to matches ;; removes matches from command-line-arguments parameter (define (re-match? re str) (irregex-match re str)) (define (skim-cmdline-opts-withargs-by-regex switch-pattern) (let-values (((result new-cmdline-args) (keyword-skim switch-pattern '() (command-line-arguments) re-match? ))) (command-line-arguments new-cmdline-args) result)) ;; recognize ducttape-lib command line switches (--quiet, --silent, --color, -d.., -dp.., -logfile) ;; - reset parameters; reset DUCTTAPE_* env vars to match user specified intent ;; - mutate (command-line-arguments) parameter to subtract these recognized and handled switches ;; * beware -- now (argv) and (command-line-arguments) are inconsistent... cannot mutate (argv) alas. Use (command-line-arguments) ;; WARNING: this defines command line arguments that may clash with your program. Only call this if you ;; are sure they can coexist. (define (ducttape-process-command-line) ;; --quiet (let ((quiet-opts (skim-cmdline-opts-noarg-by-regex "--?quiet"))) (if (not (null? quiet-opts)) (begin (setenv "DUCTTAPE_QUIET_MODE" "1") (ducttape-quiet-mode "1")))) ;; --silent (let ((silent-opts (skim-cmdline-opts-noarg-by-regex "--?silent"))) (if (not (null? silent-opts)) (begin (setenv "DUCTTAPE_SILENT_MODE" "1") (ducttape-silent-mode "1")))) ;; -color (let ((color-opts (skim-cmdline-opts-noarg-by-regex "--?colou?r(ize)?"))) (if (not (null? color-opts)) (begin (setenv "DUCTTAPE_COLORIZE" "1") (ducttape-color-mode "1")))) ;; -nocolor (let ((nocolor-opts (skim-cmdline-opts-noarg-by-regex "--?nocolou?r(ize)?"))) (if (not (null? nocolor-opts)) (begin (unsetenv "DUCTTAPE_COLORIZE" ) (ducttape-color-mode #f)))) ;; -logfile (let ((logfile-opts (skim-cmdline-opts-withargs-by-regex "--?log(-?file)?"))) (if (not (null? logfile-opts)) (begin (ducttape-log-file (car (reverse logfile-opts))) (setenv "DUCTTAPE_LOG_FILE" (ducttape-log-file))))) ;; -d -dd -d# (let ((debug-opts (skim-cmdline-opts-noarg-by-regex "-d(d*|\\d+)")) (initial-debuglevel (if (ducttape-debug-level) (ducttape-debug-level) 0) )) (if (not (null? debug-opts)) (begin (ducttape-debug-level (let loop ((opts debug-opts) (debuglevel initial-debuglevel)) (if (null? opts) debuglevel (let* ( (curopt (car opts)) (restopts (cdr opts)) (ds (string-match "-(d+)" curopt)) (dnum (string-match "-d(\\d+)" curopt))) (cond (ds (loop restopts (+ debuglevel (string-length (cadr ds))))) (dnum (loop restopts (string->number (cadr dnum))))))))) (setenv "DUCTTAPE_DEBUG_LEVEL" (number->string (ducttape-debug-level)))))) ;; -dp <pat> / --debug-pattern <pat> (let ((debugpat-opts (skim-cmdline-opts-withargs-by-regex "--?(debug-pattern|dp)"))) (if (not (null? debugpat-opts)) (begin (ducttape-debug-regex-filter (string-join debugpat-opts "|")) (setenv "DUCTTAPE_DEBUG_PATTERN" (ducttape-debug-regex-filter)))))) ;;; following code commented out; side effects not wanted on startup ;; immediately activate logfile (will be noop if logfile disabled) ;;(ducttape-activate-logfile) ;;(set-ducttape-log-exit-handler) ;; TODO: hook exception handler so we can log exception before we sign off. ;; handle command line immediately; ;;(process-command-line) ) ; end module |
Added ducttape/ducttape-lib.setup version [f078cc60c2].
> | 1 | (standard-extension 'ducttape-lib '1.0.0) |
Added ducttape/mimetypes.scm version [391fe0b393].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 | ;; gathered from macosx: ;; cat /etc/apache2/mime.types | grep -v '^#' | perl -ne 'print "(\"$2\" . \"$1\")\n" if /(\S+)\s+(\S+)/' > mimetypes.scm ;; + manual manipulation (define ducttape_ext2mimetype '(("ez" . "application/andrew-inset") ("aw" . "application/applixware") ("atom" . "application/atom+xml") ("atomcat" . "application/atomcat+xml") ("atomsvc" . "application/atomsvc+xml") ("ccxml" . "application/ccxml+xml") ("cdmia" . "application/cdmi-capability") ("cdmic" . "application/cdmi-container") ("cdmid" . "application/cdmi-domain") ("cdmio" . "application/cdmi-object") ("cdmiq" . "application/cdmi-queue") ("cu" . "application/cu-seeme") ("davmount" . "application/davmount+xml") ("dbk" . "application/docbook+xml") ("dssc" . "application/dssc+der") ("xdssc" . "application/dssc+xml") ("ecma" . "application/ecmascript") ("emma" . "application/emma+xml") ("epub" . "application/epub+zip") ("exi" . "application/exi") ("pfr" . "application/font-tdpfr") ("gml" . "application/gml+xml") ("gpx" . "application/gpx+xml") ("gxf" . "application/gxf") ("stk" . "application/hyperstudio") ("ink" . "application/inkml+xml") ("ipfix" . "application/ipfix") ("jar" . "application/java-archive") ("ser" . "application/java-serialized-object") ("class" . "application/java-vm") ("js" . "application/javascript") ("json" . "application/json") ("jsonml" . "application/jsonml+json") ("lostxml" . "application/lost+xml") ("hqx" . "application/mac-binhex40") ("cpt" . "application/mac-compactpro") ("mads" . "application/mads+xml") ("mrc" . "application/marc") ("mrcx" . "application/marcxml+xml") ("ma" . "application/mathematica") ("mathml" . "application/mathml+xml") ("mbox" . "application/mbox") ("mscml" . "application/mediaservercontrol+xml") ("metalink" . "application/metalink+xml") ("meta4" . "application/metalink4+xml") ("mets" . "application/mets+xml") ("mods" . "application/mods+xml") ("m21" . "application/mp21") ("mp4s" . "application/mp4") ("doc" . "application/msword") ("mxf" . "application/mxf") ("bin" . "application/octet-stream") ("oda" . "application/oda") ("opf" . "application/oebps-package+xml") ("ogx" . "application/ogg") ("omdoc" . "application/omdoc+xml") ("onetoc" . "application/onenote") ("oxps" . "application/oxps") ("xer" . "application/patch-ops-error+xml") ("pdf" . "application/pdf") ("pgp" . "application/pgp-encrypted") ("asc" . "application/pgp-signature") ("prf" . "application/pics-rules") ("p10" . "application/pkcs10") ("p7m" . "application/pkcs7-mime") ("p7s" . "application/pkcs7-signature") ("p8" . "application/pkcs8") ("ac" . "application/pkix-attr-cert") ("cer" . "application/pkix-cert") ("crl" . "application/pkix-crl") ("pkipath" . "application/pkix-pkipath") ("pki" . "application/pkixcmp") ("pls" . "application/pls+xml") ("ai" . "application/postscript") ("cww" . "application/prs.cww") ("pskcxml" . "application/pskc+xml") ("rdf" . "application/rdf+xml") ("rif" . "application/reginfo+xml") ("rnc" . "application/relax-ng-compact-syntax") ("rl" . "application/resource-lists+xml") ("rld" . "application/resource-lists-diff+xml") ("rs" . "application/rls-services+xml") ("gbr" . "application/rpki-ghostbusters") ("mft" . "application/rpki-manifest") ("roa" . "application/rpki-roa") ("rsd" . "application/rsd+xml") ("rss" . "application/rss+xml") ("rtf" . "application/rtf") ("sbml" . "application/sbml+xml") ("scq" . "application/scvp-cv-request") ("scs" . "application/scvp-cv-response") ("spq" . "application/scvp-vp-request") ("spp" . "application/scvp-vp-response") ("sdp" . "application/sdp") ("setpay" . "application/set-payment-initiation") ("setreg" . "application/set-registration-initiation") ("shf" . "application/shf+xml") ("smi" . "application/smil+xml") ("rq" . "application/sparql-query") ("srx" . "application/sparql-results+xml") ("gram" . "application/srgs") ("grxml" . "application/srgs+xml") ("sru" . "application/sru+xml") ("ssdl" . "application/ssdl+xml") ("ssml" . "application/ssml+xml") ("tei" . "application/tei+xml") ("tfi" . "application/thraud+xml") ("tsd" . "application/timestamped-data") ("plb" . "application/vnd.3gpp.pic-bw-large") ("psb" . "application/vnd.3gpp.pic-bw-small") ("pvb" . "application/vnd.3gpp.pic-bw-var") ("tcap" . "application/vnd.3gpp2.tcap") ("pwn" . "application/vnd.3m.post-it-notes") ("aso" . "application/vnd.accpac.simply.aso") ("imp" . "application/vnd.accpac.simply.imp") ("acu" . "application/vnd.acucobol") ("atc" . "application/vnd.acucorp") ("air" . "application/vnd.adobe.air-application-installer-package+zip") ("fcdt" . "application/vnd.adobe.formscentral.fcdt") ("fxp" . "application/vnd.adobe.fxp") ("xdp" . "application/vnd.adobe.xdp+xml") ("xfdf" . "application/vnd.adobe.xfdf") ("ahead" . "application/vnd.ahead.space") ("azf" . "application/vnd.airzip.filesecure.azf") ("azs" . "application/vnd.airzip.filesecure.azs") ("azw" . "application/vnd.amazon.ebook") ("acc" . "application/vnd.americandynamics.acc") ("ami" . "application/vnd.amiga.ami") ("apk" . "application/vnd.android.package-archive") ("cii" . "application/vnd.anser-web-certificate-issue-initiation") ("fti" . "application/vnd.anser-web-funds-transfer-initiation") ("atx" . "application/vnd.antix.game-component") ("mpkg" . "application/vnd.apple.installer+xml") ("m3u8" . "application/vnd.apple.mpegurl") ("swi" . "application/vnd.aristanetworks.swi") ("iota" . "application/vnd.astraea-software.iota") ("aep" . "application/vnd.audiograph") ("mpm" . "application/vnd.blueice.multipass") ("bmi" . "application/vnd.bmi") ("rep" . "application/vnd.businessobjects") ("cdxml" . "application/vnd.chemdraw+xml") ("mmd" . "application/vnd.chipnuts.karaoke-mmd") ("cdy" . "application/vnd.cinderella") ("cla" . "application/vnd.claymore") ("rp9" . "application/vnd.cloanto.rp9") ("c4g" . "application/vnd.clonk.c4group") ("c11amc" . "application/vnd.cluetrust.cartomobile-config") ("c11amz" . "application/vnd.cluetrust.cartomobile-config-pkg") ("csp" . "application/vnd.commonspace") ("cdbcmsg" . "application/vnd.contact.cmsg") ("cmc" . "application/vnd.cosmocaller") ("clkx" . "application/vnd.crick.clicker") ("clkk" . "application/vnd.crick.clicker.keyboard") ("clkp" . "application/vnd.crick.clicker.palette") ("clkt" . "application/vnd.crick.clicker.template") ("clkw" . "application/vnd.crick.clicker.wordbank") ("wbs" . "application/vnd.criticaltools.wbs+xml") ("pml" . "application/vnd.ctc-posml") ("ppd" . "application/vnd.cups-ppd") ("car" . "application/vnd.curl.car") ("pcurl" . "application/vnd.curl.pcurl") ("dart" . "application/vnd.dart") ("rdz" . "application/vnd.data-vision.rdz") ("uvf" . "application/vnd.dece.data") ("uvt" . "application/vnd.dece.ttml+xml") ("uvx" . "application/vnd.dece.unspecified") ("uvz" . "application/vnd.dece.zip") ("fe_launch" . "application/vnd.denovo.fcselayout-link") ("dna" . "application/vnd.dna") ("mlp" . "application/vnd.dolby.mlp") ("dpg" . "application/vnd.dpgraph") ("dfac" . "application/vnd.dreamfactory") ("kpxx" . "application/vnd.ds-keypoint") ("ait" . "application/vnd.dvb.ait") ("svc" . "application/vnd.dvb.service") ("geo" . "application/vnd.dynageo") ("mag" . "application/vnd.ecowin.chart") ("nml" . "application/vnd.enliven") ("esf" . "application/vnd.epson.esf") ("msf" . "application/vnd.epson.msf") ("qam" . "application/vnd.epson.quickanime") ("slt" . "application/vnd.epson.salt") ("ssf" . "application/vnd.epson.ssf") ("es3" . "application/vnd.eszigno3+xml") ("ez2" . "application/vnd.ezpix-album") ("ez3" . "application/vnd.ezpix-package") ("fdf" . "application/vnd.fdf") ("mseed" . "application/vnd.fdsn.mseed") ("seed" . "application/vnd.fdsn.seed") ("gph" . "application/vnd.flographit") ("ftc" . "application/vnd.fluxtime.clip") ("fm" . "application/vnd.framemaker") ("fnc" . "application/vnd.frogans.fnc") ("ltf" . "application/vnd.frogans.ltf") ("fsc" . "application/vnd.fsc.weblaunch") ("oas" . "application/vnd.fujitsu.oasys") ("oa2" . "application/vnd.fujitsu.oasys2") ("oa3" . "application/vnd.fujitsu.oasys3") ("fg5" . "application/vnd.fujitsu.oasysgp") ("bh2" . "application/vnd.fujitsu.oasysprs") ("ddd" . "application/vnd.fujixerox.ddd") ("xdw" . "application/vnd.fujixerox.docuworks") ("xbd" . "application/vnd.fujixerox.docuworks.binder") ("fzs" . "application/vnd.fuzzysheet") ("txd" . "application/vnd.genomatix.tuxedo") ("ggb" . "application/vnd.geogebra.file") ("ggt" . "application/vnd.geogebra.tool") ("gex" . "application/vnd.geometry-explorer") ("gxt" . "application/vnd.geonext") ("g2w" . "application/vnd.geoplan") ("g3w" . "application/vnd.geospace") ("gmx" . "application/vnd.gmx") ("kml" . "application/vnd.google-earth.kml+xml") ("kmz" . "application/vnd.google-earth.kmz") ("gqf" . "application/vnd.grafeq") ("gac" . "application/vnd.groove-account") ("ghf" . "application/vnd.groove-help") ("gim" . "application/vnd.groove-identity-message") ("grv" . "application/vnd.groove-injector") ("gtm" . "application/vnd.groove-tool-message") ("tpl" . "application/vnd.groove-tool-template") ("vcg" . "application/vnd.groove-vcard") ("hal" . "application/vnd.hal+xml") ("zmm" . "application/vnd.handheld-entertainment+xml") ("hbci" . "application/vnd.hbci") ("les" . "application/vnd.hhe.lesson-player") ("hpgl" . "application/vnd.hp-hpgl") ("hpid" . "application/vnd.hp-hpid") ("hps" . "application/vnd.hp-hps") ("jlt" . "application/vnd.hp-jlyt") ("pcl" . "application/vnd.hp-pcl") ("pclxl" . "application/vnd.hp-pclxl") ("sfd-hdstx" . "application/vnd.hydrostatix.sof-data") ("mpy" . "application/vnd.ibm.minipay") ("afp" . "application/vnd.ibm.modcap") ("irm" . "application/vnd.ibm.rights-management") ("sc" . "application/vnd.ibm.secure-container") ("icc" . "application/vnd.iccprofile") ("igl" . "application/vnd.igloader") ("ivp" . "application/vnd.immervision-ivp") ("ivu" . "application/vnd.immervision-ivu") ("igm" . "application/vnd.insors.igm") ("xpw" . "application/vnd.intercon.formnet") ("i2g" . "application/vnd.intergeo") ("qbo" . "application/vnd.intu.qbo") ("qfx" . "application/vnd.intu.qfx") ("rcprofile" . "application/vnd.ipunplugged.rcprofile") ("irp" . "application/vnd.irepository.package+xml") ("xpr" . "application/vnd.is-xpr") ("fcs" . "application/vnd.isac.fcs") ("jam" . "application/vnd.jam") ("rms" . "application/vnd.jcp.javame.midlet-rms") ("jisp" . "application/vnd.jisp") ("joda" . "application/vnd.joost.joda-archive") ("ktz" . "application/vnd.kahootz") ("karbon" . "application/vnd.kde.karbon") ("chrt" . "application/vnd.kde.kchart") ("kfo" . "application/vnd.kde.kformula") ("flw" . "application/vnd.kde.kivio") ("kon" . "application/vnd.kde.kontour") ("kpr" . "application/vnd.kde.kpresenter") ("ksp" . "application/vnd.kde.kspread") ("kwd" . "application/vnd.kde.kword") ("htke" . "application/vnd.kenameaapp") ("kia" . "application/vnd.kidspiration") ("kne" . "application/vnd.kinar") ("skp" . "application/vnd.koan") ("sse" . "application/vnd.kodak-descriptor") ("lasxml" . "application/vnd.las.las+xml") ("lbd" . "application/vnd.llamagraphics.life-balance.desktop") ("lbe" . "application/vnd.llamagraphics.life-balance.exchange+xml") ("123" . "application/vnd.lotus-1-2-3") ("apr" . "application/vnd.lotus-approach") ("pre" . "application/vnd.lotus-freelance") ("nsf" . "application/vnd.lotus-notes") ("org" . "application/vnd.lotus-organizer") ("scm" . "application/vnd.lotus-screencam") ("lwp" . "application/vnd.lotus-wordpro") ("portpkg" . "application/vnd.macports.portpkg") ("mcd" . "application/vnd.mcd") ("mc1" . "application/vnd.medcalcdata") ("cdkey" . "application/vnd.mediastation.cdkey") ("mwf" . "application/vnd.mfer") ("mfm" . "application/vnd.mfmp") ("flo" . "application/vnd.micrografx.flo") ("igx" . "application/vnd.micrografx.igx") ("mif" . "application/vnd.mif") ("daf" . "application/vnd.mobius.daf") ("dis" . "application/vnd.mobius.dis") ("mbk" . "application/vnd.mobius.mbk") ("mqy" . "application/vnd.mobius.mqy") ("msl" . "application/vnd.mobius.msl") ("plc" . "application/vnd.mobius.plc") ("txf" . "application/vnd.mobius.txf") ("mpn" . "application/vnd.mophun.application") ("mpc" . "application/vnd.mophun.certificate") ("xul" . "application/vnd.mozilla.xul+xml") ("cil" . "application/vnd.ms-artgalry") ("cab" . "application/vnd.ms-cab-compressed") ("xls" . "application/vnd.ms-excel") ("xlam" . "application/vnd.ms-excel.addin.macroenabled.12") ("xlsb" . "application/vnd.ms-excel.sheet.binary.macroenabled.12") ("xlsm" . "application/vnd.ms-excel.sheet.macroenabled.12") ("xltm" . "application/vnd.ms-excel.template.macroenabled.12") ("eot" . "application/vnd.ms-fontobject") ("chm" . "application/vnd.ms-htmlhelp") ("ims" . "application/vnd.ms-ims") ("lrm" . "application/vnd.ms-lrm") ("thmx" . "application/vnd.ms-officetheme") ("cat" . "application/vnd.ms-pki.seccat") ("stl" . "application/vnd.ms-pki.stl") ("ppt" . "application/vnd.ms-powerpoint") ("ppam" . "application/vnd.ms-powerpoint.addin.macroenabled.12") ("pptm" . "application/vnd.ms-powerpoint.presentation.macroenabled.12") ("sldm" . "application/vnd.ms-powerpoint.slide.macroenabled.12") ("ppsm" . "application/vnd.ms-powerpoint.slideshow.macroenabled.12") ("potm" . "application/vnd.ms-powerpoint.template.macroenabled.12") ("mpp" . "application/vnd.ms-project") ("docm" . "application/vnd.ms-word.document.macroenabled.12") ("dotm" . "application/vnd.ms-word.template.macroenabled.12") ("wps" . "application/vnd.ms-works") ("wpl" . "application/vnd.ms-wpl") ("xps" . "application/vnd.ms-xpsdocument") ("mseq" . "application/vnd.mseq") ("mus" . "application/vnd.musician") ("msty" . "application/vnd.muvee.style") ("taglet" . "application/vnd.mynfc") ("nlu" . "application/vnd.neurolanguage.nlu") ("ntf" . "application/vnd.nitf") ("nnd" . "application/vnd.noblenet-directory") ("nns" . "application/vnd.noblenet-sealer") ("nnw" . "application/vnd.noblenet-web") ("ngdat" . "application/vnd.nokia.n-gage.data") ("n-gage" . "application/vnd.nokia.n-gage.symbian.install") ("rpst" . "application/vnd.nokia.radio-preset") ("rpss" . "application/vnd.nokia.radio-presets") ("edm" . "application/vnd.novadigm.edm") ("edx" . "application/vnd.novadigm.edx") ("ext" . "application/vnd.novadigm.ext") ("odc" . "application/vnd.oasis.opendocument.chart") ("otc" . "application/vnd.oasis.opendocument.chart-template") ("odb" . "application/vnd.oasis.opendocument.database") ("odf" . "application/vnd.oasis.opendocument.formula") ("odft" . "application/vnd.oasis.opendocument.formula-template") ("odg" . "application/vnd.oasis.opendocument.graphics") ("otg" . "application/vnd.oasis.opendocument.graphics-template") ("odi" . "application/vnd.oasis.opendocument.image") ("oti" . "application/vnd.oasis.opendocument.image-template") ("odp" . "application/vnd.oasis.opendocument.presentation") ("otp" . "application/vnd.oasis.opendocument.presentation-template") ("ods" . "application/vnd.oasis.opendocument.spreadsheet") ("ots" . "application/vnd.oasis.opendocument.spreadsheet-template") ("odt" . "application/vnd.oasis.opendocument.text") ("odm" . "application/vnd.oasis.opendocument.text-master") ("ott" . "application/vnd.oasis.opendocument.text-template") ("oth" . "application/vnd.oasis.opendocument.text-web") ("xo" . "application/vnd.olpc-sugar") ("dd2" . "application/vnd.oma.dd2+xml") ("oxt" . "application/vnd.openofficeorg.extension") ("pptx" . "application/vnd.openxmlformats-officedocument.presentationml.presentation") ("sldx" . "application/vnd.openxmlformats-officedocument.presentationml.slide") ("ppsx" . "application/vnd.openxmlformats-officedocument.presentationml.slideshow") ("potx" . "application/vnd.openxmlformats-officedocument.presentationml.template") ("xlsx" . "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") ("xltx" . "application/vnd.openxmlformats-officedocument.spreadsheetml.template") ("docx" . "application/vnd.openxmlformats-officedocument.wordprocessingml.document") ("dotx" . "application/vnd.openxmlformats-officedocument.wordprocessingml.template") ("mgp" . "application/vnd.osgeo.mapguide.package") ("dp" . "application/vnd.osgi.dp") ("esa" . "application/vnd.osgi.subsystem") ("pdb" . "application/vnd.palm") ("paw" . "application/vnd.pawaafile") ("str" . "application/vnd.pg.format") ("ei6" . "application/vnd.pg.osasli") ("efif" . "application/vnd.picsel") ("wg" . "application/vnd.pmi.widget") ("plf" . "application/vnd.pocketlearn") ("pbd" . "application/vnd.powerbuilder6") ("box" . "application/vnd.previewsystems.box") ("mgz" . "application/vnd.proteus.magazine") ("qps" . "application/vnd.publishare-delta-tree") ("ptid" . "application/vnd.pvi.ptid1") ("qxd" . "application/vnd.quark.quarkxpress") ("bed" . "application/vnd.realvnc.bed") ("mxl" . "application/vnd.recordare.musicxml") ("musicxml" . "application/vnd.recordare.musicxml+xml") ("cryptonote" . "application/vnd.rig.cryptonote") ("cod" . "application/vnd.rim.cod") ("rm" . "application/vnd.rn-realmedia") ("rmvb" . "application/vnd.rn-realmedia-vbr") ("link66" . "application/vnd.route66.link66+xml") ("st" . "application/vnd.sailingtracker.track") ("see" . "application/vnd.seemail") ("sema" . "application/vnd.sema") ("semd" . "application/vnd.semd") ("semf" . "application/vnd.semf") ("ifm" . "application/vnd.shana.informed.formdata") ("itp" . "application/vnd.shana.informed.formtemplate") ("iif" . "application/vnd.shana.informed.interchange") ("ipk" . "application/vnd.shana.informed.package") ("twd" . "application/vnd.simtech-mindmapper") ("mmf" . "application/vnd.smaf") ("teacher" . "application/vnd.smart.teacher") ("sdkm" . "application/vnd.solent.sdkm+xml") ("dxp" . "application/vnd.spotfire.dxp") ("sfs" . "application/vnd.spotfire.sfs") ("sdc" . "application/vnd.stardivision.calc") ("sda" . "application/vnd.stardivision.draw") ("sdd" . "application/vnd.stardivision.impress") ("smf" . "application/vnd.stardivision.math") ("sdw" . "application/vnd.stardivision.writer") ("sgl" . "application/vnd.stardivision.writer-global") ("smzip" . "application/vnd.stepmania.package") ("sm" . "application/vnd.stepmania.stepchart") ("sxc" . "application/vnd.sun.xml.calc") ("stc" . "application/vnd.sun.xml.calc.template") ("sxd" . "application/vnd.sun.xml.draw") ("std" . "application/vnd.sun.xml.draw.template") ("sxi" . "application/vnd.sun.xml.impress") ("sti" . "application/vnd.sun.xml.impress.template") ("sxm" . "application/vnd.sun.xml.math") ("sxw" . "application/vnd.sun.xml.writer") ("sxg" . "application/vnd.sun.xml.writer.global") ("stw" . "application/vnd.sun.xml.writer.template") ("sus" . "application/vnd.sus-calendar") ("svd" . "application/vnd.svd") ("sis" . "application/vnd.symbian.install") ("xsm" . "application/vnd.syncml+xml") ("bdm" . "application/vnd.syncml.dm+wbxml") ("xdm" . "application/vnd.syncml.dm+xml") ("tao" . "application/vnd.tao.intent-module-archive") ("pcap" . "application/vnd.tcpdump.pcap") ("tmo" . "application/vnd.tmobile-livetv") ("tpt" . "application/vnd.trid.tpt") ("mxs" . "application/vnd.triscape.mxs") ("tra" . "application/vnd.trueapp") ("ufd" . "application/vnd.ufdl") ("utz" . "application/vnd.uiq.theme") ("umj" . "application/vnd.umajin") ("unityweb" . "application/vnd.unity") ("uoml" . "application/vnd.uoml+xml") ("vcx" . "application/vnd.vcx") ("vsd" . "application/vnd.visio") ("vis" . "application/vnd.visionary") ("vsf" . "application/vnd.vsf") ("wbxml" . "application/vnd.wap.wbxml") ("wmlc" . "application/vnd.wap.wmlc") ("wmlsc" . "application/vnd.wap.wmlscriptc") ("wtb" . "application/vnd.webturbo") ("nbp" . "application/vnd.wolfram.player") ("wpd" . "application/vnd.wordperfect") ("wqd" . "application/vnd.wqd") ("stf" . "application/vnd.wt.stf") ("xar" . "application/vnd.xara") ("xfdl" . "application/vnd.xfdl") ("hvd" . "application/vnd.yamaha.hv-dic") ("hvs" . "application/vnd.yamaha.hv-script") ("hvp" . "application/vnd.yamaha.hv-voice") ("osf" . "application/vnd.yamaha.openscoreformat") ("osfpvg" . "application/vnd.yamaha.openscoreformat.osfpvg+xml") ("saf" . "application/vnd.yamaha.smaf-audio") ("spf" . "application/vnd.yamaha.smaf-phrase") ("cmp" . "application/vnd.yellowriver-custom-menu") ("zir" . "application/vnd.zul") ("zaz" . "application/vnd.zzazz.deck+xml") ("vxml" . "application/voicexml+xml") ("wgt" . "application/widget") ("hlp" . "application/winhlp") ("wsdl" . "application/wsdl+xml") ("wspolicy" . "application/wspolicy+xml") ("7z" . "application/x-7z-compressed") ("abw" . "application/x-abiword") ("ace" . "application/x-ace-compressed") ("dmg" . "application/x-apple-diskimage") ("aab" . "application/x-authorware-bin") ("aam" . "application/x-authorware-map") ("aas" . "application/x-authorware-seg") ("bcpio" . "application/x-bcpio") ("torrent" . "application/x-bittorrent") ("blb" . "application/x-blorb") ("bz" . "application/x-bzip") ("bz2" . "application/x-bzip2") ("cbr" . "application/x-cbr") ("vcd" . "application/x-cdlink") ("cfs" . "application/x-cfs-compressed") ("chat" . "application/x-chat") ("pgn" . "application/x-chess-pgn") ("nsc" . "application/x-conference") ("cpio" . "application/x-cpio") ("csh" . "application/x-csh") ("deb" . "application/x-debian-package") ("dgc" . "application/x-dgc-compressed") ("dir" . "application/x-director") ("wad" . "application/x-doom") ("ncx" . "application/x-dtbncx+xml") ("dtb" . "application/x-dtbook+xml") ("res" . "application/x-dtbresource+xml") ("dvi" . "application/x-dvi") ("evy" . "application/x-envoy") ("eva" . "application/x-eva") ("bdf" . "application/x-font-bdf") ("gsf" . "application/x-font-ghostscript") ("psf" . "application/x-font-linux-psf") ("otf" . "application/x-font-otf") ("pcf" . "application/x-font-pcf") ("snf" . "application/x-font-snf") ("ttf" . "application/x-font-ttf") ("pfa" . "application/x-font-type1") ("woff" . "application/x-font-woff") ("arc" . "application/x-freearc") ("spl" . "application/x-futuresplash") ("gca" . "application/x-gca-compressed") ("ulx" . "application/x-glulx") ("gnumeric" . "application/x-gnumeric") ("gramps" . "application/x-gramps-xml") ("gtar" . "application/x-gtar") ("hdf" . "application/x-hdf") ("install" . "application/x-install-instructions") ("iso" . "application/x-iso9660-image") ("jnlp" . "application/x-java-jnlp-file") ("latex" . "application/x-latex") ("lzh" . "application/x-lzh-compressed") ("mie" . "application/x-mie") ("prc" . "application/x-mobipocket-ebook") ("m3u8" . "application/x-mpegurl") ("application" . "application/x-ms-application") ("lnk" . "application/x-ms-shortcut") ("wmd" . "application/x-ms-wmd") ("wmz" . "application/x-ms-wmz") ("xbap" . "application/x-ms-xbap") ("mdb" . "application/x-msaccess") ("obd" . "application/x-msbinder") ("crd" . "application/x-mscardfile") ("clp" . "application/x-msclip") ("exe" . "application/x-msdownload") ("mvb" . "application/x-msmediaview") ("wmf" . "application/x-msmetafile") ("mny" . "application/x-msmoney") ("pub" . "application/x-mspublisher") ("scd" . "application/x-msschedule") ("trm" . "application/x-msterminal") ("wri" . "application/x-mswrite") ("nc" . "application/x-netcdf") ("nzb" . "application/x-nzb") ("p12" . "application/x-pkcs12") ("p7b" . "application/x-pkcs7-certificates") ("p7r" . "application/x-pkcs7-certreqresp") ("rar" . "application/x-rar-compressed") ("ris" . "application/x-research-info-systems") ("sh" . "application/x-sh") ("shar" . "application/x-shar") ("swf" . "application/x-shockwave-flash") ("xap" . "application/x-silverlight-app") ("sql" . "application/x-sql") ("sit" . "application/x-stuffit") ("sitx" . "application/x-stuffitx") ("srt" . "application/x-subrip") ("sv4cpio" . "application/x-sv4cpio") ("sv4crc" . "application/x-sv4crc") ("t3" . "application/x-t3vm-image") ("gam" . "application/x-tads") ("tar" . "application/x-tar") ("tcl" . "application/x-tcl") ("tex" . "application/x-tex") ("tfm" . "application/x-tex-tfm") ("texinfo" . "application/x-texinfo") ("obj" . "application/x-tgif") ("ustar" . "application/x-ustar") ("src" . "application/x-wais-source") ("der" . "application/x-x509-ca-cert") ("fig" . "application/x-xfig") ("xlf" . "application/x-xliff+xml") ("xpi" . "application/x-xpinstall") ("xz" . "application/x-xz") ("z1" . "application/x-zmachine") ("xaml" . "application/xaml+xml") ("xdf" . "application/xcap-diff+xml") ("xenc" . "application/xenc+xml") ("xhtml" . "application/xhtml+xml") ("xml" . "application/xml") ("dtd" . "application/xml-dtd") ("xop" . "application/xop+xml") ("xpl" . "application/xproc+xml") ("xslt" . "application/xslt+xml") ("xspf" . "application/xspf+xml") ("mxml" . "application/xv+xml") ("yang" . "application/yang") ("yin" . "application/yin+xml") ("zip" . "application/zip") ("adp" . "audio/adpcm") ("au" . "audio/basic") ("mid" . "audio/midi") ("mp4a" . "audio/mp4") ("m4a" . "audio/mp4a-latm") ("mpga" . "audio/mpeg") ("oga" . "audio/ogg") ("s3m" . "audio/s3m") ("sil" . "audio/silk") ("uva" . "audio/vnd.dece.audio") ("eol" . "audio/vnd.digital-winds") ("dra" . "audio/vnd.dra") ("dts" . "audio/vnd.dts") ("dtshd" . "audio/vnd.dts.hd") ("lvp" . "audio/vnd.lucent.voice") ("pya" . "audio/vnd.ms-playready.media.pya") ("ecelp4800" . "audio/vnd.nuera.ecelp4800") ("ecelp7470" . "audio/vnd.nuera.ecelp7470") ("ecelp9600" . "audio/vnd.nuera.ecelp9600") ("rip" . "audio/vnd.rip") ("weba" . "audio/webm") ("aac" . "audio/x-aac") ("aif" . "audio/x-aiff") ("caf" . "audio/x-caf") ("flac" . "audio/x-flac") ("mka" . "audio/x-matroska") ("m3u" . "audio/x-mpegurl") ("wax" . "audio/x-ms-wax") ("wma" . "audio/x-ms-wma") ("ram" . "audio/x-pn-realaudio") ("rmp" . "audio/x-pn-realaudio-plugin") ("wav" . "audio/x-wav") ("xm" . "audio/xm") ("cdx" . "chemical/x-cdx") ("cif" . "chemical/x-cif") ("cmdf" . "chemical/x-cmdf") ("cml" . "chemical/x-cml") ("csml" . "chemical/x-csml") ("xyz" . "chemical/x-xyz") ("bmp" . "image/bmp") ("cgm" . "image/cgm") ("g3" . "image/g3fax") ("gif" . "image/gif") ("ief" . "image/ief") ("jp2" . "image/jp2") ("jpeg" . "image/jpeg") ("ktx" . "image/ktx") ("pict" . "image/pict") ("png" . "image/png") ("btif" . "image/prs.btif") ("sgi" . "image/sgi") ("svg" . "image/svg+xml") ("tiff" . "image/tiff") ("psd" . "image/vnd.adobe.photoshop") ("uvi" . "image/vnd.dece.graphic") ("sub" . "image/vnd.dvb.subtitle") ("djvu" . "image/vnd.djvu") ("dwg" . "image/vnd.dwg") ("dxf" . "image/vnd.dxf") ("fbs" . "image/vnd.fastbidsheet") ("fpx" . "image/vnd.fpx") ("fst" . "image/vnd.fst") ("mmr" . "image/vnd.fujixerox.edmics-mmr") ("rlc" . "image/vnd.fujixerox.edmics-rlc") ("mdi" . "image/vnd.ms-modi") ("wdp" . "image/vnd.ms-photo") ("npx" . "image/vnd.net-fpx") ("wbmp" . "image/vnd.wap.wbmp") ("xif" . "image/vnd.xiff") ("webp" . "image/webp") ("3ds" . "image/x-3ds") ("ras" . "image/x-cmu-raster") ("cmx" . "image/x-cmx") ("fh" . "image/x-freehand") ("ico" . "image/x-icon") ("pntg" . "image/x-macpaint") ("sid" . "image/x-mrsid-image") ("pcx" . "image/x-pcx") ("pic" . "image/x-pict") ("pnm" . "image/x-portable-anymap") ("pbm" . "image/x-portable-bitmap") ("pgm" . "image/x-portable-graymap") ("ppm" . "image/x-portable-pixmap") ("qtif" . "image/x-quicktime") ("rgb" . "image/x-rgb") ("tga" . "image/x-tga") ("xbm" . "image/x-xbitmap") ("xpm" . "image/x-xpixmap") ("xwd" . "image/x-xwindowdump") ("eml" . "message/rfc822") ("igs" . "model/iges") ("msh" . "model/mesh") ("dae" . "model/vnd.collada+xml") ("dwf" . "model/vnd.dwf") ("gdl" . "model/vnd.gdl") ("gtw" . "model/vnd.gtw") ("mts" . "model/vnd.mts") ("vtu" . "model/vnd.vtu") ("wrl" . "model/vrml") ("x3db" . "model/x3d+binary") ("x3dv" . "model/x3d+vrml") ("x3d" . "model/x3d+xml") ("manifest" . "text/cache-manifest") ("appcache" . "text/cache-manifest") ("ics" . "text/calendar") ("css" . "text/css") ("csv" . "text/csv") ("html" . "text/html") ("n3" . "text/n3") ("txt" . "text/plain") ("dsc" . "text/prs.lines.tag") ("rtx" . "text/richtext") ("sgml" . "text/sgml") ("tsv" . "text/tab-separated-values") ("t" . "text/troff") ("ttl" . "text/turtle") ("uri" . "text/uri-list") ("vcard" . "text/vcard") ("curl" . "text/vnd.curl") ("dcurl" . "text/vnd.curl.dcurl") ("scurl" . "text/vnd.curl.scurl") ("mcurl" . "text/vnd.curl.mcurl") ("sub" . "text/vnd.dvb.subtitle") ("fly" . "text/vnd.fly") ("flx" . "text/vnd.fmi.flexstor") ("gv" . "text/vnd.graphviz") ("3dml" . "text/vnd.in3d.3dml") ("spot" . "text/vnd.in3d.spot") ("jad" . "text/vnd.sun.j2me.app-descriptor") ("wml" . "text/vnd.wap.wml") ("wmls" . "text/vnd.wap.wmlscript") ("s" . "text/x-asm") ("c" . "text/x-c") ("f" . "text/x-fortran") ("java" . "text/x-java-source") ("opml" . "text/x-opml") ("p" . "text/x-pascal") ("nfo" . "text/x-nfo") ("etx" . "text/x-setext") ("sfv" . "text/x-sfv") ("uu" . "text/x-uuencode") ("vcs" . "text/x-vcalendar") ("vcf" . "text/x-vcard") ("3gp" . "video/3gpp") ("3g2" . "video/3gpp2") ("h261" . "video/h261") ("h263" . "video/h263") ("h264" . "video/h264") ("jpgv" . "video/jpeg") ("jpm" . "video/jpm") ("mj2" . "video/mj2") ("ts" . "video/mp2t") ("mp4" . "video/mp4") ("mpeg" . "video/mpeg") ("ogv" . "video/ogg") ("qt" . "video/quicktime") ("uvh" . "video/vnd.dece.hd") ("uvm" . "video/vnd.dece.mobile") ("uvp" . "video/vnd.dece.pd") ("uvs" . "video/vnd.dece.sd") ("uvv" . "video/vnd.dece.video") ("dvb" . "video/vnd.dvb.file") ("fvt" . "video/vnd.fvt") ("mxu" . "video/vnd.mpegurl") ("pyv" . "video/vnd.ms-playready.media.pyv") ("uvu" . "video/vnd.uvvu.mp4") ("viv" . "video/vnd.vivo") ("dv" . "video/x-dv") ("webm" . "video/webm") ("f4v" . "video/x-f4v") ("fli" . "video/x-fli") ("flv" . "video/x-flv") ("m4v" . "video/x-m4v") ("mkv" . "video/x-matroska") ("mng" . "video/x-mng") ("asf" . "video/x-ms-asf") ("vob" . "video/x-ms-vob") ("wm" . "video/x-ms-wm") ("wmv" . "video/x-ms-wmv") ("wmx" . "video/x-ms-wmx") ("wvx" . "video/x-ms-wvx") ("avi" . "video/x-msvideo") ("movie" . "video/x-sgi-movie") ("smv" . "video/x-smv") ("ice" . "x-conference/x-cooltalk"))) (define (ext->mimetype ext) (let ((x (assoc ext ducttape_ext2mimetype))) (if x (cdr x) "text/plain"))) |
Added ducttape/sample_ducttape.scm version [d6ebb1f644].
> > > > | 1 2 3 4 | (include "ducttape-lib.scm") (import ducttape-lib) (inote "hello world") (exit 0) |
Added ducttape/test_ducttape.scm version [f1892fd163].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 | #!/usr/bin/env csi -script (use test) (include "ducttape-lib.scm") (import ducttape-lib) (import ansi-escape-sequences) (use trace) (set! systype (do-or-die (if (file-exists? "/bin/uname") "/bin/uname" "/usr/bin/uname"))) ;(trace skim-cmdline-opts-withargs-by-regex) ;(trace keyword-skim) ;(trace re-match?) (define (reset-ducttape) (unsetenv "DUCTTAPE_DEBUG_LEVEL") (ducttape-debug-level #f) (unsetenv "DUCTTAPE_DEBUG_PATTERN") (ducttape-debug-regex-filter ".") (unsetenv "DUCTTAPE_LOG_FILE") (ducttape-log-file #f) (unsetenv "DUCTTAPE_SILENT_MODE") (ducttape-silent-mode #f) (unsetenv "DUCTTAPE_QUIET_MODE") (ducttape-quiet-mode #f) (unsetenv "DUCTTAPE_COLOR_MODE") (ducttape-color-mode #f) ) (define (reset-ducttape-with-cmdline-list cmdline-list) (reset-ducttape) (command-line-arguments cmdline-list) (ducttape-process-command-line) ) (define (direct-iputs-test) (ducttape-color-mode #f) (ierr "I'm an error") (iwarn "I'm a warning") (inote "I'm a note") (ducttape-debug-level 1) (idbg "I'm a debug statement") (ducttape-debug-level #f) (idbg "I'm a hidden debug statement") (ducttape-silent-mode #t) (iwarn "I shouldn't show up") (inote "I shouldn't show up either") (ierr "I should show up 1") (ducttape-silent-mode #f) (ducttape-quiet-mode #t) (iwarn "I should show up 2") (inote "I shouldn't show up though") (ierr "I should show up 3") (ducttape-quiet-mode #f) (ducttape-debug-level 1) (idbg "foo") (iputs "dbg" "debug message") (iputs "e" "error message") (iputs "w" "warning message") (iputs "n" "note message") (ducttape-color-mode #t) (ierr "I'm an error COLOR") (iwarn "I'm a warning COLOR") (inote "I'm a note COLOR") (idbg "I'm a debug COLOR") ) (define (test-argprocessor-funcs) (test-group "Command line processor utility functions" (set! testargs1 '( "-d" "-d" "-d3" "-ddd" "-foo" "fooarg" "-foo" "fooarg2" "-lastArgIsDecoy" "-foo")) (command-line-arguments testargs1) (set! expected_result '("-d" "-d" "-d3" "-ddd")) (set! expected_sideeffect '("-foo" "fooarg" "-foo" "fooarg2" "-lastArgIsDecoy" "-foo")) (test "skim-cmdline-opts-noarg-by-regex result" expected_result (skim-cmdline-opts-noarg-by-regex "-d(d+|\\d+)?")) (test "skim-cmdline-opts-noarg-by-regex sideeffect" expected_sideeffect (command-line-arguments)) (command-line-arguments testargs1) (set! expected_result '("fooarg" "fooarg2" )) (set! expected_sideeffect '( "-d" "-d" "-d3" "-ddd" "-lastArgIsDecoy" "-foo")) (test "skim-cmdline-opts-withargs-by-regex result" expected_result (skim-cmdline-opts-withargs-by-regex "--?foo")) (test "skim-cmdline-opts-withargs-by-regex sideeffect" expected_sideeffect (command-line-arguments)) )) (define (test-misc) (test-group "misc" (let ((tmpfile (mktemp))) (test-assert "mktemp: temp file created" (file-exists? tmpfile)) (if (file-exists? tmpfile) (delete-file tmpfile)) ))) (define (test-systemstuff) (test-group "system commands" (let-values (((ec o e) (isys (find-exe "true")))) (test-assert "isys: /bin/true should have exit code 0" (equal? ec 0))) (let-values (((ec o e) (isys (find-exe "false")))) (test-assert "isys: /bin/false should have exit code 1" (equal? ec 1))) (let-values (((ec o e) (isys "/bin/echo" "foo" "bar" "baz"))) (test-assert "isys: /bin/echo should have exit code 0" (equal? ec 0)) (test-assert "isys: /bin/echo should have stdout 'foo bar baz'" (equal? o "foo bar baz"))) (let-values (((ec o e) (isys "/bin/ls /zzzzz"))) (let ((expected-code (if (equal? systype "Darwin") 1 2)) (expected-err (if (equal? systype "Darwin") "ls: /zzzzz: No such file or directory" "/bin/ls: cannot access /zzzzz: No such file or directory")) ) (test "isys: /bin/ls /zzzzz should have exit code 2" expected-code ec) (test "isys: /bin/ls /zzzzz should have empty stdout" "" o) (test "isys: /bin/ls /zzzzz should have stderr" expected-err e)) ) (let-values (((ec o e) (isys "/bin/ls /etc/passwd"))) (test "isys: /bin/ls /etc/passwd should have exit code 0" 0 ec) (test "isys: /bin/ls /etc/passwd should have stdout" "/etc/passwd" o) (test "isys: /bin/ls /etc/passwd should have empty stderr" "" e)) (let ((res (do-or-die "/bin/ls /etc/passwd"))) (test "do-or-die: ls /etc/passwd should work" "/etc/passwd" res )) (let ((res (do-or-die "/bin/ls /zzzzz" nodie: #t))) (test "do-or-die: ls /zzzzz should die" #f res )) ; test reading from process stdout line at a time (let* ( (lineno (counter-maker)) ; print each line with an index (eachline-fn (lambda (line) (print "GOTLINE " (lineno) "> " line))) (res (do-or-die "/bin/ls -l /etc | head; true" foreach-stdout: eachline-fn ))) (test-assert "ls -l /etc should not be empty" (not (equal? res "")))) ;; test writing to process stdout line at a time (let* ((tmpfile (mktemp)) (cmd (conc "cat > " tmpfile))) (let-values (((c o e) (isys cmd stdin-proc: (lambda (myport) (write-line "hello" myport) (write-line "hello2" myport) (close-output-port myport))))) (test "isys-sp: cat should exit 0" 0 c) (let ((mycmd (conc "cat " tmpfile))) (test "isys-sp: cat output should match input" "hello\nhello2" (do-or-die mycmd))) (delete-file tmpfile) )) (let* ((tmpfile (mktemp)) (cmd (conc "cat > " tmpfile))) (do-or-die cmd stdin-proc: (lambda (myport) (write-line "hello" myport) (write-line "hello2" myport) (close-output-port myport)) cmd) (test "dod-sp: cat output should match input" "hello\nhello2" (do-or-die (conc "cat " tmpfile))) (delete-file tmpfile)) (let* ((thefile (conc "/tmp/" (get-environment-variable "USER") "9-lines")) (counter (counter-maker)) (stdin-writer (lambda () (if (< (counter) 10) (number->string (counter 0)) #f))) (cmd (conc "cat > " thefile))) (let-values (((c o e) (isys cmd foreach-stdin-thunk: stdin-writer))) (test-assert "isys-fsl: cat should return 0" (equal? c 0)) (test-assert "isys-fsl: cat should have written a file" (file-exists? thefile)) (if (file-exists? thefile) (begin (test "isys-fsl: cat file should have right contents" "1\n2\n3\n4\n5\n6\n7\n8\n9" (do-or-die (conc "cat " thefile))) (delete-file thefile))))) ) ; end test-group ) ; end define (define (test-argprocessor ) (test-group "Command line processor parameter settings" (reset-ducttape-with-cmdline-list '()) (test-assert "(nil) debug mode should be off" (not (ducttape-debug-level))) (test-assert "(nil): debug pattern should be '.'" (equal? "." (ducttape-debug-regex-filter))) (test-assert "(nil): colors should be off" (not (ducttape-color-mode))) (test-assert "(nil): silent mode should be off" (not (ducttape-silent-mode))) (test-assert "(nil): quiet mode should be off" (not (ducttape-quiet-mode))) (test-assert "(nil): logfile should be off" (not (ducttape-log-file))) (reset-ducttape-with-cmdline-list '("-d")) (test-assert "-d: debug mode should be on at level 1" (eq? 1 (ducttape-debug-level))) (reset-ducttape-with-cmdline-list '("-dd")) (test "-dd: debug level should be 2" 2 (ducttape-debug-level)) (reset-ducttape-with-cmdline-list '("-ddd")) (test "-ddd: debug level should be 3" 3 (ducttape-debug-level)) (reset-ducttape-with-cmdline-list '("-d2")) (test "-d2: debug level should be 2" 2 (ducttape-debug-level)) (reset-ducttape-with-cmdline-list '("-d3")) (test "-d3: debug level should be 3" 3 (ducttape-debug-level)) (reset-ducttape-with-cmdline-list '("-dp" "foo")) (test "-dp foo: debug pattern should be 'foo'" "foo" (ducttape-debug-regex-filter)) (reset-ducttape-with-cmdline-list '("--debug-pattern" "foo")) (test "--debug-pattern foo: debug pattern should be 'foo'" "foo" (ducttape-debug-regex-filter)) (reset-ducttape-with-cmdline-list '("-dp" "foo" "-dp" "bar")) (test "-dp foo -dp bar: debug pattern should be 'foo|bar'" "foo|bar" (ducttape-debug-regex-filter)) (reset-ducttape-with-cmdline-list '("--quiet")) (test-assert "-quiet: quiet mode should be active" (ducttape-quiet-mode)) (reset-ducttape-with-cmdline-list '("--silent")) (test-assert "-silent: silent mode should be active" (ducttape-silent-mode)) (reset-ducttape-with-cmdline-list '("--color")) (test-assert "-color: color mode should be active" (ducttape-color-mode)) (reset-ducttape-with-cmdline-list '("--log" "foo")) (test "--log foo: logfile should be 'foo'" "foo" (ducttape-log-file)) )) (define (test-wwdate) (test-group "wwdate conversion tests" (let ((test-table '(("16ww01.5" . "2016-01-01") ("16ww18.5" . "2016-04-29") ("1999ww33.5" . "1999-08-13") ("16ww18.4" . "2016-04-28") ("16ww18.3" . "2016-04-27") ("13ww01.0" . "2012-12-30") ("13ww52.6" . "2013-12-28") ("16ww53.3" . "2016-12-28")))) (for-each (lambda (test-pair) (let ((wwdate (car test-pair)) (isodate (cdr test-pair))) (test (conc "(isodate->wwdate "isodate ") => "wwdate) wwdate (isodate->wwdate isodate)) (test (conc "(wwdate->isodate "wwdate ") => "isodate) isodate (wwdate->isodate wwdate)))) test-table)))) (define (main) ;; (test <description; #f uses func prototype> <expected result> <thunk>) ; (test-group "silly settext group" ; (test #f "\x1b[1mfoo\x1b[0m" (set-text (list 'bold) "foo")) ; (test "settext bold" "\x1b[1mfoo\x1b[0m" (set-text (list 'bold) "foo")) ; ) ; visually inspect this (direct-iputs-test) ; following use unit test test-egg (reset-ducttape) (test-argprocessor-funcs) (reset-ducttape) (test-argprocessor) (test-systemstuff) (test-misc) (test-wwdate) ) ; end main() (main) (sendmail "brandon.j.barclay@intel.com" "6hello subject" "test body" ) ;(let* ((image-file "/nfs/site/home/bjbarcla/megatest-logo.png") ; (cid "mtlogo") ; (image-alist (list (cons image-file cid))) ; (body (conc "Hello world<br /><img cid:"cid" alt=\"test image\"><br>bye!"))) ; (sendmail "brandon.j.barclay@intel.com" "7hello subject" body use_html: #t images-with-content-id-alist: image-alist) ; (print "sent image mail")) ;(sendmail "bjbarcla" "2hello subject html" "test body<h1>hello</h1><i>italics</i>" use_html: #t) ;(sendmail "bb" "4hello attach subject html" "<h2>hmm</h2>" use_html: #t attach-files-list: '( "/Users/bb/Downloads/wdmycloud-manual-4779-705103.pdf" ) ) ;(launch-repl) (test-exit) |
Added ducttape/test_example.scm version [74b706bd1d].
> > > | 1 2 3 | (use ducttape-lib) (inote "Hello world") |
Added ducttape/useargs-example.scm version [c73af521bf].
> > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | (use ducttape-lib) (let ( (customers (skim-cmdline-opts-withargs-by-regex "--cust(omer)?")) (magicmode (skim-cmdline-opts-noarg-by-regex "--magic")) ) (print "your customers are " customers) (if (null? magicmode) (print "no unicorns for you") (print "magic!") ) ) (idbg "hello") (idbg "hello2" 2) (idbg "hello2" 3) (inote "note") (iwarn "warn") (ierr "err") |
Added ducttape/workweekdate.scm version [075bec1c4d].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | (use srfi-19) (use test) ;;(use format) (use regex) ;(declare (unit wwdate)) ;; utility procedures to convert among ;; different ways to express date (wwdate, seconds since epoch, isodate) ;; ;; samples: ;; isodate -> "2016-01-01" ;; wwdate -> "16ww01.5" ;; seconds -> 1451631600 ;; procedures provided: ;; ==================== ;; seconds->isodate ;; seconds->wwdate ;; ;; isodate->seconds ;; isodate->wwdate ;; ;; wwdate->seconds ;; wwdate->isodate ;; srfi-19 used extensively; this doc is better tha the eggref: ;; http://srfi.schemers.org/srfi-19/srfi-19.html ;; Author: brandon.j.barclay@intel.com 16ww18.6 (define (date->seconds date) (inexact->exact (string->number (date->string date "~s")))) (define (seconds->isodate seconds) (let* ((date (seconds->date seconds)) (result (date->string date "~Y-~m-~d"))) result)) (define (isodate->seconds isodate) "Takes a string input of the form 'YY-MM-DD' or 'YYYY-MM-DD' and returns epoch time; for YY, assume after Y2K" (let* ((numlist (map string->number (string-split isodate "-"))) (raw-year (car numlist)) (year (if (< raw-year 100) (+ raw-year 2000) raw-year)) (month (list-ref numlist 1)) (day (list-ref numlist 2)) (date (make-date 0 0 0 0 day month year)) (seconds (date->seconds date))) seconds)) ;; adapted from perl Intel::WorkWeek perl module ;; workweek year consists of numbered weeks starting from week 1 ;; days of week are numbered starting from 0 on sunday ;; weeks begin on sunday- day number 0 and end saturday- day 6 ;; week 1 is defined as the week containing jan 1 of the year ;; workweek year does not match calendar year in workweek 1 ;; since workweek 1 contains jan1 and workweek begins sunday, ;; days prior to jan1 in workweek 1 belong to the next workweek year (define (seconds->wwdate-values seconds) (define (date-difference->seconds d1 d2) (- (date->seconds d1) (date->seconds d2))) (let* ((thisdate (seconds->date seconds)) (thisdow (string->number (date->string thisdate "~w"))) (year (date-year thisdate)) ;; intel workweek 1 begins on sunday of week containing jan1 (jan1 (make-date 0 0 0 0 1 1 year)) (jan1dow (date-week-day jan1)) (ww01 (date-subtract-duration jan1 (seconds->time (* 60 60 24 jan1dow)))) (ww01_delta_seconds (date-difference->seconds thisdate ww01)) (wwnum_initial (inexact->exact (add1 (floor (/ ww01_delta_seconds 24 3600 7) )))) ;; we could be in ww1 of next year (this-saturday (seconds->date (+ seconds (* 60 60 24 (- 6 thisdow))))) (this-week-ends-next-year? (> (date-year this-saturday) year)) (intelyear (if this-week-ends-next-year? (add1 year) year)) (intelweek (if this-week-ends-next-year? 1 wwnum_initial))) (values intelyear intelweek thisdow))) (define (string-leftpad in width pad-char) (let* ((unpadded-str (->string in)) (padlen_temp (- width (string-length unpadded-str))) (padlen (if (< padlen_temp 0) 0 padlen_temp)) (padding (make-string padlen pad-char))) (conc padding unpadded-str))) (define (string-rightpad in width pad-char) (let* ((unpadded-str (->string in)) (padlen_temp (- width (string-length unpadded-str))) (padlen (if (< padlen_temp 0) 0 padlen_temp)) (padding (make-string padlen pad-char))) (conc unpadded-str padding))) (define (zeropad num width) (string-leftpad num width #\0)) (define (seconds->wwdate seconds) (let-values (((intelyear intelweek day-of-week-num) (seconds->wwdate-values seconds))) (let ((intelyear-str (zeropad (->string (if (> intelyear 1999) (- intelyear 2000) intelyear)) 2)) (intelweek-str (zeropad (->string intelweek) 2)) (dow-str (->string day-of-week-num))) (conc intelyear-str "ww" intelweek-str "." dow-str)))) (define (isodate->wwdate isodate) (seconds->wwdate (isodate->seconds isodate))) (define (wwdate->seconds wwdate) (let ((match (string-match "^(\\d+)ww(\\d+).(\\d)$" wwdate))) (if (not match) #f (let* ( (intelyear-raw (string->number (list-ref match 1))) (intelyear (if (< intelyear-raw 100) (+ intelyear-raw 2000) intelyear-raw)) (intelww (string->number (list-ref match 2))) (dayofweek (string->number (list-ref match 3))) (day-of-seconds (* 60 60 24 )) (week-of-seconds (* day-of-seconds 7)) ;; get seconds at ww1.0 (new-years-date (make-date 0 0 0 0 1 1 intelyear)) (new-years-seconds (date->seconds new-years-date)) (new-years-dayofweek (date-week-day new-years-date)) (ww1.0_seconds (- new-years-seconds (* day-of-seconds new-years-dayofweek))) (workweek-adjustment (* week-of-seconds (sub1 intelww))) (weekday-adjustment (* dayofweek day-of-seconds)) (result (+ ww1.0_seconds workweek-adjustment weekday-adjustment))) result)))) (define (wwdate->isodate wwdate) (seconds->isodate (wwdate->seconds wwdate))) (define (current-wwdate) (seconds->wwdate (current-seconds))) (define (current-isodate) (seconds->isodate (current-seconds))) (define (wwdate-tests) (test-group "date conversion tests" (let ((test-table '(("16ww01.5" . "2016-01-01") ("16ww18.5" . "2016-04-29") ("1999ww33.5" . "1999-08-13") ("16ww18.4" . "2016-04-28") ("16ww18.3" . "2016-04-27") ("13ww01.0" . "2012-12-30") ("13ww52.6" . "2013-12-28") ("16ww53.3" . "2016-12-28")))) (for-each (lambda (test-pair) (let ((wwdate (car test-pair)) (isodate (cdr test-pair))) (test (conc "(isodate->wwdate "isodate ") => "wwdate) wwdate (isodate->wwdate isodate)) (test (conc "(wwdate->isodate "wwdate ") => "isodate) isodate (wwdate->isodate wwdate)))) test-table)))) |
Modified megamod.scm from [72c329a55f] to [950fd3028d].
︙ | ︙ | |||
39 40 41 42 43 44 45 46 47 48 49 50 51 52 | ;; (declare (uses runconfigmod)) (declare (uses runsmod)) ;; (declare (uses servermod)) ;; (declare (uses subrunmod)) ;; (declare (uses tasksmod)) (declare (uses testsmod)) ;; (declare (uses vgmod)) (module megamod * (import scheme chicken data-structures extras) (use (prefix base64 base64:) | > > > > | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | ;; (declare (uses runconfigmod)) (declare (uses runsmod)) ;; (declare (uses servermod)) ;; (declare (uses subrunmod)) ;; (declare (uses tasksmod)) (declare (uses testsmod)) ;; (declare (uses vgmod)) (declare (uses pkts)) (declare (uses mtargs)) (declare (uses mtconfigf)) (declare (uses ducttape-lib)) (module megamod * (import scheme chicken data-structures extras) (use (prefix base64 base64:) |
︙ | ︙ | |||
67 68 69 70 71 72 73 | http-client intarweb irregex matchable md5 message-digest pathname-expand | | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | http-client intarweb irregex matchable md5 message-digest pathname-expand ;; pkts ports posix ;; queue regex regex-case s11n sparse-vectors |
︙ | ︙ | |||
93 94 95 96 97 98 99 | tcp typed-records udp uri-common z3 ) | | | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | tcp typed-records udp uri-common z3 ) (import (prefix mtconfigf configf:)) (define read-config configf:read-config) (define find-and-read-config configf:find-and-read-config) (define config:eval-string-in-environment configf:eval-string-in-environment) (import spiffy) ;; (import apimod) |
︙ | ︙ | |||
122 123 124 125 126 127 128 129 130 131 132 133 134 135 | ;; (import runconfigmod) (import runsmod) ;; (import servermod) ;; (import subrunmod) ;; (import tasksmod) (import testsmod) ;; (import vgmod) (use (prefix ulex ulex:)) (include "common_records.scm") (include "db_records.scm") (include "key_records.scm") (include "run_records.scm") | > > > | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | ;; (import runconfigmod) (import runsmod) ;; (import servermod) ;; (import subrunmod) ;; (import tasksmod) (import testsmod) ;; (import vgmod) (import pkts) (import (prefix mtargs args:)) (import ducttape-lib) (use (prefix ulex ulex:)) (include "common_records.scm") (include "db_records.scm") (include "key_records.scm") (include "run_records.scm") |
︙ | ︙ | |||
168 169 170 171 172 173 174 | (include "common-inc.scm") ;; L5 (include "db-inc.scm") ;; L4 (include "env-inc.scm") (include "http-transport-inc.scm") (include "items-inc.scm") ;; (include "keys-inc.scm") (include "launch-inc.scm") ;; L1 | | | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | (include "common-inc.scm") ;; L5 (include "db-inc.scm") ;; L4 (include "env-inc.scm") (include "http-transport-inc.scm") (include "items-inc.scm") ;; (include "keys-inc.scm") (include "launch-inc.scm") ;; L1 ;; (include "margs-inc.scm") (include "mt-inc.scm") (include "ods-inc.scm") ;; L1 (include "pgdb-inc.scm") (include "portlogger-inc.scm") (include "process-inc.scm") ;; L6 (include "rmt-inc.scm") ;; L2 (include "runconfig-inc.scm") |
︙ | ︙ |
Modified megatest.scm from [2845293d3c] to [d6e6748073].
︙ | ︙ | |||
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | (import dbmod) (declare (uses runsmod)) (import runsmod) (declare (uses testsmod)) (import testsmod) (declare (uses megamod)) (import megamod) ;; invoke the imports (declare (uses commonmod.import)) (declare (uses testsmod.import)) (declare (uses rmtmod.import)) (declare (uses runsmod.import)) (declare (uses megamod.import)) (configf:set-debug-printers debug:print debug:print-info debug:print-error *default-log-port*) ;; (declare (uses tdb)) ;; (declare (uses mt)) ;; (declare (uses api)) ;; (declare (uses tasks)) ;; only used for debugging. | > > > > > > > > > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | (import dbmod) (declare (uses runsmod)) (import runsmod) (declare (uses testsmod)) (import testsmod) (declare (uses megamod)) (import megamod) (declare (uses mtargs)) (import (prefix mtargs args:)) (declare (uses mtconfigf)) (import (prefix mtconfigf configf:)) (declare (uses ducttape-lib)) (import ducttape-lib) ;; invoke the imports (declare (uses commonmod.import)) (declare (uses testsmod.import)) (declare (uses rmtmod.import)) (declare (uses runsmod.import)) (declare (uses megamod.import)) (declare (uses mtargs.import)) (declare (uses mtconfigf.import)) (declare (uses ducttape-lib.import)) (configf:set-debug-printers debug:print debug:print-info debug:print-error *default-log-port*) ;; (declare (uses tdb)) ;; (declare (uses mt)) ;; (declare (uses api)) ;; (declare (uses tasks)) ;; only used for debugging. |
︙ | ︙ |
Added mtargs.scm version [1e6b59e54f].
> > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ;;====================================================================== ;; Copyright 2019, Matthew Welland. ;; ;; This file is part of Megatest. ;; ;; Megatest is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; Megatest is distributed in the hope that 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 Megatest. If not, see <http://www.gnu.org/licenses/>. ;;====================================================================== (declare (unit mtargs)) (include "mtargs/mtargs.scm") |
Added mtargs/Makefile version [f71e390f41].
> > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # Copyright 2007-2010, Matthew Welland. # # This program is made available under the GNU GPL version 2.0 or # greater. See the accompanying file COPYING for details. # # This program is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR # PURPOSE. # TARGDIR = $(shell csi -e "(print (car \#\#sys\#include-pathnames))(exit)") all : uptodate.log # $(TARGDIR)/mtargs.so uptodate.log : mtargs.scm mtargs.setup chicken-install | tee uptodate.log $(TARGDIR)/mtargs.so : mtargs.so @echo installing to $(TARGDIR) cp mtargs.so $(TARGDIR) mtargs.so : mtargs.scm csc -s mtargs.scm |
Added mtargs/mtargs.meta version [65ccfb2eb7].
> > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | ( ; Your egg's license: (license "LGPL") ; Pick one from the list of categories (see below) for your egg and enter it ; here. (category misc) ; A list of eggs mpeg3 depends on. If none, you can omit this declaration ; altogether. If you are making an egg for chicken 3 and you need to use ; procedures from the `files' unit, be sure to include the `files' egg in the ; `needs' section (chicken versions < 3.4.0 don't provide the `files' unit). ; `depends' is an alias to `needs'. (needs srfi-69 srfi-1) ; A list of eggs required for TESTING ONLY. See the `Tests' section. (test-depends test) (author "Matt Welland") (synopsis "Primitive argument processor.")) |
Added mtargs/mtargs.scm version [73a7b43ccf].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | ;; Copyright 2007-2010, Matthew Welland. ;; ;; This file is part of mtargs. ;; ;; mtargs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; mtargs is distributed in the hope that 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 mtargs. If not, see <http://www.gnu.org/licenses/>. (module mtargs ( arg-hash get-arg get-arg-from usage get-args print-args any-defined? help ) (import scheme chicken data-structures extras posix ports files) (use srfi-69 srfi-1) (define arg-hash (make-hash-table)) (define help "") (define (get-arg arg . default) (if (null? default) (hash-table-ref/default arg-hash arg #f) (hash-table-ref/default arg-hash arg (car default)))) (define (any-defined? . args) (not (null? (filter (lambda (x) x) (map get-arg args))))) (define (get-arg-from ht arg . default) (if (null? default) (hash-table-ref/default ht arg #f) (hash-table-ref/default ht arg (car default)))) (define (usage . args) (if (> (length args) 0) (apply print "ERROR: " args)) (if (string? help) (print help) (print "Usage: " (car (argv)) " ... ")) (exit 0)) (define (get-args args params switches arg-hash num-needed) (let* ((numtargs (length args)) (adj-num-needed (if num-needed (+ num-needed 2) #f))) (if (< numtargs (if adj-num-needed adj-num-needed 2)) (if (>= num-needed 1) (usage "No arguments provided") '()) (let loop ((arg (cadr args)) (tail (cddr args)) (remtargs '())) (cond ((member arg params) ;; args with params (if (< (length tail) 1) (usage "param given without argument " arg) (let ((val (car tail)) (newtail (cdr tail))) (hash-table-set! arg-hash arg val) (if (null? newtail) remtargs (loop (car newtail)(cdr newtail) remtargs))))) ((member arg switches) ;; args with no params (i.e. switches) (hash-table-set! arg-hash arg #t) (if (null? tail) remtargs (loop (car tail)(cdr tail) remtargs))) (else (if (null? tail)(append remtargs (list arg)) ;; return the non-used args (loop (car tail)(cdr tail)(append remtargs (list arg)))))))) )) (define (print-args remtargs arg-hash) (print "ARGS: " remtargs) (for-each (lambda (arg) (print " " arg " " (hash-table-ref/default arg-hash arg #f))) (hash-table-keys arg-hash))) ) |
Added mtargs/mtargs.setup version [8300885e1f].
> > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ;; Copyright 2007-2010, Matthew Welland. ;; ;; This program is made available under the GNU GPL version 2.0 or ;; greater. See the accompanying file COPYING for details. ;; ;; This program is distributed WITHOUT ANY WARRANTY; without even the ;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ;; PURPOSE. ;;;; mtargs.setup ;; compile the code into a dynamically loadable shared object ;; (will generate mtargs.so) (compile -s mtargs.scm) ;; Install as extension library (standard-extension 'mtargs "mtargs.so") |
Added mtconfigf.scm version [dd571ebac6].
> > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ;;====================================================================== ;; Copyright 2019, Matthew Welland. ;; ;; This file is part of Megatest. ;; ;; Megatest is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; Megatest is distributed in the hope that 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 Megatest. If not, see <http://www.gnu.org/licenses/>. ;;====================================================================== (declare (unit mtconfigf)) (include "mtconfigf/mtconfigf.scm") |
Added mtconfigf/Makefile version [b67298756b].
> > | 1 2 | test: env CHICKEN_REPOSITORY=../../../megatest/tmpinstall/eggs/lib/chicken/7 csi -s tests/run.scm |
Added mtconfigf/mtconfigf.meta version [9fb56292e9].
> > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | ( ; Your egg's license: (license "LGPL") ; Pick one from the list of categories (see below) for your egg and enter it ; here. (category misc) ; A list of eggs mpeg3 depends on. If none, you can omit this declaration ; altogether. If you are making an egg for chicken 3 and you need to use ; procedures from the `files' unit, be sure to include the `files' egg in the ; `needs' section (chicken versions < 3.4.0 don't provide the `files' unit). ; `depends' is an alias to `needs'. (needs srfi-1 srfi-69 regex regex-case directory-utils extras srfi-13 posix typed-records) ; A list of eggs required for TESTING ONLY. See the `Tests' section. (test-depends test) (author "Matt Welland") (synopsis "Megatest config file (ini-space format) with many enhancements.")) |
Added mtconfigf/mtconfigf.scm version [f14586a434].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 | ;;====================================================================== ;; Copyright 2006-2018, Matthew Welland. ;; ;; This file is part of Megatest. ;; ;; Megatest is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; Megatest is distributed in the hope that 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 Megatest. If not, see <http://www.gnu.org/licenses/>. ;; ;;====================================================================== ;; NOTE: This is the configf module, long term it will replace configf.scm. (module mtconfigf ( set-debug-printers lazy-convert assoc-safe-add section-var-set! safe-file-exists? read-link-f nice-path eval-string-in-environment safe-setenv with-env-vars cmd-run->list port->list configf:system process-line shell configf:read-line cfgdat->env-alist calc-allow-system apply-wildcards val->alist section->val-alist read-config find-config find-and-read-config lookup var-is? lookup-number section-vars get-section set-section-var compress-multi-lines expand-multi-lines file->list write-config write-merge-config read-refdb map-all-hier-alist config->alist alist->config read-alist write-alist config->ini ;;set-verbosity add-eval-string get-eval-string squelch-debug-prints ;; misc realpath find-chicken-lib ) (import scheme chicken data-structures extras ports files) (use posix typed-records srfi-18 pathname-expand posix-extras) (use regex regex-case srfi-69 srfi-1 directory-utils extras srfi-13 ) (use srfi-69) (import posix) ;; stub debug printers overridden by set-debug-printers (define (debug:print n e . args) (apply print args)) (define (debug:print-info n e . args) (apply print "INFO: " args)) (define (debug:print-error n e . args) (apply print "ERROR: " args)) ;;(import (prefix mtdebug debug:)) ;;(define args:any? args:any-defined?) ;; cannot name it any? in mtargs module ;; FROM common.scm ;; ;; this plugs a hole in posix-extras in recent chicken versions > 4.9) (let-values (( (chicken-release-number chicken-major-version) (apply values (map string->number (take (string-split (chicken-version) ".") 2))))) (if (or (> chicken-release-number 4) (and (eq? 4 chicken-release-number) (> chicken-major-version 9))) (define ##sys#expand-home-path pathname-expand))) ;;(define (set-verbosity v)(debug:set-verbosity v)) (define *default-log-port* (current-error-port)) (define (debug:print-error n . args) ;;; n available to end-users but ignored for ;; default provided function (with-output-to-port (current-error-port) (lambda () (apply print "ERROR: "args)))) (define (set-debug-printers normal-fn info-fn error-fn default-port) (if error-fn (set! debug:print-error error-fn)) (if info-fn (set! debug:print-info info-fn)) (if normal-fn (set! debug:print normal-fn)) (if default-port (set! *default-log-port* default-port))) (define (squelch-debug-prints) (let ((noop (lambda x #f))) (set! debug:print noop) (set! debug:print-info noop))) ;; if it looks like a number -> convert it to a number, else return it ;; (define (lazy-convert inval) (let* ((as-num (if (string? inval)(string->number inval) #f))) (or as-num inval))) (define *eval-string* "") (define (add-eval-string str) (if (not (string-contains *eval-string* str)) (set! *eval-string* (conc *eval-string* " " str)))) (define (get-eval-string) *eval-string*) ;; Moved to common ;; ;; return list (path fullpath configname) (define (find-config configname #!key (toppath #f)) (if toppath (let ((cfname (conc toppath "/" configname))) (if (safe-file-exists? cfname) (list toppath cfname configname) (list #f #f #f))) (let* ((cwd (string-split (current-directory) "/"))) (let loop ((dir cwd)) (let* ((path (conc "/" (string-intersperse dir "/"))) (fullpath (conc path "/" configname))) (if (safe-file-exists? fullpath) (list path fullpath configname) (let ((remcwd (take dir (- (length dir) 1)))) (if (null? remcwd) (list #f #f #f) ;; #f #f) (loop remcwd))))))))) (define (assoc-safe-add alist key val #!key (metadata #f)) (let ((newalist (filter (lambda (x)(not (equal? key (car x)))) alist))) (append newalist (list (if metadata (list key val metadata) (list key val)))))) (define (section-var-set! cfgdat section-name var value #!key (metadata #f)) (hash-table-set! cfgdat section-name (assoc-safe-add (hash-table-ref/default cfgdat section-name '()) var value metadata: metadata))) ;;====================================================================== ;; Environment handling stuff ;;====================================================================== (define (safe-file-exists? path) (handle-exceptions exn #f (file-exists? path))) (define (read-link-f path) (handle-exceptions exn (begin (debug:print-error 0 *default-log-port* "command \"/bin/readlink -f " path "\" failed.") path) ;; just give up (with-input-from-pipe (conc "/bin/readlink -f " path) (lambda () (read-line))))) ;; return a nice clean pathname made absolute (define (nice-path dir) (let ((match (string-match "^(~[^\\/]*)(\\/.*|)$" dir))) (if match ;; using ~ for home? (nice-path (conc #;(read-link-f (cadr match)) (realpath (cadr match)) "/" (caddr match))) (normalize-pathname (if (absolute-pathname? dir) dir (conc (current-directory) "/" dir)))))) (define (eval-string-in-environment str) (handle-exceptions exn (begin (debug:print-error 0 *default-log-port* "problem evaluating \"" str "\" in the shell environment") #f) (let ((cmdres (cmd-run->list (conc "echo " str)))) (if (null? cmdres) "" (caar cmdres))))) (define (safe-setenv key val) (if (substring-index ":" key) ;; variables containing : are for internal use and cannot be environment variables. (debug:print-error 4 *default-log-port* "skip setting internal use only variables containing \":\"") (if (and (string? val) (string? key)) (handle-exceptions exn (debug:print-error 0 *default-log-port* "bad value for setenv, key=" key ", value=" val) (setenv key val)) (debug:print-error 0 *default-log-port* "bad value for setenv, key=" key ", value=" val)))) ;; accept an alist or hash table containing envvar/env value pairs (value of #f causes unset) ;; execute thunk in context of environment modified as per this list ;; restore env to prior state then return value of eval'd thunk. ;; ** this is not thread safe ** (define (with-env-vars delta-env-alist-or-hash-table thunk) (let* ((delta-env-alist (if (hash-table? delta-env-alist-or-hash-table) (hash-table->alist delta-env-alist-or-hash-table) delta-env-alist-or-hash-table)) (restore-thunks (filter identity (map (lambda (env-pair) (let* ((env-var (car env-pair)) (new-val (let ((tmp (cdr env-pair))) (if (list? tmp) (car tmp) tmp))) (current-val (get-environment-variable env-var)) (restore-thunk (cond ((not current-val) (lambda () (unsetenv env-var))) ((not (string? new-val)) #f) ((eq? current-val new-val) #f) (else (lambda () (setenv env-var current-val)))))) ;;(when (not (string? new-val)) ;; (debug:print 0 *default-log-port* " PROBLEM: not a string: "new-val"\n from env-alist:\n"delta-env-alist) ;; (pp delta-env-alist) ;; (exit 1)) (cond ((not new-val) ;; modify env here (unsetenv env-var)) ((string? new-val) (setenv env-var new-val))) restore-thunk)) delta-env-alist)))) (let ((rv (thunk))) (for-each (lambda (x) (x)) restore-thunks) ;; restore env to original state rv))) (define (cmd-run->list cmd #!key (delta-env-alist-or-hash-table '())) (with-env-vars delta-env-alist-or-hash-table (lambda () (let* ((fh (open-input-pipe cmd)) (res (port->list fh)) (status (close-input-pipe fh))) (list res status))))) (define (port->list fh) (if (eof-object? fh) #f (let loop ((curr (read-line fh)) (result '())) (if (not (eof-object? curr)) (loop (read-line fh) (append result (list curr))) result)))) ;;====================================================================== ;; Make the regexp's needed globally available ;;====================================================================== (define configf:include-rx (regexp "^\\[include\\s+(.*)\\]\\s*$")) (define configf:script-rx (regexp "^\\[scriptinc\\s+(\\S+)([^\\]]*)\\]\\s*$")) ;; include output from a script (define configf:section-rx (regexp "^\\[(.*)\\]\\s*$")) (define configf:blank-l-rx (regexp "^\\s*$")) (define configf:key-sys-pr (regexp "^(\\S+)\\s+\\[system\\s+(\\S+.*)\\]\\s*$")) (define configf:key-val-pr (regexp "^(\\S+)(\\s+(.*)|())$")) (define configf:key-no-val (regexp "^(\\S+)(\\s*)$")) (define configf:comment-rx (regexp "^\\s*#.*")) (define configf:cont-ln-rx (regexp "^(\\s+)(\\S+.*)$")) (define configf:settings (regexp "^\\[configf:settings\\s+(\\S+)\\s+(\\S+)]\\s*$")) (define configf:initstr-rx (regexp "^\\[configf:initstr\\s+(.*)\\]\\s*$")) ;; read a line and process any #{ ... } constructs (define configf:var-expand-regex (regexp "^(.*)#\\{(scheme|system|shell|getenv|get|runconfigs-get|rget|scm|sh|rp|gv|g|mtrah)\\s+([^\\}\\{]*)\\}(.*)")) (define (configf:system ht cmd) (system cmd) ) ;; Lookup a value in runconfigs based on -reqtarg or -target ;; (define (runconfigs-get config var) ;; .dvars is a special bin for storing metadata such as target (let ((targ (lookup config ".dvars" "target"))) ;; (common:args-get-target))) ;; (or (args:get-arg "-reqtarg")(args:get-arg "-target")(getenv "MT_TARGET")))) (if targ (or (lookup config targ var) (lookup config "default" var)) (lookup config "default" var)))) (define (realpath x) (let ((currdir (current-directory))) (handle-exceptions exn (begin (change-directory currdir) x) ;; anything goes wrong - return given path (change-directory x) (let ((result (current-directory))) (change-directory currdir) result)))) ;; (resolve-pathname (pathname-expand (or x "/dev/null")) )) (define (common:get-this-exe-fullpath #!key (argv (argv))) (let* ((this-script (cond ((and (> (length argv) 2) (string-match "^(.*/csi|csi)$" (car argv)) (string-match "^-(s|ss|sx|script)$" (cadr argv))) (caddr argv)) (else (car argv)))) (fullpath (realpath this-script))) fullpath)) ;; (use trace) ;; (trace-call-sites #t) ;; (trace realpath common:get-this-exe-fullpath) (define *common:this-exe-fullpath* (common:get-this-exe-fullpath)) (define *common:this-exe-dir* (pathname-directory *common:this-exe-fullpath*)) (define *common:this-exe-name* (pathname-strip-directory *common:this-exe-fullpath*)) (define (find-chicken-lib) (let* ((ckhome (chicken-home)) (libpath-number (car (reverse (string-split (repository-path) "/")))) (libpath (conc *common:this-exe-dir* "/../../eggs/lib/chicken/" libpath-number))) (if (and (not (get-environment-variable "CHICKEN_REPOSITORY")) (directory-exists? libpath)) (conc "(repository-path \""libpath"\") ") ""))) (define (process-line l ht allow-system #!key (linenum #f)(extend-eval "")) (let loop ((res l)) (if (string? res) (let ((matchdat (string-search configf:var-expand-regex res))) (if matchdat (let* ((prestr (list-ref matchdat 1)) (cmdtype (list-ref matchdat 2)) ;; eval, system, shell, getenv (cmd (list-ref matchdat 3)) (poststr (list-ref matchdat 4)) (result #f) (start-time (current-milliseconds)) (cmdsym (string->symbol cmdtype)) (presnip (conc "(import posix)(import directory-utils)" "(set! getenv get-environment-variable)" )) (allsnip (conc "(import posix)(import directory-utils)" "(set! getenv get-environment-variable)" (find-chicken-lib) "(import (prefix mtconfigf configf:))" "(import mtconfigf)" *eval-string*)) (fullcmd (case cmdsym ((scheme scm) (conc "(lambda (ht)" allsnip "" cmd "))")) ((system) (conc "(lambda (ht)" allsnip "(configf:system ht \"" cmd "\"))")) ((shell sh) (conc "(lambda (ht)" allsnip "(string-translate (shell \"" cmd "\") \"\n\" \" \"))")) ((realpath rp)(conc "(lambda (ht)" allsnip "(configf:nice-path \"" cmd "\"))")) ((getenv gv) (conc "(lambda (ht)(get-environment-variable \"" cmd "\"))")) ((mtrah) (conc "(lambda (ht)" allsnip " (let ((extra \"" cmd "\"))" " (conc (or *toppath* (get-environment-variable \"MT_RUN_AREA_HOME\"))" " (if (string-null? extra) \"\" \"/\")" " extra)))")) ((get g) (let* ((parts (string-split cmd)) (sect (car parts)) (var (cadr parts))) (conc "(lambda (ht)(configf:lookup ht \"" sect "\" \"" var "\"))"))) ;;((runconfigs-get rget) (conc "(lambda (ht)" allsnip "(configf:runconfigs-get ht \"" cmd "\"))")) ((runconfigs-get rget) (runconfigs-get ht cmd)) (else "(lambda (ht)(print \"ERROR\") \"ERROR\")")))) (handle-exceptions exn (let ((arguments ((condition-property-accessor 'exn 'arguments) exn)) (message ((condition-property-accessor 'exn 'message) exn)) (allstr (conc "#{( " cmdtype ") " cmd "}, full expansion: " fullcmd))) (debug:print 0 *default-log-port* "WARNING: failed to process config input \"" l "\"") (debug:print 0 *default-log-port* " message: " message (if arguments (conc "; " (string-intersperse (map conc arguments) ", ")) "")) (debug:print 0 *default-log-port* "INFO: allstr is\n" allstr) ;; (debug:print 0 *default-log-port* "exn=" (condition->list exn)) (set! result allstr)) (if (or allow-system (not (member cmdtype '("system" "shell" "sh")))) (if (member cmdsym '(runconfigs-get rget)) (begin (set! result fullcmd) fullcmd) (with-input-from-string fullcmd (lambda () (set! result ((eval (read) ;;(module-environment 'mtconfigf) ) ht))))) (set! result (conc "#{(" cmdtype ") " cmd "}")))) (case cmdsym ((system shell scheme scm sh) (let ((delta (- (current-milliseconds) start-time))) (if (> delta 2000) (debug:print-info 0 *default-log-port* "for line \"" l "\"\n command: " cmd " took " (/ delta 1000) " seconds to run with output:\n " result) (debug:print-info 9 *default-log-port* "for line \"" l "\"\n command: " cmd " took " (/ delta 1000) " seconds to run with output:\n " result))))) (loop (conc prestr result poststr))) res)) res))) ;; Run a shell command and return the output as a string (define (shell cmd) (let* ((output (cmd-run->list cmd)) (res (car output)) (status (cadr output))) (if (equal? status 0) (let ((outres (string-intersperse res "\n"))) (debug:print-info 4 *default-log-port* "shell result:\n" outres) outres) (begin (with-output-to-port (current-error-port) (lambda () (print "ERROR: " cmd " returned bad exit code " status))) "")))) ;; this was inline but I'm pretty sure that is a hold over from when it was *very* simple ... ;; (define (configf:read-line p ht allow-processing settings #!key ....) (let loop ((inl (read-line p))) (let ((cont-line (and (string? inl) (not (string-null? inl)) (equal? "\\" (string-take-right inl 1))))) (if cont-line ;; last character is \ (let ((nextl (read-line p))) (if (not (eof-object? nextl)) (loop (string-append (if cont-line (string-take inl (- (string-length inl) 1)) inl) nextl)))) (let ((res (case allow-processing ;; if (and allow-processing ;; (not (eq? allow-processing 'return-string))) ((#t #f) (process-line inl ht allow-processing)) ((return-string) inl) (else (process-line inl ht allow-processing))))) (if (string? res) (let* ((r1 (if (not (equal? (hash-table-ref/default settings "trim-trailing-spaces" "no") "no")) (string-substitute "\\s+$" "" res) res)) (r2 (if (not (equal? (hash-table-ref/default settings "line-end-comments" "no") "no")) (string-substitute "\\s*#+[^\\{]*.*$" "" r1) r1))) r2) res)))))) (define (cfgdat->env-alist section cfgdat-ht allow-system) (filter (lambda (pair) (let* ((var (car pair)) (val (cdr pair))) (cons var (cond ((and allow-system (procedure? val)) ;; if we decided to use something other than #t or #f for allow-system ('return-procs or 'return-string) , this may become problematic (val)) ((procedure? val) #f) ((string? val) val) (else "#f"))))) (append (hash-table-ref/default cfgdat-ht "default" '()) (if (equal? section "default") '() (hash-table-ref/default cfgdat-ht section '()))))) (define (calc-allow-system allow-system section sections) (if sections (and (or (equal? "default" section) (member section sections)) allow-system) ;; account for sections and return allow-system as it might be a symbol such as return-strings allow-system)) ;; given a config hash and a section name, apply that section to all matching sections (using wildcard % or regex if /..../) ;; remove the section when done so that there is no downstream clobbering ;; (define (apply-wildcards ht section-name) (if (hash-table-exists? ht section-name) (let* ((vars (hash-table-ref ht section-name)) (rxstr (if (string-contains section-name "%") (string-substitute (regexp "%") ".*" section-name) (string-substitute (regexp "^/(.*)/$") "\\1" section-name))) (rx (regexp rxstr))) ;; (print "\nsection-name: " section-name " rxstr: " rxstr) (for-each (lambda (section) (if section (let ((same-section (string=? section-name section)) (rx-match (string-match rx section))) ;; (print "section: " section " vars: " vars " same-section: " same-section " rx-match: " rx-match) (if (and (not same-section) rx-match) (for-each (lambda (bundle) ;; (print "bundle: " bundle) (let ((key (car bundle)) (val (cadr bundle)) (meta (if (> (length bundle) 2)(caddr bundle) #f))) (hash-table-set! ht section (assoc-safe-add (hash-table-ref ht section) key val metadata: meta)))) vars))))) (hash-table-keys ht)))) ht) ;;====================================================================== ;; Extended config lines, allows storing more hierarchial data in the config lines ;; ABC a=1; b=hello world; c=a ;; ;; NOTE: implementation is quite limited. You currently cannot have ;; semicolons in your string values. ;;====================================================================== ;; convert string a=1; b=2; c=a silly thing; d= ;; to '((a . 1)(b . 2)(c . "a silly thing")(d . "")) ;; (define (val->alist val #!key (convert #f)) (let ((val-list (string-split-fields ";\\s*" val #:infix))) (if val-list (map (lambda (x) (let ((f (string-split-fields "\\s*=\\s*" x #:infix))) (case (length f) ((0) `(,#f)) ;; null string case ((1) `(,(string->symbol (car f)))) ((2) `(,(string->symbol (car f)) . ,(let ((inval (cadr f))) (if convert (lazy-convert inval) inval)))) (else f)))) val-list) '()))) ;; I don't want configf to turn into a weak yaml format but this extention is really useful ;; (define (section->val-alist cfgdat section-name #!key (convert #f)) (let ((section (get-section cfgdat section-name))) (map (lambda (item) (let ((key (car item)) (val (cadr item))) ;; BUG IN WAIT. sections are not returned as proper alists, should fix this. (cons key (val->alist val convert: convert)))) section))) ;; read a config file, returns hash table of alists ;; read a config file, returns hash table of alists ;; adds to ht if given (must be #f otherwise) ;; allow-system: ;; #f - do not evaluate [system ;; #t - immediately evaluate [system and store result as string ;; 'return-procs -- return a proc taking ht as an argument that may be evaulated at some future time ;; 'return-string -- return a string representing a proc taking ht as an argument that may be evaulated at some future time ;; envion-patt is a regex spec that identifies sections that will be eval'd ;; in the environment on the fly ;; sections: #f => get all, else list of sections to gather ;; post-section-procs alist of section-pattern => proc, where: (proc section-name next-section-name ht curr-path) ;; apply-wildcards: #t/#f - apply vars from targets with % wildcards to all matching sections ;; ;; NOTE: apply-wild variable is intentional (but a better name would be good) ;; (define (read-config path ht allow-system #!key (environ-patt #f) (curr-section #f) (sections #f) (settings (make-hash-table)) (keep-filenames #f) (post-section-procs '()) (apply-wild #t) ) (debug:print 9 *default-log-port* "BB> read-config > keep-filenames: " keep-filenames) (debug:print 9 *default-log-port* "START: " path) ;; (if *configdat* ;; (common:save-pkt `((action . read-config) ;; (f . ,(cond ((string? path) path) ;; ((port? path) "port") ;; (else (conc path)))) ;; (T . configf)) ;; *configdat* #t add-only: #t)) (if (and (not (port? path)) (not (safe-file-exists? path))) ;; for case where we are handed a port (begin (debug:print-info 1 *default-log-port* "read-config - file not found " path " current path: " (current-directory)) ;; WARNING: This is a risky change but really, we should not return an empty hash table if no file read? #f) ;; (if (not ht)(make-hash-table) ht)) (let* ((have-file (string? path)) (inp (if have-file (open-input-file path) path)) ;; we can be handed a port (res (if (not ht)(make-hash-table) ht)) (metapath (if keep-filenames path #f)) (process-wildcards (lambda (res curr-section-name) (if (and apply-wild (or (string-contains curr-section-name "%") ;; wildcard (string-match "/.*/" curr-section-name))) ;; regex (begin (apply-wildcards res curr-section-name) (hash-table-delete! res curr-section-name)))))) ;; NOTE: if the section is a wild card it will be REMOVED from res (let loop ((inl (configf:read-line inp res (calc-allow-system allow-system curr-section sections) settings)) ;; (read-line inp)) (curr-section-name (if curr-section curr-section "default")) (var-flag #f);; turn on for key-var-pr and cont-ln-rx, turn off elsewhere (lead #f)) (debug:print-info 8 *default-log-port* "curr-section-name: " curr-section-name " var-flag: " var-flag "\n inl: \"" inl "\"") (if (eof-object? inl) (begin ;; process last section for wildcards (process-wildcards res curr-section-name) (if have-file ;; we received a path, not a port, thus we are responsible for closing it. (close-input-port inp)) (if (list? sections) ;; delete all sections except given when sections is provided (for-each (lambda (section) (if (not (member section sections)) (hash-table-delete! res section))) ;; we are using "" as a dumping ground and must remove it before returning the ht (hash-table-keys res))) (debug:print 9 *default-log-port* "END: " path) res ) ;; retval (regex-case inl (configf:comment-rx _ (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f)) (configf:blank-l-rx _ (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f)) (configf:settings ( x setting val ) (begin (hash-table-set! settings setting val) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))) (configf:initstr-rx ( x initstr ) (begin (add-eval-string initstr) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))) (configf:include-rx ( x include-file ) (let* ((curr-conf-dir (pathname-directory path)) (full-conf (if (and (absolute-pathname? include-file) (file-exists? include-file)) include-file (nice-path (conc (if curr-conf-dir curr-conf-dir ".") "/" include-file)))) (all-matches (sort (handle-exceptions exn (list) (glob full-conf)) string<=?))) (if (null? all-matches) (begin (debug:print '(2 9) #f "INFO: include file(s) matching " include-file " not found (called from " path ")") (debug:print 2 *default-log-port* " " full-conf)) (for-each (lambda (fpath) ;; (push-directory conf-dir) (debug:print 9 *default-log-port* "Including: " full-conf) (read-config fpath res allow-system environ-patt: environ-patt curr-section: curr-section-name sections: sections settings: settings keep-filenames: keep-filenames)) all-matches)) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))) (configf:script-rx ( x include-script params);; handle-exceptions ;; exn ;; (begin ;; (debug:print '(0 2 9) #f "INFO: include from script " include-script " failed.") ;; (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f)) (if (and (safe-file-exists? include-script)(file-execute-access? include-script)) (let* ((local-allow-system (calc-allow-system allow-system curr-section-name sections)) (env-delta (cfgdat->env-alist curr-section-name res local-allow-system)) (new-inp-port (with-env-vars env-delta (lambda () (open-input-pipe (conc include-script " " params)))))) (debug:print '(2 9) *default-log-port* "Including from script output: " include-script) ;; (print "We got here, calling read-config next. Port is: " new-inp-port) (read-config new-inp-port res allow-system environ-patt: environ-patt curr-section: curr-section-name sections: sections settings: settings keep-filenames: keep-filenames) (close-input-port new-inp-port) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f)) (begin (debug:print 0 *default-log-port* "Script not found or not exectutable: " include-script) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))) ) ;; ) (configf:section-rx ( x section-name ) (begin ;; call post-section-procs (for-each (lambda (dat) (let ((patt (car dat)) (proc (cdr dat))) (if (string-match patt curr-section-name) (proc curr-section-name section-name res path)))) post-section-procs) ;; after gathering the vars for a section and if apply-wildcards is true and if there is a wildcard in the section name process wildcards ;; NOTE: we are processing the curr-section-name, NOT section-name. (process-wildcards res curr-section-name) (if (not (hash-table-ref/default res section-name #f))(hash-table-set! res section-name '())) ;; ensure that mere mention of a section is not lost (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) ;; if we have the sections list then force all settings into "" and delete it later? ;; (if (or (not sections) ;; (member section-name sections)) ;; section-name "") ;; stick everything into "". NOPE: We need new strategy. Put stuff in correct sections and then delete all sections later. section-name #f #f))) (configf:key-sys-pr ( x key cmd ) (if (calc-allow-system allow-system curr-section-name sections) (let ((alist (hash-table-ref/default res curr-section-name '())) (val-proc (lambda () (let* ((start-time (current-seconds)) (local-allow-system (calc-allow-system allow-system curr-section-name sections)) (env-delta (cfgdat->env-alist curr-section-name res local-allow-system)) (cmdres (cmd-run->list cmd delta-env-alist-or-hash-table: env-delta)) ;; BB: here is where [system is exec'd. needs to have env from other vars! (delta (- (current-seconds) start-time)) (status (cadr cmdres)) (res (car cmdres))) (debug:print-info 4 *default-log-port* "" inl "\n => " (string-intersperse res "\n")) (if (not (eq? status 0)) (begin (debug:print-error 0 *default-log-port* "problem with " inl ", return code " status " output: " cmdres))) (if (> delta 2) (debug:print-info 0 *default-log-port* "for line \"" inl "\"\n command: " cmd " took " delta " seconds to run with output:\n " res) (debug:print-info 9 *default-log-port* "for line \"" inl "\"\n command: " cmd " took " delta " seconds to run with output:\n " res)) (if (null? res) "" (string-intersperse res " ")))))) (hash-table-set! res curr-section-name (assoc-safe-add alist key (case (calc-allow-system allow-system curr-section-name sections) ((return-procs) val-proc) ((return-string) cmd) (else (val-proc))) metadata: metapath)) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f)) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))) (configf:key-no-val ( x key val) (let* ((alist (hash-table-ref/default res curr-section-name '())) (fval (or (if (string? val) val #f) ""))) ;; fval should be either "" or " " (one or more spaces) (debug:print 10 *default-log-port* " setting: [" curr-section-name "] " key " = #t") (safe-setenv key fval) (hash-table-set! res curr-section-name (assoc-safe-add alist key fval metadata: metapath)) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name key #f))) (configf:key-val-pr ( x key unk1 val unk2 ) (let* ((alist (hash-table-ref/default res curr-section-name '())) (envar (and environ-patt (string-search (regexp environ-patt) curr-section-name) (and (not (string-null? key)) (not (equal? "!" (substring key 0 1)))) ;; ! as leading character is a signature to NOT export to the environment ;; (string-match "^.*:.*:.*$" key) ;; ;; something:something:something reserved for triggers in runconfigs )) (realval (if envar (eval-string-in-environment val) val))) (debug:print-info 6 *default-log-port* "read-config env setting, envar: " envar " realval: " realval " val: " val " key: " key " curr-section-name: " curr-section-name) (if envar (safe-setenv key realval)) (debug:print 10 *default-log-port* " setting: [" curr-section-name "] " key " = " val) (hash-table-set! res curr-section-name (assoc-safe-add alist key realval metadata: metapath)) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name key #f))) ;; if a continued line (configf:cont-ln-rx ( x whsp val ) (let ((alist (hash-table-ref/default res curr-section-name '()))) (if var-flag ;; if set to a string then we have a continued var (let ((newval (conc (lookup res curr-section-name var-flag) "\n" ;; trim lead from the incoming whsp to support some indenting. (if lead (string-substitute (regexp lead) "" whsp) "") val))) ;; (print "val: " val "\nnewval: \"" newval "\"\nvarflag: " var-flag) (hash-table-set! res curr-section-name (assoc-safe-add alist var-flag newval metadata: metapath)) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name var-flag (if lead lead whsp))) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f)))) (else (debug:print-error 0 *default-log-port* "problem parsing " path ",\n \"" inl "\"") (set! var-flag #f) (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f)))) ) ;; end loop ))) ;; look at common:set-fields for an example of how to use the set-fields proc ;; pathenvvar will set the named var to the path of the config ;; (define (find-and-read-config fname #!key (environ-patt #f)(given-toppath #f)(pathenvvar #f)(set-fields #f)(keep-filenames #f)) (let* ((curr-dir (current-directory)) (configinfo (find-config fname toppath: given-toppath)) (toppath (car configinfo)) (configfile (cadr configinfo))) (if toppath (change-directory toppath)) (if (and toppath pathenvvar)(setenv pathenvvar toppath)) (let ((configdat (if configfile (read-config configfile #f #t environ-patt: environ-patt post-section-procs: (if set-fields (list (cons "^fields$" set-fields) ) '()) #f keep-filenames: keep-filenames)))) (if toppath (change-directory curr-dir)) (list configdat toppath configfile fname)))) (define (lookup cfgdat section var) (if (hash-table? cfgdat) (let ((sectdat (hash-table-ref/default cfgdat section '()))) (if (null? sectdat) #f (let ((match (assoc var sectdat))) (if match ;; (and match (list? match)(> (length match) 1)) (cadr match) #f)) )) #f)) ;; use to have definitive setting: ;; [foo] ;; var yes ;; ;; (var-is? cfgdat "foo" "var" "yes") => #t ;; (define (var-is? cfgdat section var expected-val) (equal? (lookup cfgdat section var) expected-val)) ;; safely look up a value that is expected to be a number, return ;; a default (#f unless provided) ;; (define (lookup-number cfgdat section varname #!key (default #f)) (let* ((val (lookup cfgdat section varname)) (res (if val (string->number (string-substitute "\\s+" "" val #t)) #f))) (cond (res res) (val (debug:print 0 *default-log-port* "ERROR: no number found for [" section "], " varname ", got: " val)) (else default)))) (define (section-vars cfgdat section) (let ((sectdat (hash-table-ref/default cfgdat section '()))) (if (null? sectdat) '() (map car sectdat)))) (define (get-section cfgdat section) (hash-table-ref/default cfgdat section '())) (define (set-section-var cfgdat section var val) (let ((sectdat (get-section cfgdat section))) (hash-table-set! cfgdat section (assoc-safe-add sectdat var val)))) ;;(append (filter (lambda (x)(not (assoc var sectdat))) sectdat) ;; (list var val)))) ;; moved to common ;; (define (setup) ;; (let* ((configf (find-config "megatest.config")) ;; (config (if configf (read-config configf #f #t) #f))) ;; (if config ;; (setenv "RUN_AREA_HOME" (pathname-directory configf))) ;; config)) ;;====================================================================== ;; Non destructive writing of config file ;;====================================================================== (define (compress-multi-lines fdat) ;; step 1.5 - compress any continued lines (if (null? fdat) fdat (let loop ((hed (car fdat)) (tal (cdr fdat)) (cur "") (led #f) (res '())) ;; ALL WHITESPACE LEADING LINES ARE TACKED ON!! ;; 1. remove led whitespace ;; 2. tack on to hed with "\n" (let ((match (string-match configf:cont-ln-rx hed))) (if match ;; blast! have to deal with a multiline (let* ((lead (cadr match)) (lval (caddr match)) (newl (conc cur "\n" lval))) (if (not led)(set! led lead)) (if (null? tal) (set! fdat (append fdat (list newl))) (loop (car tal)(cdr tal) newl led res))) ;; NB// not tacking newl onto res (let ((newres (if led (append res (list cur hed)) (append res (list hed))))) ;; prev was a multiline (if (null? tal) newres (loop (car tal)(cdr tal) "" #f newres)))))))) ;; note: I'm cheating a little here. I merely replace "\n" with "\n " (define (expand-multi-lines fdat) ;; step 1.5 - compress any continued lines (if (null? fdat) fdat (let loop ((hed (car fdat)) (tal (cdr fdat)) (res '())) (let ((newres (append res (list (string-substitute (regexp "\n") "\n " hed #t))))) (if (null? tal) newres (loop (car tal)(cdr tal) newres)))))) (define (file->list fname) (if (safe-file-exists? fname) (let ((inp (open-input-file fname))) (let loop ((inl (read-line inp)) (res '())) (if (eof-object? inl) (begin (close-input-port inp) (reverse res)) (loop (read-line inp)(cons inl res))))) '())) ;; raw basic write config in ini format ;; (define (write-config cfgdat fname) (with-output-to-file fname (lambda () (config->ini cfgdat)))) ;; (for-each ;; (lambda (section) ;; (let ((sec-dat (hash-table-ref cfgdat section))) ;; (for-each (lambda (entry)(print (car entry) " " (cadr entry))) sec-dat))) ;; (sort (hash-table-keys cfgdat) (lambda (a b)(string<= a b))))))) ;;====================================================================== ;; Write a config ;; 0. Given a refererence data structure "indat" ;; 1. Open the output file and read it into a list ;; 2. Flatten any multiline entries ;; 3. Modify values per contents of "indat" and remove absent values ;; 4. Append new values to the section (immediately after last legit entry) ;; 5. Write out the new list ;;====================================================================== (define (write-merge-config indat fname #!key (required-sections '())) (let* (;; step 1: Open the output file and read it into a list (fdat (file->list fname)) (refdat (make-hash-table)) (sechash (make-hash-table)) ;; current section hash, init with hash for "default" section (new #f) ;; put the line to be used in new, if it is to be deleted the set new to #f (secname #f)) ;; step 2: Flatten multiline entries (if (not (null? fdat))(set! fdat (compress-multi-lines fdat))) ;; step 3: Modify values per contents of "indat" and remove absent values (if (not (null? fdat)) (let loop ((hed (car fdat)) (tal (cadr fdat)) (res '()) (lnum 0)) (regex-case hed (configf:comment-rx _ (set! res (append res (list hed)))) ;; (loop (read-line inp) curr-section-name #f #f)) (configf:blank-l-rx _ (set! res (append res (list hed)))) ;; (loop (read-line inp) curr-section-name #f #f)) (configf:section-rx ( x section-name ) (let ((section-hash (hash-table-ref/default refdat section-name #f))) (if (not section-hash) (let ((newhash (make-hash-table))) (hash-table-set! refdat section-name newhash) (set! sechash newhash)) (set! sechash section-hash)) (set! new hed) ;; will append this at the bottom of the loop (set! secname section-name) )) ;; No need to process key cmd, let it fall though to key val (configf:key-val-pr ( x key val ) (let ((newval (lookup indat secname key))) ;; secname was sec. I think that was a bug ;; can handle newval == #f here => that means key is removed (cond ((equal? newval val) (set! res (append res (list hed)))) ((not newval) ;; key has been removed (set! new #f)) ((not (equal? newval val)) (hash-table-set! sechash key newval) (set! new (conc key " " newval))) (else (debug:print-error 0 *default-log-port* "problem parsing line number " lnum "\"" hed "\""))))) (else (debug:print-error 0 *default-log-port* "Problem parsing line num " lnum " :\n " hed ))) (if (not (null? tal)) (loop (car tal)(cdr tal)(if new (append res (list new)) res)(+ lnum 1))) ;; drop to here when done processing, res contains modified list of lines (set! fdat res))) ;; step 4: Append new values to the section (for-each (lambda (section) (let ((sdat '()) ;; append needed bits here (svars (section-vars indat section))) (for-each (lambda (var) (let ((val (lookup refdat section var))) (if (not val) ;; this one is new (begin (if (null? sdat)(set! sdat (list (conc "[" section "]")))) (set! sdat (append sdat (list (conc var " " val)))))))) svars) (set! fdat (append fdat sdat)))) (delete-duplicates (append required-sections (hash-table-keys indat)))) ;; step 5: Write out new file (with-output-to-file fname (lambda () (for-each (lambda (line) (print line)) (expand-multi-lines fdat)))))) ;;====================================================================== ;; refdb ;;====================================================================== ;; reads a refdb into an assoc array of assoc arrays ;; returns (list dat msg) (define (read-refdb refdb-path) (let ((sheets-file (conc refdb-path "/sheet-names.cfg"))) (if (not (safe-file-exists? sheets-file)) (list #f (conc "ERROR: no refdb found at " refdb-path)) (if (not (file-read-access? sheets-file)) (list #f (conc "ERROR: refdb file not readable at " refdb-path)) (let* ((sheets (with-input-from-file sheets-file (lambda () (let loop ((inl (read-line)) (res '())) (if (eof-object? inl) (reverse res) (loop (read-line)(cons inl res))))))) (data '())) (for-each (lambda (sheet-name) (let* ((dat-path (conc refdb-path "/" sheet-name ".dat")) (ref-dat (read-config dat-path #f #t)) (ref-assoc (map (lambda (key) (list key (hash-table-ref ref-dat key))) (hash-table-keys ref-dat)))) ;; (hash-table->alist ref-dat))) ;; (set! data (append data (list (list sheet-name ref-assoc)))))) (set! data (cons (list sheet-name ref-assoc) data)))) sheets) (list data "NO ERRORS")))))) ;; map over all pairs in a three level hierarchial alist and apply a function to the keys/val ;; (define (map-all-hier-alist data proc #!key (initproc1 #f)(initproc2 #f)(initproc3 #f)) (for-each (lambda (sheetname) (let* ((sheettmp (assoc sheetname data)) (sheetdat (if sheettmp (cadr sheettmp) '()))) (if initproc1 (initproc1 sheetname)) (for-each (lambda (sectionname) (let* ((sectiontmp (assoc sectionname sheetdat)) (sectiondat (if sectiontmp (cadr sectiontmp) '()))) (if initproc2 (initproc2 sheetname sectionname)) (for-each (lambda (varname) (let* ((valtmp (assoc varname sectiondat)) (val (if valtmp (cadr valtmp) ""))) (proc sheetname sectionname varname val))) (map car sectiondat)))) (map car sheetdat)))) (map car data)) data) ;;====================================================================== ;; C O N F I G T O / F R O M A L I S T ;;====================================================================== (define (config->alist cfgdat) (hash-table->alist cfgdat)) (define (alist->config adat) (let ((ht (make-hash-table))) (for-each (lambda (section) (hash-table-set! ht (car section)(cdr section))) adat) ht)) ;; if (define (read-alist fname) (handle-exceptions exn #f (alist->config (with-input-from-file fname read)))) (define (write-alist cdat fname #!key (locker #f)(unlocker #f)) (if (and locker (not (locker fname))) (debug:print 0 *default-log-port* "INFO: Could not get lock on " fname)) (let* ((dat (config->alist cdat)) (res (begin (with-output-to-file fname ;; first write out the file (lambda () (pp dat))) (if (file-exists? fname) ;; now verify it is readable (if (read-alist fname) #t ;; data is good. (begin (handle-exceptions exn #f (debug:print 0 *default-log-port* "WARNING: content " dat " for cache " fname " is not readable. Deleting generated file.") (delete-file fname)) #f)) #f)))) (if unlocker (unlocker fname)) res)) ;; convert config hash-table/list data to ini format ;; (define (config->ini data) (map (lambda (section) (let ((section-name (car section)) (section-dat (cdr section))) (print "\n[" section-name "]") (map (lambda (dat-pair) (let* ((var (car dat-pair)) (val (cadr dat-pair)) (fname (if (> (length dat-pair) 2)(caddr dat-pair) #f))) (if fname (print "# " var "=>" fname)) (print var " " val))) section-dat))) ;; (print "section-dat: " section-dat)) (hash-table->alist data))) ;(use trace) ;(trace-call-sites #t) ;(trace read-config) ) |
Added mtconfigf/mtconfigf.setup version [14a686d751].
> > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ;; Copyright 2007-2010, Matthew Welland. ;; ;; This program is made available under the GNU GPL version 2.0 or ;; greater. See the accompanying file COPYING for details. ;; ;; This program is distributed WITHOUT ANY WARRANTY; without even the ;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ;; PURPOSE. ;;;; mtconfig.setup ;; compile the code into dynamically loadable shared objects ;; and install as modules (compile -s mtconfigf.scm) (standard-extension 'mtconfigf "mtconfigf.so") |
Added mtconfigf/tests/run.scm version [f0fc4f2f77].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | (load "../mtdebug/mtdebug.scm") (import mtdebug) (load "mtconfigf.scm") (import (prefix mtconfigf config:)) (use mtdebug) ;; configure mtconfigf (let* ((normal-fn debug:print) (info-fn debug:print-info) (error-fn debug:print-error) (default-port (current-output-port))) (config:set-debug-printers normal-fn info-fn error-fn default-port)) (use test) (let* ((cfgdat (config:read-config "tests/test.config" #f #f))) (test #f "value" (config:lookup cfgdat "basic" "key")) (test #f 2 (config:lookup-number cfgdat "basic" "two")) ) (config:add-eval-string "(define (customfunc) \"hello\")") (let* ((cfgdat (config:read-config "tests/test2.config" #f #f))) (test #f "bar" (config:lookup cfgdat "schemy" "rgetreftarget")) (test #f "baz" (config:lookup cfgdat "schemy" "rgetrefdefault")) (test #f "2" (config:lookup cfgdat "schemy" "addup")) (test #f 2 (config:lookup-number cfgdat "schemy" "addup")) (test #f "hello" (config:lookup cfgdat "schemy" "custom")) ) (test #f (conc "hello " (get-environment-variable "USER")) (config:eval-string-in-environment "hello $USER")) (let* ((cfgdat (config:read-config "tests/test3.config" #f #t))) (test #f "hello" (config:lookup cfgdat "systemic" "hello")) (test #f (conc "hello " (get-environment-variable "USER")) (config:lookup cfgdat "systemic" "hellouser")) ) |
Added mtconfigf/tests/test.config version [3d5375a8d9].
> > > | 1 2 3 | [basic] key value two 2 |
Added mtconfigf/tests/test2.config version [18058f78ed].
> > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [default] deffoo baz [a-target] foo bar [.dvars] target a-target [schemy] addup #{scheme (+ 1 1)} custom #{scheme (customfunc)} rgetreftarget #{rget foo} rgetrefdefault #{rget deffoo} |
Added mtconfigf/tests/test3.config version [3f1e49e30c].
> > > | 1 2 3 | [systemic] hello [system echo hello] hellouser [system echo hello $USER] |
Added pkts.scm version [4f496b5684].
> > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ;;====================================================================== ;; Copyright 2019, Matthew Welland. ;; ;; This file is part of Megatest. ;; ;; Megatest is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; Megatest is distributed in the hope that 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 Megatest. If not, see <http://www.gnu.org/licenses/>. ;;====================================================================== (declare (unit pkts)) (include "pkts/pkts.scm") |
Added pkts/pktrec.scm version [28997466b3].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | (define-syntax define-record-type (syntax-rules () ((define-record-type type (constructor constructor-tag ...) predicate (field-tag accessor . more) ...) (begin (define type (make-record-type 'type '(field-tag ...))) (define constructor (record-constructor type '(constructor-tag ...))) (define predicate (record-predicate type)) (define-record-field type field-tag accessor . more) ...)))) ; An auxilliary macro for define field accessors and modifiers. ; This is needed only because modifiers are optional. (define-syntax define-record-field (syntax-rules () ((define-record-field type field-tag accessor) (define accessor (record-accessor type 'field-tag))) ((define-record-field type field-tag accessor modifier) (begin (define accessor (record-accessor type 'field-tag)) (define modifier (record-modifier type 'field-tag)))))) ; Record types ; We define the following procedures: ; ; (make-record-type <type-name <field-names>) -> <record-type> ; (record-constructor <record-type<field-names>) -> <constructor> ; (record-predicate <record-type>) -> <predicate> ; (record-accessor <record-type <field-name>) -> <accessor> ; (record-modifier <record-type <field-name>) -> <modifier> ; where ; (<constructor> <initial-value> ...) -> <record> ; (<predicate> <value>) -> <boolean> ; (<accessor> <record>) -> <value> ; (<modifier> <record> <value>) -> <unspecific> ; Record types are implemented using vector-like records. The first ; slot of each record contains the record's type, which is itself a ; record. (define (record-type record) (record-ref record 0)) ;---------------- ; Record types are themselves records, so we first define the type for ; them. Except for problems with circularities, this could be defined as: ; (define-record-type :record-type ; (make-record-type name field-tags) ; record-type? ; (name record-type-name) ; (field-tags record-type-field-tags)) ; As it is, we need to define everything by hand. (define :record-type (make-record 3)) (record-set! :record-type 0 :record-type) ; Its type is itself. (record-set! :record-type 1 ':record-type) (record-set! :record-type 2 '(name field-tags)) ; Now that :record-type exists we can define a procedure for making more ; record types. (define (make-record-type name field-tags) (let ((new (make-record 3))) (record-set! new 0 :record-type) (record-set! new 1 name) (record-set! new 2 field-tags) new)) ; Accessors for record types. (define (record-type-name record-type) (record-ref record-type 1)) (define (record-type-field-tags record-type) (record-ref record-type 2)) ;---------------- ; A utility for getting the offset of a field within a record. (define (field-index type tag) (let loop ((i 1) (tags (record-type-field-tags type))) (cond ((null? tags) (error "record type has no such field" type tag)) ((eq? tag (car tags)) i) (else (loop (+ i 1) (cdr tags)))))) ;---------------- ; Now we are ready to define RECORD-CONSTRUCTOR and the rest of the ; procedures used by the macro expansion of DEFINE-RECORD-TYPE. (define (record-constructor type tags) (let ((size (length (record-type-field-tags type))) (arg-count (length tags)) (indexes (map (lambda (tag) (field-index type tag)) tags))) (lambda args (if (= (length args) arg-count) (let ((new (make-record (+ size 1)))) (record-set! new 0 type) (for-each (lambda (arg i) (record-set! new i arg)) args indexes) new) (error "wrong number of arguments to constructor" type args))))) (define (record-predicate type) (lambda (thing) (and (record? thing) (eq? (record-type thing) type)))) (define (record-accessor type tag) (let ((index (field-index type tag))) (lambda (thing) (if (and (record? thing) (eq? (record-type thing) type)) (record-ref thing index) (error "accessor applied to bad value" type tag thing))))) (define (record-modifier type tag) (let ((index (field-index type tag))) (lambda (thing value) (if (and (record? thing) (eq? (record-type thing) type)) (record-set! thing index value) (error "modifier applied to bad value" type tag thing))))) Records ; This implements a record abstraction that is identical to vectors, ; except that they are not vectors (VECTOR? returns false when given a ; record and RECORD? returns false when given a vector). The following ; procedures are provided: ; (record? <value>) -> <boolean> ; (make-record <size>) -> <record> ; (record-ref <record> <index>) -> <value> ; (record-set! <record> <index> <value>) -> <unspecific> ; ; These can implemented in R5RS Scheme as vectors with a distinguishing ; value at index zero, providing VECTOR? is redefined to be a procedure ; that returns false if its argument contains the distinguishing record ; value. EVAL is also redefined to use the new value of VECTOR?. ; Define the marker and redefine VECTOR? and EVAL. (define record-marker (list 'record-marker)) (define real-vector? vector?) (define (vector? x) (and (real-vector? x) (or (= 0 (vector-length x)) (not (eq? (vector-ref x 0) record-marker))))) ; This won't work if ENV is the interaction environment and someone has ; redefined LAMBDA there. (define eval (let ((real-eval eval)) (lambda (exp env) ((real-eval `(lambda (vector?) ,exp)) vector?)))) ; Definitions of the record procedures. (define (record? x) (and (real-vector? x) (< 0 (vector-length x)) (eq? (vector-ref x 0) record-marker))) (define (make-record size) (let ((new (make-vector (+ size 1)))) (vector-set! new 0 record-marker) new)) (define (record-ref record index) (vector-ref record (+ index 1))) (define (record-set! record index value) (vector-set! record (+ index 1) value)) |
Added pkts/pkts.meta version [b5255a025d].
> > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ;; -*- scheme -*- ( ; Your egg's license: (license "BSD") ; Pick one from the list of categories (see below) for your egg and enter it ; here. (category db) ; A list of eggs pkts depends on. If none, you can omit this declaration ; altogether. If you are making an egg for chicken 3 and you need to use ; procedures from the `files' unit, be sure to include the `files' egg in the ; `needs' section (chicken versions < 3.4.0 don't provide the `files' unit). ; `depends' is an alias to `needs'. ;; (needs (autoload "3.0")) ; A list of eggs required for TESTING ONLY. See the `Tests' section. (test-depends test) (author "Matt Welland") (synopsis "A sha1-chain based datastore built on packets consisting of single line cards modeled loosely on the fossil scm datastore.")) |
Added pkts/pkts.release-info version [fbbc2937bb].
> > > | 1 2 3 | (repo fossil "http://www.kiatoa.com/cgi-bin/fossils/{egg-name}") (uri zip "http://www.kiatoa.com/cgi-bin/fossils/{egg-name}/zip/{egg-name}.zip?uuid={egg-release}") (release "1.0") |
Added pkts/pkts.scm version [d1cd1cb6f6].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 | ;; Copyright 2006-2017, Matthew Welland. ;; ;; This file is part of Pkts ;; ;; Pkts is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; Pkts is distributed in the hope that 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 Pkts. If not, see <http://www.gnu.org/licenses/>. ;; ;; CARDS: ;; ;; A card is a line of text, the first two characters are a letter followed by a ;; space. The letter is the card type. ;; ;; PKTS: ;; ;; A pkt is a sorted list of cards with a final card Z that contains the shar1 hash ;; of all of the preceding cards. ;; ;; APKT: ;; ;; An alist mapping card types to card data ;; '((T . "pkttype") ;; (a . "some content")) ;; ;; EPKT: ;; ;; Extended packet using friendly keys. Must use a pktspec to convert to/from epkts ;; '((ptype . "pkttype") ;; (adata . "some content)) ;; ;; DPKT: ;; ;; pkts pulled from the database have this format: ;; ;;((apkt (Z . "7de89c09ac024b3832c93e16cd78d11e2e28733b") <= this is a the alist ;; (t . "v1.63/tip/dev") ;; (c . "QUICKPATT") ;; (T . "runstart") ;; (P . "354eeb67120a921e3e33155ecab1b522ac10b6bd") ;; (D . "1488995096.0")) ;; (id . 8) ;; (group-id . 0) ;; (uuid . "7de89c09ac024b3832c93e16cd78d11e2e28733b") ;; (parent . "") ;; (pkt-type . "runstart") ;; (pkt . "D 1488995096.0\nP 354eeb67120a921e3e33155ecab1b522ac10b6bd\nT runstart\nc QUICKPATT\nt v1.63/tip/dev\nZ 7de89c09ac024b3832c93e16cd78d11e2e28733b")) ;; ;; pktspec is alist of alists mapping types and nicekeys to keys ;; ;; '((posting . ((title . t) ;; (url . u) ;; (blurb . b))) ;; (comment . ((comment . c) ;; (score . s)))) ;; Reserved cards: ;; P : pkt parent ;; R : reference pkt containing mapping of short string -> sha1sum strings ;; T : pkt type ;; D : current time from (current-time), unless provided ;; Z : shar1 hash of the packet ;; Example usage: ;; ;; Create a pkt: ;; ;; (use pkts) ;; (define-values (uuid pkt) ;; (alist->pkt ;; '((fruit . "apple") (meat . "beef")) ;; this is the data to convert ;; '((foods (fruit . f) (meat . m))) ;; this is the pkt spec ;; ptype: ;; 'foods)) ;; ;; Add to pkt queue: ;; ;; (define db (open-queue-db "/tmp/pkts" "pkts.db")) ;; (add-to-queue db pkt uuid 'foods #f 0) ;; no parent and use group_id of 0 ;; ;; Retrieve the packet from the db and extract a value: ;; ;; (alist-ref ;; 'meat ;; (dpkt->alist ;; (car (get-dpkts db #f 0 #f)) ;; '((foods (fruit . f) ;; (meat . m))))) ;; => "beef" ;; (module pkts ( ;; cards, util and misc ;; sort-cards ;; calc-shar1 ;; ;; low-level constructor procs, exposed only for development/testing, will be removed construct-sdat construct-pkt card->type/value add-z-card ;; queue database procs open-queue-db add-to-queue create-and-queue lookup-by-uuid lookup-by-id get-dpkts get-not-processed-pkts get-related find-pkts process-pkts get-descendents get-ancestors get-pkts get-last-descendent with-queue-db load-pkts-to-db ;; procs that operate directly on pkts, sdat, apkts, dpkts etc. pkt->alist ;; pkt -> apkt (i.e. alist) pkt->sdat ;; pkt -> '("a aval" "b bval" ...) sdat->alist ;; '("a aval" "b bval"...) -> ((a . "aval")(b . "bval") ...) dblst->dpkts ;; convert list of tuples from queue db into dpkts dpkt->alist ;; flatten a dpkt into an alist containing all db fields and the pkt alist dpkts->alists ;; apply dpkt->alist to a list of alists using a pkt-spec alist->pkt ;; returns two values uuid, pkt get-value ;; looks up a value given a key in a dpkt flatten-all ;; merge the list of values from a query which includes a pkt into a flat alist <== really useful! check-pkt ;; pkt alists write-alist->pkt read-pkt->alist ;; archive database archive-open-db write-archive-pkts archive-pkts mark-processed ;; pktsdb pktdb-conn ;; useful pktdb-fname pktsdb-open pktsdb-close pktsdb-add-record ;; temporary pktdb-pktspec ;; utility procs increment-string ;; used to get indexes for strings in ref pkts make-report ;; make a .dot file ) (import chicken scheme data-structures posix srfi-1 regex srfi-13 srfi-69 ports extras) (use crypt sha1 message-digest (prefix dbi dbi:) typed-records) ;;====================================================================== ;; DATA MANIPULATION UTILS ;;====================================================================== (define-inline (unescape-data data) (string-translate* data '(("\\n" . "\n") ("\\\\" . "\\")))) (define-inline (escape-data data) (string-translate* data '(("\n" . "\\n") ("\\" . "\\\\")))) (define-inline (make-card type data) (conc type " " (escape-data (->string data)))) ;; reverse an alist for doing pktkey -> external key conversions ;; (define-inline (reverse-aspec aspec) (map (lambda (dat) (cons (cdr dat)(car dat))) aspec)) ;; add a card to the list of cards, sdat ;; if type is #f return only sdat ;; if data is #f return only sdat ;; (define-inline (add-card sdat type data) (if (and type data) (cons (make-card type data) sdat) sdat)) ;;====================================================================== ;; STRING AS FUNKY NUMBER ;;====================================================================== ;; NOTE: PTDZ are removed as they are reserved. NB// the R card is not used in a ;; ref, instead the P parent card is used. ;; Question: Why does it matter to remove PTDZ? ;; To make the ref easier to use the ref strings will be the keys ;; so we cannot have overlap with any actual keys. But this is a ;; bit silly. What we need to do instead is reject keys of length ;; one where the char is in PTDZ ;; ;; This is basically base92 ;; (define string-num-chars (string->list "!#$%&'()*+,-./0123456789:;<=>?@ABCEFGHIJKLMNOQRSUVWXY[\\]^_abcdefghijklmnopqrstuvwxyz{|}~")) ;; "0123456789abcdefghijklmnopqrstuvwxyzABCEFGHIJKLMNOQSUVWXY!#$%&'()*+,-./[]:;<=>?\\^_{}|")) (define (char-incr inchar) (let* ((carry #f) (next-char (let ((rem (member inchar string-num-chars))) (if (eq? (length rem) 1) ;; we are at the last character in our string-num-chars list (begin (set! carry #t) (car string-num-chars)) (cadr rem))))) (values next-char carry))) (define (increment-string str) (if (string-null? str) "0" (let ((strlst (reverse (string->list str)))) ;; need to process the string from the lsd (list->string (let loop ((hed (car strlst)) (tal (cdr strlst)) (res '())) (let-values (((newhed carry)(char-incr hed))) ;; (print "newhed: " newhed " carry: " carry " tal: " tal) (let ((newres (cons newhed res))) (if carry ;; we'll have to propagate the carry (if (null? tal) ;; at the end, tack on "0" (which is really a "1") (cons (car string-num-chars) newres) (loop (car tal)(cdr tal) newres)) (append (reverse tal) newres))))))))) ;;====================================================================== ;; P K T S D B I N T E R F A C E ;; ;; INTEGER, REAL, TEXT ;;====================================================================== ;; ;; spec ;; ( (tablename1 . (field1name L1 TYPE) ;; (field2name L2 TYPE) ... ) ;; (tablename2 ... )) ;; ;; Example: (tests (testname n TEXT) ;; (rundir r TEXT) ;; ... ) ;; ;; pkt keys are taken from the first letter, if that is not unique ;; then look at the next letter and so on ;; ;; use this struct to hold the pktspec and the db handle ;; (defstruct pktdb (fname #f) (pktsdb-spec #f) (pktspec #f) ;; cache the pktspec (field-keys #f) ;; cache the field->key mapping (field1 . k1) ... (key-fields #f) ;; cache the key->field mapping (conn #f) ) ;; WARNING: There is a simplification in the pktsdb spec w.r.t. pktspec. ;; The field specs are the cdr of the table list - not a full ;; list. The extra list level in pktspec is gratuitous and should ;; be removed. ;; (define (pktsdb-spec->pktspec tables-spec) (map (lambda (tablespec) (list (car tablespec) (map (lambda (field-spec) (cons (car field-spec)(cadr field-spec))) (cdr tablespec)))) tables-spec)) (define (pktsdb-open dbfname pktsdb-spec) (let* ((pdb (make-pktdb)) (dbexists (file-exists? dbfname)) (db (dbi:open 'sqlite3 `((dbname . ,dbfname))))) (pktdb-pktsdb-spec-set! pdb pktsdb-spec) (pktdb-pktspec-set! pdb (pktsdb-spec->pktspec pktsdb-spec)) (pktdb-fname-set! pdb dbfname) (pktdb-conn-set! pdb db) (if (not dbexists) (pktsdb-init pdb)) pdb)) (define (pktsdb-init pktsdb) (let* ((db (pktdb-conn pktsdb)) (pktsdb-spec (pktdb-pktsdb-spec pktsdb))) ;; create a table for the pkts themselves (dbi:exec db "CREATE TABLE IF NOT EXISTS pkts (id INTEGER PRIMARY KEY, zkey TEXT, record_id INTEGER, pkt TEXT);") (for-each (lambda (table) (let* ((table-name (car table)) (fields (cdr table)) (stmt (conc "CREATE TABLE IF NOT EXISTS " table-name " (id INTEGER PRIMARY KEY," (string-intersperse (map (lambda (fieldspec) (conc (car fieldspec) " " (caddr fieldspec))) fields) ",") ");"))) (dbi:exec db stmt))) pktsdb-spec))) ;; create pkt from the data and insert into pkts table ;; ;; data is assoc list of (field . value) ... ;; tablename is a symbol matching the table name ;; (define (pktsdb-add-record pktsdb tablename data #!optional (parent #f)) (let*-values (((zkey pkt) (alist->pkt data (pktdb-pktspec pktsdb) ptype: tablename))) ;; have the data as alist so insert it into appropriate table also (let* ((db (pktdb-conn pktsdb))) ;; TODO: Address collisions (dbi:exec db "INSERT INTO pkts (zkey,pkt,record_id) VALUES (?,?,?);" zkey pkt -1) (let* (;; (pktid (pktsdb-pktkey->pktid pktsdb pktkey)) (record-id (pktsdb-insert pktsdb tablename data))) (dbi:exec db "UPDATE pkts SET record_id=? WHERE zkey=?;" record-id zkey) )))) ;; (define (pktsdb-insert pktsdb tablename data) (let* ((db (pktdb-conn pktsdb)) (stmt (conc "INSERT INTO " tablename " (" (string-intersperse (map conc (map car data)) ",") ") VALUES ('" ;; TODO: Add lookup of data type and do not ;; wrap integers with quotes (string-intersperse (map conc (map cdr data)) "','") "');"))) (print "stmt: " stmt) (dbi:exec db stmt) ;; lookup the record-id and return it )) (define (pktsdb-close pktsdb) (dbi:close (pktdb-conn pktsdb))) ;; (let loop ((s "0")(n 0))(print s)(if (< n 5000)(loop (increment-string s)(+ n 1)))) ;;====================================================================== ;; CARDS, MISC and UTIL ;;====================================================================== ;; given string (likely multi-line) "dat" return shar1 hash ;; (define-inline (calc-shar1 instr) (message-digest-string (sha1-primitive) instr)) ;; given a single card return its type and value ;; (define (card->type/value card) (let ((ctype (substring card 0 1)) (cval (substring card 2 (string-length card)))) (values (string->symbol ctype) cval))) ;;====================================================================== ;; SDAT procs ;; sdat is legacy/internal usage. Intention is to remove sdat calls from ;; the exposed calls. ;;====================================================================== ;; sort list of cards ;; (define-inline (sort-cards sdat) (sort sdat string<=?)) ;; pkt rules ;; 1. one card per line ;; 2. at least one card ;; 3. no blank lines ;; given sdat, a list of cards return uuid, packet (as sdat) ;; (define (add-z-card sdat) (let* ((sorted-sdat (sort-cards sdat)) (dat (string-intersperse sorted-sdat "\n")) (uuid (calc-shar1 dat))) (values uuid (conc dat "\nZ " uuid)))) (define (check-pkt pkt) (handle-exceptions exn #f ;; anything goes wrong - call it a crappy pkt (let* ((sdat (string-split pkt "\n")) (rdat (reverse sdat)) ;; reversed (zdat (car rdat)) (Z (cadr (string-split zdat))) (cdat (string-intersperse (reverse (cdr rdat)) "\n"))) (equal? Z (calc-shar1 cdat))))) ;;====================================================================== ;; APKTs ;;====================================================================== ;; convert a sdat (list of cards) to an alist ;; (define (sdat->alist sdat) (let loop ((hed (car sdat)) (tal (cdr sdat)) (res '())) (let-values (( (ctype cval)(card->type/value hed) )) ;; if this card is not one of the common ones tack it on to rem (let* ((oldval (alist-ref ctype res)) (newres (cons (cons ctype (if oldval ;; list or string (if (list? oldval) (cons cval oldval) (cons cval (list oldval))) cval)) res))) (if (null? tal) newres (loop (car tal)(cdr tal) newres)))))) ;;((apkt (Z . "7de89c09ac024b3832c93e16cd78d11e2e28733b") <= this is a the alist ;; (t . "v1.63/tip/dev") ;; (c . "QUICKPATT") ;; (T . "runstart") ;; (P . "354eeb67120a921e3e33155ecab1b522ac10b6bd") ;; (D . "1488995096.0")) ;; (id . 8) ;; (group-id . 0) ;; (uuid . "7de89c09ac024b3832c93e16cd78d11e2e28733b") ;; (parent . "") ;; (pkt-type . "runstart") ;; (pkt . "D 1488995096.0\nP 354eeb67120a921e3e33155ecab1b522ac10b6bd\nT runstart\nc QUICKPATT\nt v1.63/tip/dev\nZ 7de89c09ac024b3832c93e16cd78d11e2e28733b")) ;; ;; pktspec is alist of alists mapping types and nicekeys to keys ;; ;; '((posting . ((title . t) ;; (url . u) ;; (blurb . b))) ;; (comment . ((comment . c) ;; (score . s)))) ;; DON'T USE? ;; (define (get-value field dpkt . spec-in) (if (null? spec-in) (alist-ref field dpkt) (let* ((spec (car spec-in)) (apkt (alist-ref 'apkt dpkt))) ;; get the pkt alist (if (and apkt spec) (let* ((ptype (alist-ref 'pkt-type dpkt)) (pspec (alist-ref (string->symbol ptype) spec))) ;; do we have a spec for this type of pkt (and pspec (let* ((key (alist-ref field pspec))) (and key (alist-ref key apkt))))) #f)))) ;; convert a dpkt to a pure alist given a pktspec ;; this flattens out the alist to include the data from ;; the queue database record ;; (define (dpkt->alist dpkt pktspec) (let* ((apkt (alist-ref 'apkt dpkt)) (pkt-type (or (alist-ref 'pkt-type dpkt) ;; pkt-type is from the database field pkt_type (alist-ref 'T apkt))) (pkt-fields (alist-ref (string->symbol pkt-type) pktspec)) (rev-fields (if pkt-fields (reverse-aspec pkt-fields) '()))) (append (map (lambda (entry) (let* ((pkt-key (car entry)) (new-key (or (alist-ref pkt-key rev-fields) pkt-key))) `(,new-key . ,(cdr entry)))) apkt) dpkt))) ;; convert a list of dpkts into a list of alists using pkt-spec ;; (define (dpkts->alists dpkts pkt-spec) (map (lambda (x) (dpkt->alist x pkt-spec)) dpkts)) ;; Generic flattener, make the tuple and pkt into a single flat alist ;; ;; qry-result-spec is a list of symbols corresponding to each field ;; (define (flatten-all inlst pktspec . qry-result-spec) (map (lambda (tuple) (dpkt->alist (apply dblst->dpkts tuple qry-result-spec) pktspec)) inlst)) ;; call like this: ;; (construct-sdat 'a "a data" 'S "S data" ...) ;; returns list of cards ;; ( "A a value" "D 12345678900" ...) ;; (define (construct-sdat . alldat) (let ((have-D-card #f)) ;; flag (if (even? (length alldat)) (let loop ((type (car alldat)) (data (cadr alldat)) (tail (cddr alldat)) (res '())) (if (eq? type 'D)(set! have-D-card #t)) (if (null? tail) (if have-D-card ;; return the constructed pkt, add a D card if none found (add-card res type data) (add-card (add-card res 'D (current-seconds)) type data)) (loop (car tail) (cadr tail) (cddr tail) (add-card res type data)))) #f))) ;; #f means it failed to create the sdat (define (construct-pkt . alldat) (add-z-card (apply construct-sdat alldat))) ;;====================================================================== ;; CONVERTERS ;;====================================================================== (define (pkt->sdat pkt) (map unescape-data (string-split pkt "\n"))) ;; given a pure pkt return an alist ;; (define (pkt->alist pkt #!key (pktspec #f)) (let ((sdat (cond ((string? pkt) (pkt->sdat pkt)) ((list? pkt) pkt) (else #f)))) (if pkt (if pktspec (dpkt->alist (list (cons 'apkt (sdat->alist sdat))) pktspec) (sdat->alist sdat)) #f))) ;; convert an alist to an sdat ;; in: '((a . "blah")(b . "foo")) ;; out: '("a blah" "b foo") ;; (define (alist->sdat adat) (map (lambda (dat) (conc (car dat) " " (cdr dat))) adat)) ;; adat is the incoming alist, aspec is the mapping ;; from incoming key to the pkt key (usually one ;; letter to keep data tight) see the pktspec at the ;; top of this file ;; ;; NOTE: alists can contain multiple instances of the same key (supported fine by pkts) ;; but you (obviously I suppose) cannot use alist-ref to access those entries. ;; (define (alist->pkt adat aspec #!key (ptype #f)) (let* ((pkt-type (or ptype (alist-ref 'T adat) ;; can provide in the incoming alist #f)) (pkt-spec (if pkt-type ;; alist of external-key -> key (or (alist-ref pkt-type aspec) '()) (if (null? aspec) '() (cdar aspec)))) ;; default to first one if nothing specified (new-alist (map (lambda (dat) (let* ((key (car dat)) (val (cdr dat)) (newkey (or (alist-ref key pkt-spec) key))) (cons newkey (escape-data (conc val))))) ;; convert all incoming data (symbols, numbers etc.) to a string and then escape newlines. adat)) (new-with-type (if (alist-ref 'T new-alist) new-alist (cons `(T . ,pkt-type) new-alist))) (with-d-card (if (alist-ref 'D new-with-type) new-with-type (cons `(D . ,(current-seconds)) new-with-type)))) (add-z-card (alist->sdat with-d-card)))) ;;====================================================================== ;; D B Q U E U E I N T E R F A C E ;;====================================================================== ;; pkts ( ;; id SERIAL PRIMARY KEY, ;; uuid TEXT NOT NULL, ;; parent_uuid TEXT default '', ;; pkt_type INTEGER DEFAULT 0, ;; group_id INTEGER NOT NULL, ;; pkt TEXT NOT NULL ;; schema is list of SQL statements - can be used to extend db with more tables ;; (define (open-queue-db dbpath dbfile #!key (schema '())) (let* ((dbfname (conc dbpath "/" dbfile)) (dbexists (if (file-exists? dbfname) #t (begin (create-directory dbpath #t) #f))) (db (dbi:open 'sqlite3 (list (cons 'dbname dbfname))))) ;; (set-busy-handler! db (busy-timeout 10000)) (if (not dbexists) ;; NOTE: In the archive we allow duplicates and other messiness. (for-each (lambda (stmt) (dbi:exec db stmt)) (cons "CREATE TABLE IF NOT EXISTS pkts (id INTEGER PRIMARY KEY, group_id INTEGER NOT NULL, uuid TEXT NOT NULL, parent_uuid TEXT TEXT DEFAULT '', pkt_type TEXT NOT NULL, pkt TEXT NOT NULL, processed INTEGER DEFAULT 0)" schema))) ;; 0=not processed, 1=processed, 2... for expansion db)) (define (add-to-queue db pkt uuid pkt-type parent-uuid group-id) (dbi:exec db "INSERT INTO pkts (uuid,parent_uuid,pkt_type,pkt,group_id) VALUES(?,?,?,?,?);" ;; $1,$2,$3,$4,$5);" uuid (if parent-uuid parent-uuid "");; use null string as placeholder for no parent uuid. (if pkt-type (conc pkt-type) "") pkt group-id)) ;; given all needed parameters create a pkt and store it in the queue ;; procs is an alist that maps pkt-type to a function that takes a list of pkt params ;; in data and returns the uuid and pkt ;; (define (create-and-queue conn procs pkt-type parent-uuid group-id data) (let ((proc (alist-ref pkt-type procs))) (if proc (let-values (( (uuid pkt) (proc data) )) (add-to-queue conn pkt uuid pkt-type parent-uuid group-id) uuid) #f))) ;; given uuid get pkt, if group-id is specified use it (reduces probablity of ;; being messed up by a uuid collision) ;; (define (lookup-by-uuid db pkt-uuid group-id) (if group-id (dbi:get-one db "SELECT pkt FROM pkts WHERE group_id=? AND uuid=?;" group-id pkt-uuid) (dbi:get-one db "SELECT pkt FROM pkts WHERE uuid=?;" pkt-uuid))) ;; find a packet by its id ;; (define (lookup-by-id db id) (dbi:get-one db "SELECT pkt FROM pkts WHERE id=?;" id)) ;; apply a proc to the open db handle for a pkt db in pdbpath ;; (define (with-queue-db pdbpath proc #!key (schema #f)) (cond ((not (equal? (file-owner pdbpath)(current-effective-user-id))) (print "ERROR: directory " pdbpath " is not owned by " (current-effective-user-name))) (else (let* ((pdb (open-queue-db pdbpath "pkts.db" schema: schema)) ;; '("CREATE TABLE groups (id INTEGER PRIMARY KEY,groupname TEXT, CONSTRAINT group_constraint UNIQUE (groupname));")))) (res (proc pdb))) (dbi:close pdb) res)))) (define (load-pkts-to-db pktsdirs pdbpath #!key (schema #f)) (with-queue-db pdbpath (lambda (pdb) (for-each (lambda (pktsdir) ;; look at all (cond ((not (file-exists? pktsdir)) (print "ERROR: packets directory " pktsdir " does not exist.")) ((not (directory? pktsdir)) (print "ERROR: packets directory path " pktsdir " is not a directory.")) ((not (file-read-access? pktsdir)) (print "ERROR: packets directory path " pktsdir " is not readable.")) (else ;; (print "INFO: Loading packets found in " pktsdir) (let ((pkts (glob (conc pktsdir "/*.pkt")))) (for-each (lambda (pkt) (let* ((uuid (cadr (string-match ".*/([0-9a-f]+).pkt" pkt))) (exists (lookup-by-uuid pdb uuid #f))) (if (not exists) (let* ((pktdat (string-intersperse (with-input-from-file pkt read-lines) "\n")) (apkt (pkt->alist pktdat)) (ptype (alist-ref 'T apkt))) (add-to-queue pdb pktdat uuid (or ptype 'cmd) #f 0)) ;; (debug:print 4 *default-log-port* "Added " uuid " of type " ptype " to queue")) ;; (debug:print 4 *default-log-port* "pkt: " uuid " exists, skipping...") ))) pkts))))) pktsdirs)))) ;;====================================================================== ;; P R O C E S S P K T S ;;====================================================================== ;; given a list of field values pulled from the queue db generate a list ;; of dpkt's ;; (define (dblst->dpkts lst . altmap) (let* ((maplst (if (null? altmap) '(id group-id uuid parent pkt-type pkt processed) altmap)) (res (map cons maplst lst))) ;; produces list of pairs, i.e an alist (cons `(apkt . ,(pkt->alist (alist-ref 'pkt res))) res))) ;; NB// ptypes is a list of symbols, '() or #f find all types ;; (define (get-dpkts db ptypes group-id parent-uuid #!key (uuid #f)) (let* ((ptype-qry (if (and ptypes (not (null? ptypes))) (conc " IN ('" (string-intersperse (map conc ptypes) "','") "')") (conc " LIKE '%' "))) (rows (dbi:get-rows db (conc "SELECT id,group_id,uuid,parent_uuid,pkt_type,pkt,processed FROM pkts WHERE pkt_type " ptype-qry " AND group_id=? AND processed=0 " (if parent-uuid (conc "AND parent_uuid='" parent-uuid "' ") "") (if uuid (conc "AND uuid='" uuid "' ") "") "ORDER BY id DESC;") group-id))) (map dblst->dpkts (map vector->list rows)))) ;; get N pkts not yet processed for group-id ;; (define (get-not-processed-pkts db group-id pkt-type limit offset) (map dblst->dpkts (map vector->list (dbi:get-rows db "SELECT id,group_id,uuid,parent_uuid,pkt_type,pkt,processed FROM pkts WHERE pkt_type = ? AND group_id = ? AND processed=0 LIMIT ? OFFSET ?;" (conc pkt-type) ;; convert symbols to string group-id limit offset )))) ;; given a uuid, get not processed child pkts ;; (define (get-related db group-id uuid) (map dblst->dpkts (dbi:get-rows db "SELECT id,group_id,uuid,parent_uuid,pkt_type,pkt,processed FROM pkts WHERE parent_uuid=? AND group_id=? AND processed=0;" uuid group-id))) ;; generic pkt processor ;; ;; find all packets in group-id of type in ptypes and apply proc to pktdat ;; (define (process-pkts conn group-id ptypes parent-uuid proc) (let* ((pkts (get-dpkts conn ptypes group-id parent-uuid))) (map proc pkts))) ;; criteria is an alist ((k . valpatt) ...) ;; - valpatt is a regex ;; - ptypes is a list of types (symbols expected) ;; match-type: 'any or 'all ;; (define (find-pkts db ptypes criteria #!key (processed #f)(match-type 'any)(pkt-spec #f)) ;; processed=#f, don't use, else use (let* ((pkts (get-dpkts db ptypes 0 #f)) (match-rules (lambda (pktdat) ;; returns a list of matching rules (filter (lambda (c) ;; (print "c: " c) (let* ((ctype (car c)) ;; card type (rx (cdr c)) ;; card pattern ;; (t (alist-ref 'pkt-type pktdat)) (pkt (alist-ref 'pkt pktdat)) (apkt (pkt->alist pkt)) (cdat (alist-ref ctype apkt))) ;; (print "cdat: " cdat) ;; " apkt: " apkt) (if cdat (string-match rx cdat) #f))) criteria))) (res (filter (lambda (pktdat) (if (null? criteria) ;; looking for all pkts #t (case match-type ((any)(not (null? (match-rules pktdat)))) ((all)(eq? (length (match-rules pktdat))(length criteria))) (else (print "ERROR: bad match type " match-type ", expecting any or all."))))) pkts))) (if pkt-spec (dpkts->alists res pkt-spec) res))) ;; get descendents of parent-uuid ;; ;; NOTE: Should be doing something like the following: ;; ;; given a uuid, get not processed child pkts ;; processed: ;; #f => get all ;; 0 => get not processed ;; 1 => get processed ;; (define (get-ancestors db group-id uuid #!key (processed #f)) (map dblst->dpkts (map vector->list (dbi:get-rows db (conc "SELECT id,group_id,uuid,parent_uuid,pkt_type,pkt,processed FROM pkts WHERE uuid IN (WITH RECURSIVE tree(uuid,parent_uuid) AS ( SELECT uuid, parent_uuid FROM pkts WHERE uuid = ? UNION ALL SELECT t.uuid, t.parent_uuid FROM pkts t JOIN tree ON t.uuid = tree.parent_uuid ) SELECT uuid FROM tree) AND group_id=?" (if processed (conc " AND processed=" processed) "") ";") uuid group-id)))) ;; Untested ;; (define (get-descendents db group-id uuid #!key (processed #f)) (map dblst->dpkts (map vector->list (dbi:get-rows db (conc "SELECT id,group_id,uuid,parent_uuid,pkt_type,pkt,processed FROM pkts WHERE uuid IN (WITH RECURSIVE tree(uuid,parent_uuid) AS ( SELECT uuid, parent_uuid FROM pkts WHERE uuid = ? UNION ALL SELECT t.uuid, t.parent_uuid FROM pkts t JOIN tree ON t.parent_uuid = tree.uuid ) SELECT uuid FROM tree) AND group_id=?" (if processed (conc " AND processed=" processed) "") ";") uuid group-id)))) ;; look up descendents based on given info unless passed in a list via inlst ;; (define (get-last-descendent db group-id uuid #!key (processed #f)(inlst #f)) (let ((descendents (or inlst (get-descendents db group-id uuid processed: processed)))) (if (null? descendents) #f (last descendents)))) ;;====================================================================== ;; A R C H I V E S - always to a sqlite3 db ;;====================================================================== ;; open an archive db ;; path: archive-dir/<year>/month.db ;; (define (archive-open-db archive-dir) (let* ((curr-time (seconds->local-time (current-seconds))) (dbpath (conc archive-dir "/" (time->string curr-time "%Y"))) (dbfile (conc dbpath "/" (time->string curr-time "%m") ".db")) (dbexists (if (file-exists? dbfile) #t (begin (create-directory dbpath #t) #f)))) (let ((db (dbi:open 'sqlite3 (list (cons 'dbname dbfile))))) ;; (set-busy-handler! db (busy-timeout 10000)) (if (not dbexists) ;; NOTE: In the archive we allow duplicates and other messiness. (dbi:exec db "CREATE TABLE IF NOT EXISTS pkts (id INTEGER, group_id INTEGER, uuid TEXT, parent_uuid TEXT, pkt_type TEXT, pkt TEXT, processed INTEGER DEFAULT 0)")) db))) ;; turn on transactions! otherwise this will be painfully slow ;; (define (write-archive-pkts src-db db pkt-ids) (let ((pkts (dbi:get-rows src-db (conc "SELECT id,group_id,uuid,parent_uuid,pkt_type,pkt FROM pkts WHERE id IN (" (string-intersperse (map conc pkt-ids) ",") ")")))) ;; (dbi:with-transaction ;; db (lambda () (for-each (lambda (pkt) (apply dbi:exec db "INSERT INTO pkts (id,group_id,uuid,parent_uuid,pkt_type,pkt) VALUES (?,?,?,?,?,?)" pkt)) pkts)))) ;; ) ;; given a list of uuids and lists of uuids move all to ;; the sqlite3 db for the current archive period ;; (define (archive-pkts conn pkt-ids archive-dir) (let ((db (archive-open-db archive-dir))) (write-archive-pkts conn db pkt-ids) (dbi:close db)) ;; (pg:with-transaction ;; conn ;; (lambda () (for-each (lambda (id) (dbi:get-one conn "DELETE FROM pkts WHERE id=?" id)) pkt-ids)) ;; )) ;; given a list of ids mark all as processed ;; (define (mark-processed conn pkt-ids) ;; (pg:with-transaction ;; conn ;; (lambda () (for-each (lambda (id) (dbi:get-one conn "UPDATE pkts SET processed=1 WHERE id=?;" id)) pkt-ids)) ;; x)) ;; a generic pkt getter, gets from the pkts db ;; (define (get-pkts conn ptypes) (let* ((ptypes-str (if (null? ptypes) "" (conc " WHERE pkt_type IN ('" (string-intersperse ptypes ",") "') "))) (qry-str (conc "SELECT id,group_id,uuid,parent_uuid,pkt_type,pkt,processed FROM pkts" ptypes-str))) (map vector->list (dbi:get-rows conn qry-str)))) ;; make a report of the pkts in the db ;; ptypes of '() gets all pkts ;; display-fields ;; (define (make-report dest conn pktspec display-fields . ptypes) (let* (;; (conn (dbi:db-conn (s:db))) (all-rows (get-pkts conn ptypes)) (all-pkts (flatten-all all-rows pktspec 'id 'group-id 'uuid 'parent 'pkt-type 'pkt 'processed)) (by-uuid (let ((ht (make-hash-table))) (for-each (lambda (pkt) (let ((uuid (alist-ref 'uuid pkt))) (hash-table-set! ht uuid pkt))) all-pkts) ht)) (by-parent (let ((ht (make-hash-table))) (for-each (lambda (pkt) (let ((parent (alist-ref 'parent pkt))) (hash-table-set! ht parent (cons pkt (hash-table-ref/default ht parent '()))))) all-pkts) ht)) (oup (if dest (open-output-file dest) (current-output-port)))) (with-output-to-port oup (lambda () (print "digraph megatest_state_status { // ranksep=0.05 rankdir=LR; node [shape=\"box\"]; ") ;; first all the names (for-each (lambda (pkt) (let* ((uuid (alist-ref 'uuid pkt)) (shortuuid (substring uuid 0 4)) (type (alist-ref 'pkt-type pkt)) (processed (alist-ref 'processed pkt))) (print "\"" uuid "\" [label=\"" shortuuid ", (" type ", " (if processed "processed" "not processed") ")") (for-each (lambda (key-field) (let ((val (alist-ref key-field pkt))) (if val (print key-field "=" val)))) display-fields) (print "\" ];"))) all-pkts) ;; now for parent-child relationships (for-each (lambda (pkt) (let ((uuid (alist-ref 'uuid pkt)) (parent (alist-ref 'parent pkt))) (if (not (equal? parent "")) (print "\"" parent "\" -> \"" uuid"\";")))) all-pkts) (print "}") )) (if dest (begin (close-output-port oup) (system "dot -Tpdf out.dot -o out.pdf"))) )) ;;====================================================================== ;; Read ref pkts into a vector < laststr hash table > ;;====================================================================== ;;====================================================================== ;; Read/write packets to files (convience functions) ;;====================================================================== ;; write alist to a pkt file ;; (define (write-alist->pkt targdir dat #!key (pktspec '())(ptype #f)) (let-values (((uuid pkt)(alist->pkt dat pktspec ptype: ptype))) (with-output-to-file (conc targdir "/" uuid ".pkt") (lambda () (print pkt))) uuid)) ;; return the uuid ;; read pkt into alist ;; (define (read-pkt->alist pkt-file #!key (pktspec #f)) (pkt->alist (with-input-from-file pkt-file read-string) pktspec: pktspec)) ) ;; module pkts |
Added pkts/pkts.setup version [bf666feb42].
> > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 | ;; Copyright 2007-2017, Matthew Welland. ;; ;; This program is made available under the GNU GPL version 2.0 or ;; greater. See the accompanying file COPYING for details. ;; ;; This program is distributed WITHOUT ANY WARRANTY; without even the ;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ;; PURPOSE. ;;;; pkts.setup (standard-extension 'pkts "1.0") |
Added pkts/tests/run.scm version [957c7c2ae2].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | (use test) ;; (use (prefix pkts pkts:)) (use pkts (prefix dbi dbi:)) ;; (use trace)(trace sdat->alist pkt->alist) (if (file-exists? "queue.db")(delete-file "queue.db")) (test-begin "pkts and pkt archives") ;;====================================================================== ;; Basic pkt creation, parsing and conversion routines ;;====================================================================== (test-begin "basic packets") (test #f '(A "This is a packet") (let-values (((t v) (card->type/value "A This is a packet"))) (list t v))) (test #f "A A\nZ 664449e7299e0065a3e25c138ccef2df13ba291e" (let-values (((uuid res) (add-z-card '("A A")))) res)) (test #f '("CC C++" "D 1486332719.0" "a A" "b C")(sort (construct-sdat 'b "C" 'a "A" 'CC "C++" 'D 1486332719.0) string<=?)) (define pkt-example #f) (test #f "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84" (let-values (((uuid res) (construct-pkt 'b "C" 'a "A" 'CC "C++" 'D 1486332719.0))) (set! pkt-example (cons uuid res)) res)) (test-end "basic packets") ;;====================================================================== ;; Sqlite and postgresql based queue of pkts ;;====================================================================== (test-begin "pkt queue") (define db #f) (test #f 'sqlite3 (let ((dbh (open-queue-db "." "queue.db"))) (set! db dbh) (dbi:db-dbtype dbh))) (test #f (cdr pkt-example) (begin (add-to-queue db (cdr pkt-example)(car pkt-example) 'basic #f 0) (lookup-by-uuid db (car pkt-example) 0))) (test #f (cdr pkt-example) (lookup-by-id db 1)) (test #f 1 (length (find-pkts db '(basic) '()))) (test-end "pkt queue") ;;====================================================================== ;; Process groups of pkts ;;====================================================================== (test-begin "lists of packets") (test #f '((apkt . #f) (id . 1) (group-id . 2) (uuid . 3) (parent . 4) (pkt-type . 5)) ;; ((id . 1) (group-id . 2) (uuid . 3) (parent . 4) (pkt-type . 5)) (dblst->dpkts '(1 2 3 4 5))) (test #f '(((apkt (Z . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (b . "C") (a . "A") (D . "1486332719.0") (C . " C++")) (id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (processed . 0))) ;; '(((apkt (Z . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (b . "C") (a . "A") (D . "1486332719.0") (C . " C++")) (id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84"))) ;; '(((id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84"))) (get-dpkts db '(basic) 0 #f)) (test #f '(((apkt (Z . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (b . "C") (a . "A") (D . "1486332719.0") (C . " C++")) (id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (processed . 0))) ;; '(((apkt (Z . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (b . "C") (a . "A") (D . "1486332719.0") (C . " C++")) (id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84"))) ;; '(((id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84"))) (get-not-processed-pkts db 0 'basic 1000 0)) (test-end "lists of packets") (test-begin "pkts as alists") (define pktspec '((posting . ((title . t) ;; NOTE: same as ((posting (title . t)(url . u)(blub . b)) ... (url . u) (blurb . b))) (comment . ((comment . c) (score . s))) (basic . ((b-field . b) (a-field . a))))) (define pktlst (find-pkts db '(basic) '())) (define dpkt (car pktlst)) (test #f "A" (get-value 'a-field dpkt pktspec)) (test #f "C" (alist-ref 'b-field (dpkt->alist dpkt pktspec))) (define basic-spec '((nada (foo . b)(bar . f))(basic (foo . f)(bar . b)))) (define test-pkt '((foo . "fooval")(bar . "barval"))) (let*-values (((u p) (alist->pkt test-pkt basic-spec ptype: 'basic)) ((apkt) (pkt->alist p)) ((bpkt) (pkt->alist p pktspec: basic-spec))) (test #f "fooval" (alist-ref 'f apkt)) (test #f "fooval" (alist-ref 'foo bpkt)) (test #f #f (alist-ref 'f bpkt))) (test-end "pkts as alists") (test-begin "descendents and ancestors") (define (get-uuid pkt)(alist-ref 'uuid pkt)) ;; add a child to 263e (let-values (((uuid pkt) (construct-pkt 'x "X" 'y "Y" 'P "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84" 'D "1486332719.0"))) (add-to-queue db pkt uuid 'basic "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84" 0)) (test #f '("263eb3b6193de7fe65b1ded5bcda513e8b4d6b84" "818fe30988c9673441b8f203972a8bda6af682f8") (map (lambda (x)(alist-ref 'uuid x)) (get-descendents db 0 "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84"))) (test #f '("263eb3b6193de7fe65b1ded5bcda513e8b4d6b84" "818fe30988c9673441b8f203972a8bda6af682f8") (map (lambda (x)(alist-ref 'uuid x)) (get-ancestors db 0 "818fe30988c9673441b8f203972a8bda6af682f8"))) (test-end "descendents and ancestors") (test-end "pkts and pkt archives") (test-begin "pktsdb") (define spec '((tests (testname n TEXT) (testpath p TEXT) (duration d INTEGER)))) ;; (define pktsdb (make-pktdb)) ;; (pktdb-pktsdb-spec-set! pktsdb spec) (define pktsdb #f) (test #f #t (dbi:database? (let ((pdb (pktsdb-open "test.db" spec))) (set! pktsdb pdb) (pktdb-conn pdb)))) ;; (pp (pktdb-pktspec pktsdb)) (test #f #t (pktsdb-add-record pktsdb 'tests '((testname . "test1")))) (pktsdb-close pktsdb) (test-end "pktsdb") |
Modified rmt-inc.scm from [507254531f] to [8953c5e876].
︙ | ︙ | |||
70 71 72 73 74 75 76 | (client:setup areapath) #f)))) (define *send-receive-mutex* (make-mutex)) ;; should have separate mutex per run-id (define (rmt:send-receive cmd rid params #!key (attemptnum 1)(area-dat #f)) ;; start attemptnum at 1 so the modulo below works as expected (rmt:open-qry-close-locally cmd 0 params)) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | > > > > > > > > > > > > | < < < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | (client:setup areapath) #f)))) (define *send-receive-mutex* (make-mutex)) ;; should have separate mutex per run-id (define (rmt:send-receive cmd rid params #!key (attemptnum 1)(area-dat #f)) ;; start attemptnum at 1 so the modulo below works as expected (rmt:open-qry-close-locally cmd 0 params)) ;; ;; ;; #;(common:telemetry-log (conc "rmt:"(->string cmd)) ;; ;; #;(define (rmt:send-receive cmd rid params #!key (attemptnum 1)(area-dat #f)) ;; start attemptnum at 1 so the modulo below works as expected ;; ;; ;; ;; #;(common:telemetry-log (conc "rmt:"(->string cmd)) ;; ;; payload: `((rid . ,rid) ;; ;; (params . ,params))) ;; ;; ;; ;; do all the prep locked under the rmt-mutex ;; (mutex-lock! *rmt-mutex*) ;; ;; ;; 1. check if server is started IFF cmd is a write OR if we are not on the homehost, store in runremote ;; ;; 2. check the age of the connections. refresh the connection if it is older than timeout-20 seconds. ;; ;; 3. do the query, if on homehost use local access ;; ;; ;; (let* ((start-time (current-seconds)) ;; snapshot time so all use cases get same value ;; (areapath *toppath*);; TODO - resolve from dbstruct to be compatible with multiple areas ;; (runremote (or area-dat ;; *runremote*)) ;; (readonly-mode (rmtmod:calc-ro-mode runremote *toppath*))) ;; ;; ;; ensure we have a record for our connection for given area ;; (if (not runremote) ;; can remove this one. should never get here. ;; (begin ;; (set! *runremote* (make-remote)) ;; (set! runremote *runremote*))) ;; new runremote will come from this on next iteration ;; ;; ;; ensure we have a homehost record ;; (if (not (pair? (remote-hh-dat runremote))) ;; not on homehost ;; (thread-sleep! 0.1) ;; since we shouldn't get here, delay a little ;; (remote-hh-dat-set! runremote (common:get-homehost))) ;; ;; ;;(print "BB> readonly-mode is "readonly-mode" dbfile is "dbfile) ;; (cond ;; ;; give up if more than 15 attempts ;; ((> attemptnum 15) ;; (debug:print 0 *default-log-port* "ERROR: 15 tries to start/connect to server. Giving up.") ;; (exit 1)) ;; ;; ;; readonly mode, read request- handle it - case 2 ;; ((and readonly-mode ;; (member cmd api:read-only-queries)) ;; (mutex-unlock! *rmt-mutex*) ;; (debug:print-info 12 *default-log-port* "rmt:send-receive, case 2") ;; (rmt:open-qry-close-locally cmd 0 params) ;; ) ;; ;; ;; readonly mode, write request. Do nothing, return #f ;; (readonly-mode (extras-readonly-mode *rmt-mutex* *default-log-port* cmd params)) ;; ;; ;; This block was for pre-emptively resetting the connection if there had been no communication for some time. ;; ;; I don't think it adds any value. If the server is not there, just fail and start a new connection. ;; ;; also, the expire-time calculation might not be correct. We want, time-since-last-server-access > (server:get-timeout) ;; ;; ;; ;; reset the connection if it has been unused too long ;; ((and runremote ;; (remote-conndat runremote) ;; (> (current-seconds) ;; if it has been more than server-timeout seconds since last contact, close this connection and start a new on ;; (+ (http-transport:server-dat-get-last-access (remote-conndat runremote)) ;; (remote-server-timeout runremote)))) ;; (debug:print-info 0 *default-log-port* "Connection to " (remote-server-url runremote) " expired due to no accesses, forcing new connection.") ;; (http-transport:close-connections area-dat: runremote) ;; (remote-conndat-set! runremote #f) ;; invalidate the connection, thus forcing a new connection. ;; (mutex-unlock! *rmt-mutex*) ;; (rmt:send-receive cmd rid params attemptnum: attemptnum)) ;; ;; ;; on homehost and this is a read ;; ((and (not (remote-force-server runremote)) ;; honor forced use of server, i.e. server NOT required ;; (cdr (remote-hh-dat runremote)) ;; on homehost ;; (member cmd api:read-only-queries)) ;; this is a read ;; (mutex-unlock! *rmt-mutex*) ;; (debug:print-info 12 *default-log-port* "rmt:send-receive, case 5") ;; (rmt:open-qry-close-locally cmd 0 params)) ;; ;; ;; on homehost and this is a write, we already have a server, but server has died ;; ((and (cdr (remote-hh-dat runremote)) ;; on homehost ;; (not (member cmd api:read-only-queries)) ;; this is a write ;; (remote-server-url runremote) ;; have a server ;; (not (server:ping (remote-server-url runremote)))) ;; server has died. NOTE: this is not a cheap call! Need better approach. ;; (set! *runremote* (make-remote)) ;; (remote-force-server-set! runremote (common:force-server?)) ;; (mutex-unlock! *rmt-mutex*) ;; (debug:print-info 12 *default-log-port* "rmt:send-receive, case 6") ;; (rmt:send-receive cmd rid params attemptnum: attemptnum)) ;; ;; ;; on homehost and this is a write, we already have a server ;; ((and (not (remote-force-server runremote)) ;; honor forced use of server, i.e. server NOT required ;; (cdr (remote-hh-dat runremote)) ;; on homehost ;; (not (member cmd api:read-only-queries)) ;; this is a write ;; (remote-server-url runremote)) ;; have a server ;; (mutex-unlock! *rmt-mutex*) ;; (debug:print-info 12 *default-log-port* "rmt:send-receive, case 4.1") ;; (rmt:open-qry-close-locally cmd 0 params)) ;; ;; ;; on homehost, no server contact made and this is a write, passively start a server ;; ((and (not (remote-force-server runremote)) ;; honor forced use of server, i.e. server NOT required ;; (cdr (remote-hh-dat runremote)) ;; have homehost ;; (not (remote-server-url runremote)) ;; no connection yet ;; (not (member cmd api:read-only-queries))) ;; not a read-only query ;; (debug:print-info 12 *default-log-port* "rmt:send-receive, case 8") ;; (let ((server-url (server:check-if-running *toppath*))) ;; (server:read-dotserver->url *toppath*))) ;; (server:check-if-running *toppath*))) ;; Do NOT want to run server:check-if-running - very expensive to do for every write call ;; (if server-url ;; (remote-server-url-set! runremote server-url) ;; the string can be consumed by the client setup if needed ;; (if (common:force-server?) ;; (server:start-and-wait *toppath*) ;; (server:kind-run *toppath*)))) ;; (remote-force-server-set! runremote (common:force-server?)) ;; (mutex-unlock! *rmt-mutex*) ;; (debug:print-info 12 *default-log-port* "rmt:send-receive, case 8.1") ;; (rmt:open-qry-close-locally cmd 0 params)) ;; ;; ((or (and (remote-force-server runremote) ;; we are forcing a server and don't yet have a connection to one ;; (not (remote-conndat runremote))) ;; (and (not (cdr (remote-hh-dat runremote))) ;; not on a homehost ;; (not (remote-conndat runremote)))) ;; and no connection ;; (debug:print-info 12 *default-log-port* "rmt:send-receive, case 9, hh-dat: " (remote-hh-dat runremote) " conndat: " (remote-conndat runremote)) ;; (mutex-unlock! *rmt-mutex*) ;; (if (not (server:check-if-running *toppath*)) ;; who knows, maybe one has started up? ;; (server:start-and-wait *toppath*)) ;; (remote-conndat-set! runremote (rmt:get-connection-info *toppath*)) ;; calls client:setup which calls client:setup-http ;; (rmt:send-receive cmd rid params attemptnum: attemptnum)) ;; TODO: add back-off timeout as ;; ;; ;; all set up if get this far, dispatch the query ;; ((and (not (remote-force-server runremote)) ;; (cdr (remote-hh-dat runremote))) ;; we are on homehost ;; (mutex-unlock! *rmt-mutex*) ;; (debug:print-info 12 *default-log-port* "rmt:send-receive, case 10") ;; (rmt:open-qry-close-locally cmd (if rid rid 0) params)) ;; ;; ;; not on homehost, do server query ;; (else (extras-case-11 *default-log-port* runremote cmd params attemptnum rid))))) ;; bunch of small functions factored out of send-receive to make debug easier ;; (define (extras-case-11 *default-log-port* runremote cmd params attemptnum rid) ;; (mutex-unlock! *rmt-mutex*) (debug:print-info 12 *default-log-port* "rmt:send-receive, case 9") |
︙ | ︙ |