diff --git a/README b/README new file mode 100644 index 0000000..4181c15 --- /dev/null +++ b/README @@ -0,0 +1,13 @@ + chez-openbsd - mirror of ChezScheme with OpenBSD boot files +============================================================= + +THIS REPO IS A MIRROR OF https://github.com/cisco/ChezScheme CONTAINING OPENBSD BOOT FILES. +I am not the owner of ChezScheme nor a developer of ChezScheme. +Please send issues related to ChezScheme directly to their Github repo. +You'll find a copy of the original README in README.md. + +To build on OpenBSD, simply do `./configure --threads` and `gmake -jN`, +`--threads` enabling posix thread support and N in `-jN` being the number of cores in your system. + +See https://git.heimdall.pm/chez-openbsd/releases for releases. +See https://heimdall.pm/blog/2022/07/28/how-to-build-chezscheme-on-openbsd.html for more information. diff --git a/README.md b/README.md index 633c955..65aaf2a 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,60 @@ -# chez-openbsd - mirror of ChezScheme with OpenBSD boot files -## ChezScheme v9.5.9 - -**THIS REPO IS A MIRROR OF [CHEZSCHEME](https://github.com/cisco/ChezScheme) CONTAINING OPENBSD BOOT FILES.** -I am not the owner of ChezScheme nor a developer of ChezScheme. -Please send issues related to ChezScheme directly to their [Github repo](https://github.com/cisco/ChezScheme). -You'll find a copy of the original README in `README.original.md`. - -To build on OpenBSD, simply do: -```bash -$ ./configure --threads -$ gmake -jN -``` -`--threads` enables (posix) thread support and the `N` in `-jN` being the number of cores in your system. - -See [releases](https://basedwa.re/tmtt/chez-openbsd/releases). -See [the original blogpost](https://heimdall.pm/blog/2022/07/28/how-to-build-chezscheme-on-openbsd.html) for more information. +[![test](https://github.com/cisco/ChezScheme/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/cisco/ChezScheme/actions/workflows/test.yml) + +Chez Scheme is both a programming language and an implementation +of that language, with supporting tools and documentation. + +As a superset of the language described in the +[Revised6 Report on the Algorithmic Language Scheme](http://www.r6rs.org) +(R6RS), Chez Scheme supports all standard features of Scheme, +including first-class procedures, proper treatment of tail calls, +continuations, user-defined records, libraries, exceptions, and +hygienic macro expansion. + +Chez Scheme also includes extensive support for interfacing with C +and other languages, support for multiple threads possibly running +on multiple cores, non-blocking I/O, and many other features. + +The Chez Scheme implementation consists of a compiler, run-time +system, and programming environment. +Although an interpreter is available, all code is compiled by +default. +Source code is compiled on-the-fly when loaded from a source file +or entered via the shell. +A source file can also be precompiled into a stored binary form and +automatically recompiled when its dependencies change. +Whether compiling on the fly or precompiling, the compiler produces +optimized machine code, with some optimization across separately +compiled library boundaries. +The compiler can also be directed to perform whole-program compilation, +which does full cross-library optimization and also reduces a +program and the libraries upon which it depends to a single binary. + +The run-time system interfaces with the operating system and supports, +among other things, binary and textual (Unicode) I/O, automatic +storage management (dynamic memory allocation and generational +garbage collection), library management, and exception handling. +By default, the compiler is included in the run-time system, allowing +programs to be generated and compiled at run time, and storage for +dynamically compiled code, just like any other dynamically allocated +storage, is automatically reclaimed by the garbage collector. + +The programming environment includes a source-level debugger, a +mechanism for producing HTML displays of profile counts and program +"hot spots" when profiling is enabled during compilation, tools for +inspecting memory usage, and an interactive shell interface (the +expression editor, or "expeditor" for short) that supports multi-line +expression editing. + +The R6RS core of the Chez Scheme language is described in +[The Scheme Programming Language](http://www.scheme.com/tspl4/), +which also includes an introduction to Scheme and a set of example programs. +Chez Scheme's additional language, run-time system, and +programming environment features are described in the +[Chez Scheme User's Guide](http://cisco.github.io/ChezScheme/csug9.5/csug.html). +The latter includes a shared index and a shared summary of forms, +with links where appropriate to the former, so it is often the best +starting point. + +Get started with Chez Scheme by [Building Chez Scheme](BUILDING). + +For more information see the [Chez Scheme Project Page](https://cisco.github.io/ChezScheme/). diff --git a/README.original.md b/README.original.md deleted file mode 100644 index 65aaf2a..0000000 --- a/README.original.md +++ /dev/null @@ -1,60 +0,0 @@ -[![test](https://github.com/cisco/ChezScheme/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/cisco/ChezScheme/actions/workflows/test.yml) - -Chez Scheme is both a programming language and an implementation -of that language, with supporting tools and documentation. - -As a superset of the language described in the -[Revised6 Report on the Algorithmic Language Scheme](http://www.r6rs.org) -(R6RS), Chez Scheme supports all standard features of Scheme, -including first-class procedures, proper treatment of tail calls, -continuations, user-defined records, libraries, exceptions, and -hygienic macro expansion. - -Chez Scheme also includes extensive support for interfacing with C -and other languages, support for multiple threads possibly running -on multiple cores, non-blocking I/O, and many other features. - -The Chez Scheme implementation consists of a compiler, run-time -system, and programming environment. -Although an interpreter is available, all code is compiled by -default. -Source code is compiled on-the-fly when loaded from a source file -or entered via the shell. -A source file can also be precompiled into a stored binary form and -automatically recompiled when its dependencies change. -Whether compiling on the fly or precompiling, the compiler produces -optimized machine code, with some optimization across separately -compiled library boundaries. -The compiler can also be directed to perform whole-program compilation, -which does full cross-library optimization and also reduces a -program and the libraries upon which it depends to a single binary. - -The run-time system interfaces with the operating system and supports, -among other things, binary and textual (Unicode) I/O, automatic -storage management (dynamic memory allocation and generational -garbage collection), library management, and exception handling. -By default, the compiler is included in the run-time system, allowing -programs to be generated and compiled at run time, and storage for -dynamically compiled code, just like any other dynamically allocated -storage, is automatically reclaimed by the garbage collector. - -The programming environment includes a source-level debugger, a -mechanism for producing HTML displays of profile counts and program -"hot spots" when profiling is enabled during compilation, tools for -inspecting memory usage, and an interactive shell interface (the -expression editor, or "expeditor" for short) that supports multi-line -expression editing. - -The R6RS core of the Chez Scheme language is described in -[The Scheme Programming Language](http://www.scheme.com/tspl4/), -which also includes an introduction to Scheme and a set of example programs. -Chez Scheme's additional language, run-time system, and -programming environment features are described in the -[Chez Scheme User's Guide](http://cisco.github.io/ChezScheme/csug9.5/csug.html). -The latter includes a shared index and a shared summary of forms, -with links where appropriate to the former, so it is often the best -starting point. - -Get started with Chez Scheme by [Building Chez Scheme](BUILDING). - -For more information see the [Chez Scheme Project Page](https://cisco.github.io/ChezScheme/). diff --git a/csug/canned/csug.css b/csug/canned/csug.css deleted file mode 100644 index 083ce26..0000000 --- a/csug/canned/csug.css +++ /dev/null @@ -1,35 +0,0 @@ -BODY {background-color: #FFFFFF} - -a:link, a:active, a:visited { color:#005568; text-decoration:underline } -a:hover { color:white; text-decoration:underline; background:#005568 } - -a.plain:link, a.plain:active, a.plain:visited { color:#005568; text-decoration:none } -a.plain:hover { color:white; text-decoration:none; background:#005568 } - -a.toc:link, a.toc:active, a.toc:visited {font-family: sans-serif; color:#005568; text-decoration:none} -a.toc:hover {font-family: sans-serif; color:white; text-decoration:none; background:#005568} - -a.image:link, a.image:active, a.image:visited, a.image:hover { - color: #005568; - background: #FFFFFF; -} - -ul.tocchapter { list-style: none; } -ul.tocsection { list-style: circle; color: #C41230 } - -hr.copyright { width: 50% } - -input.default { background: #ffffff; color: #000000; vertical-align: middle} - -h1, h2, h3, h4 {font-family: sans-serif; color: #005568} -h1 {font-size: 2em} -h2 {margin-top: 30px; font-size: 1.5em} -h3 {margin-top: 30px; font-size: 1.17em} -h1, h2, h3, h4 {font-weight: bold} - -.title { font-family: sans-serif; font-weight: bold; font-size: 2.5em; color: #005568; white-space: nowrap} - -.formdef { color: #005568 } - -table.indent {margin-left: 20px} - diff --git a/csug/canned/csug.css b/csug/canned/csug.css new file mode 120000 index 0000000..69b665c --- /dev/null +++ b/csug/canned/csug.css @@ -0,0 +1 @@ +../csug.css \ No newline at end of file diff --git a/ta6ob/LOG b/ta6ob/LOG deleted file mode 100644 index 1b3f7b6..0000000 --- a/ta6ob/LOG +++ /dev/null @@ -1,2341 +0,0 @@ -9.4 changes: -- updated version to 9.4 - bintar README NOTICE makefiles/Mf-install.in scheme.1.in - c/Makefile.i3nt c/Makefile.a6nt c/Makefile.ti3nt c/Makefile.ta6nt - mats/bldnt.bat workarea c/scheme.rc s/7.ss s/cmacros.ss - release_notes/release_notes.stex csug/csug.stex -- added missing include - killme.c -- added new mat verifying that primitives raise exceptions for invalid - arguments based on primdata.ss signatures. fixed some of those - signatures, which weren't otherwise used except for arity checking. - fixed some issues turned up by the test with who reports errors - and how. - primdata.ss, 5_1.ss, 7.ss, compile.ss, cpnanopass.ss, fasl.ss, - interpret.ss, io.ss, record.ss, syntax.ss, - primvars.ms, 5_1.ms, 7.ms, 8.ms, record.ms, mats/Mf-base, - root-experr*, patch* -- string comparisons (string=?, string-cidate test in mat time&date-printing to work regardless of - what locale (and time zone) the host machine has set. - date.ms -- fixed date->time-utc to honor the zone-offset field when converting a date - object to a time-utc object. - stats.c, - date.ms -- fixed incorrect handling of library-extension when searching wpo files - compile.ss, - 7.ms -- modified floatify_normalize to properly round denormalized results. - obviated scale_float in the process. - number.c, - ieee.ms -- fixed 0eNNNN for large NNNN to produce 0.0 rather than infinity - strnum.ss, - 5_3.ms -- the reader now raises an exception with condition type implementation - restriction (among the other usual lexical condition types), and - string->number now raises #f, for #e@, where and are - nonzero integers, since Chez Scheme can't represent polar numbers other - than 0@ and @0 exactly. @ still produces an inexact result, - i.e., we're still extending the set of inexact numeric constants beyond - what R6RS dictates. doing this required a rework of $str->num, which - turned into a fairly extensive rewrite that fixed up a few other minor - issues (like r6rs:string->number improperly allowing 1/2e10) and - eliminated the need for consumers to call $str->num twice in cases - where it can actually produce a number. added some related new tests, - including several found missing by profiling. added a couple of - checks to number->string the absence of which was causing argument - errors to be reported by other routines. - strnum.ss, exceptions.ss, read.ss - 5_3.ms, 6.ms, root-experr*, patch* -- added pdhtml flag, which if set to t causes profile-dump-html to be - called at the end of a mat run. - mats/Mf-base -- compile-whole-program and compile-whole-library now copy the hash-bang - line from the wpo file (if it has one) to the object file. - compile.ss, - 7.ms -- stex is now a submodule. csug/Makefile and release_notes/Makefile - set and use the required Scheme and STEXLIB variables accordingly. - they default the machine type to a6le, but this can be overridden - and is by the generated top-level Makefile. the generated top-level - Makefile now has a new docs target that runs make in both csug and - release_notes, and an updated distclean target that cleans the same. - the annoying csug Makefile .fig.pdf rule redefinition is now gone. - copyright.stex and csug.stex now list May 2016 as the revision month - and date; this will have to be updated for future releases. - configure, makefiles/Makefile.in, - csug/Makefile, copyright.stex, csug.stex, - release_notes/Makefile -- added custom install options. workarea creates an empty config.h, - and configure creates a config.h that sets the default scheme heap - path and scheme-script name based on the actual configuration. - configure, newrelease, workarea, checkin, - c/Mf-base, scheme.c, main.c, - Mf-install.in -- renamed the installed example directory from lib to examples. - Mf-install.in, - scheme.1.in -- added force option to gzip during man page install to prevent gzip from - asking for permission to overwrite existing man page files. - Mf-install.in -- removed ~/lib/csv%v/%m from the default scheme heap path on unix-like - systems. documented inclusion of %x\..\..\boot\%m in the Windows - default scheme heap path. - main.c, - use.stex -- added new configuration options: --installbin, --installlib, - --installschemename, --installpetitename, and --installscriptname. - configure -- updated the example library link to the nanopass framework. - CONTRIBUTING.md -- now cleaning up petite.1 and scheme.1 left behind by make install - Makefile-workarea.in, checkin -- now removing workarea after cleaning csug and release_notes so - Mf-stex (included from csug/Makefile and release_notes/Makefile) - doesn't complain trying to determine the machine type. - Makefile.in -- added installsh support for --ifdiff so the csug make file can use it - for the install target. - installsh, - csug/Makefile -- added instructions for building (cross-compiling) a boot file for - a supported machine type for which a boot file is not built by default. - BUILDING -- corrected CHEZSCHEMELIBS and CHEZSCHEMEEXTS index entries to be - CHEZSCHEMELIBDIRS and CHEZSCHEMELIBEXTS. - use.stex -- updated to curl stex version 1.2.1 - configure -- updated the fix to S_mktime to work on windows. the struct tm - structure on windows does not have the tm_gmtoff field used in the - mac and linux version of the code. - stats.c -- updated the Windows makefiles for building and testing to remove links for - files that no longer exist, which was getting in the way of creating links - for files that do exist. Also updated the build batch file for Windows to - compile the nanopass framework separately before building the rest of the - scheme compiler and libraries. - s/Mf-{a6,i3,ta6,ti3}nt, s/bldnt.bat, - mats/Mf-{a6,i3,ta6,ti3}nt -- updated the read me to include a link to the Chez Scheme project page. - README.md -- fixed embarrassing typo in read me. - README.md -- profiler's html output refresh: mark the files as HTML5 rather - than HTML4; use target attributes rather than onclick events to - open links in specific windows; add a missing table row element; - replace the deprecated name attribute with an id attribute (and - replace the anchors with spans); and replace the deprecated valign - attribute with a style attribute. - pdhtml.ss - -9.4.1 changes: -- updated version to 9.4.1 - bintar BUILDING NOTICE makefiles/Mf-install.in scheme.1.in - c/Makefile.i3nt c/Makefile.a6nt c/Makefile.ti3nt c/Makefile.ta6nt - mats/bldnt.bat workarea c/scheme.rc s/7.ss s/cmacros.ss - release_notes/release_notes.stex csug/csug.stex -- updated newrelease to produce the correct log-entry format and - fixed the existing 9.4.1 log entry - newrelease, LOG -- replaced a couple of tabs - number.c -- updated the descriptions of statistics and related functions to - reflect the Version 9.3.1 change from sstats structures to sstats - records, with sstats times represented as time objects and sstats - bytes and counts represented as exact integers; also updated the - sstats-difference description to reflect that it no longer coerces - negative differences to zero. added a corresponding release note. - system.stex, - release_notes.stex -- added a cast to eliminate a warning - c/number.c -- fixed bug in Windows version of directory-separator-predicate when - path-* procedures are passed a path that is not a string. - s/6.ss -- fixed bug in cp0 on Windows with $foreign-wchar?. - s/cp0.ss -- Cygwin is now used on Windows, updated mats, eliminated unused killme - BUILDING c/*nt c/Mf-base c/scheme.exe.manifest configure - examples/Makefile mats/6.ms mats/Mf-* mats/foreign.ms mats/ftype.ms - mats/patch-* mats/windows.ms s/Mf-*nt s/Mf-base workarea - release_notes.stex -- fixed spelling of non-existent - s/syntax.ss -- now forcing zlib configuration before compiling files that depend on - the zlib header files, since zlib's configure script can modify the - header files. removed ZlibInclude variable, which no longer serves - a purpose. - c/Mf-*, c/Makefile.*nt -- removed unnecessary datestamp.c target - c/Mf.*nt -- fixed unnecessary blocking in expeditor on Windows. - c/expeditor.c -- eliminated a couple of thread-safety issues and limitations on the - sizes of pathnames produced by expansion of tilde (home-directory) - prefixes by replacing S_pathname, S_pathname_impl, and S_homedir - with S_malloc_pathname, which always mallocs space for the result. - one thread-safety issue involved the use of static strings for expanded - pathnames and affected various file-system operations. the other - affected the file open routines and involved use of the incoming - pathname while deactivated. the incoming pathname is sometimes if not - always a pointer into a Scheme bytevector, which can be overwritten if a - collection occurs while the thread is deactivated. the size limitation - corresponded to the use of the static strings, which were limited to - PATH_MAX bytes. (PATH_MAX typically isn't actually the maximum path - length in contemporary operating systems.) eliminated similar issues - for wide pathnames under Windows by adding S_malloc_wide_pathname. - consumers of the old routines have been modified to use the new - routines and to free the result strings. the various file operations - now consistently treat a pathname with an unresolvable home directory - as a pathname that happens to start with a tilde. eliminated unused - foreign-symbol binding of "(cs)pathname" to S_pathname. - io.c, externs.h, new_io.c, prim5.c, scheme.c, prim.c -- various places where a call to close or gzclose was retried when - the close operation was interrupted no longer do so, since this can - cause problems when another thread has reallocated the same file - descriptor. - new_io.c -- now using vcvarsall type x86_amd64 rather than amd64 when the - former appears to supported and the latter does not, as is the - case with VS Express 2015. - c/Mf-a6nt, c/Mf-ta6nt -- commented out one of the thread mats that consistently causes - indefinite delays under Windows and OpenBSD due to starvation. - thread.ms -- increased wait time for a couple of subprocess responses - 6.ms -- added call to collector to close files opened during iconv mats - specifically for when mats are run under Windows with no iconv dll. - io.ms -- fixed typo: VC/bin/vcvars64.bat => VC/bin/amd64/vcvars64.bat - c/Mf-a6nt, c/Mf-ta6nt -- scheme_mutex_t now uses volatile keyword for owner and count fields - because these fields can be accessed from multiple threads - concurrently. Updated $yield and $thread-check in mats/thread.ms to - be more tolerant of timing variability. - c/types.h, mats/thread.ms, release_notes.stex -- fixed three instances of unchecked mallocs reported by laqrix in - github issue #77. - io.c, schlib.c, thread.c -- continue the profiler's html output refresh: refine the styling - (and palette) and update CSUG to match. update the CSUG screenshots - to reflect the refined look. - s/pdhtml.ss - csug/system.stex - csug/canned/profilehtml-orig.png - csug/canned/profilehtml.png - csug/canned/fatfibhtml-orig.png - csug/canned/fatfibhtml.png -- add unicode support to the expression editor. entry and display now work - except that combining characters are not treated correctly for - line-wrapping. this addresses github issue #32 and part of issue #81. - c/expeditor.c, s/expeditor.ss -- moved s_ee_write_char function within the WIN32 check to allow the unicode - change to compile on windows. unicode is not yet supported in the windows - version of the repl. - c/expeditor.c -- reworked the S_create_thread_object to print an error and exit when - allocating the thread context fails from Sactivate_thread. before - this change, the error was raised on the main thread, which resulted - in strange behavior at best. also added who argument to - S_create_thread_object to allow it to report either Sactivate_thread - or fork-thread led to the error. - externs.h, schsig.c, scheme.c, thread.c -- fixed a bug in cpvalid resulting in it leaving behind a cpvalid-defer - form for later passes to choke on. also fixed cp0 to print the correct - name for cpvalid when it does this. - cpvalid.ss, cp0.ss, - misc.ms -- updated the prototype for s_ee_write_char to match the definition - expeditor.c -- fixed a side-effect preservation bug with non-trivial test-context - not-like patterns. - cp0.ss, - cp0.ms, 4.ms -- instead of default-exception handler, new-cafe establishes a handler - that calls the current value of base-exception-handler so the handler - can be overridden, as we do in our own make files. - cafe.ss, - 7.ms -- fixed a bug in case and exclusive-cond syntax-error calls causing an - exception in syntax-error instead of the intended error message. - syntax.ss -- added tests for the case and exclusive-cond syntax-error calls - 4.ms, root-experr-compile-0-f-f-f -- added print-extended-identifiers parameter. when #t, symbols like - 1+ and +++ print without escapes. - priminfo.ss, print.ss, - 6.ms -- added descriptions of print-extended-identifiers to the user's guide - and release notes. updated the release notes to account for a couple - of other log entries. - release_notes.stex, - intro.stex, io.stex -- updated the sockets example to work with the current version of Chez. - Change the foreign procedure definitions to use the more portable int - rather than integer-32. Switch to a custom port - [make-custom-binary-input/output-port] rather than a generic port - [make-input/output-port], which resulted in deleting quite a bit of - code. Fix various compiler warnings in the C code, and along the way, - fix a signedness bug in c_write that could have resulted in not writing - the full buffer (but reporting that it did) in the case of errors from - write. - examples/csocket.c, examples/socket.ss -- use high-precision clock time on Windows 8 and up - c/stats.c -- fixed profiling code that keyed profiling locations off of only the - bfp to instead key off of both the bfp and efp. - pdhtml.ss -- added Windows installer using the WiX Toolset - BUILDING, install/* (new) -- fix typo in ordinal format for 12 - format.ss, - format.ms -- renamed install directory to wininstall to avoid conflict with - top-level Makefile - BUILDING, install/* (removed), wininstall/* (new) -- updated zlib to version 1.2.11 - configure -- added procedure-arity-mask to report the allowed argument counts of - a compiled function. On a procedure from interpret or from one of - the trace procedures or syntactic forms, procedure-arity-mask - may report counts that are not actually allowed by the source - procedure. - cmacros.ss, compile.ss, cpnanopass.ss, mkheader.ss, primdata.ss, - prims.ss, strip.ss, - fasl.c, gc.c, globals.h, prim.c, prim5.c, scheme.c, schsig.c, - misc.ms, root-experr*, - objects.stex -- for non-win32 systems, now setting al register to a count of the - floating-point register arguments as required for varargs functions - by the System V ABI. - x86_64.ss, - foreign.ms -- added a missing quote mark in new printf mat Windows case - foreign.ms -- added travis-ci automation script and a 'partialx' testing target to - allow us to perform more than a single run of testing without running - afoul of travis-ci's 50-minute build timeout. 'partialx' tests six - of the twelve configurations tested by 'allx'. - .travis.yml (new), - mats/Mf-base -- paired the 'partialx' down to just four test configurations, with one - interpreter run, to try to get the threaded builds into line with - travis-ci's timeout. - mats/Mf-base -- eliminated some direct assumptions that a vector's type/length field - is a fixnum and added meta-asserts to verify that it is in a couple of - others, to facilitate future changes to vector typing. vectors are - now treated essentially like fxvectors, strings, and bytevectors. - cmacros.ss, cpnanopass.ss, prims.ss, mkheader.ss, - alloc.c, gc.c, scheme.c -- fixed a few comments to refer to scheme.c rather than main.c - externs.h, globals.h, thread.c -- for 64-bit Windows systems, now copying foreign-procedure - double-precision floating-point register arguments to integer - registers as required for varargs functions. Windows does not - support single-precision floating-point arguments as varargs. - foreign.ms, np-languages.ss, x86_64.ss -- added an optional timeout argument to condition-wait - externs.h, stats.c, thread.c, thread.h, csug/threads.stex, - primvars.ms, thread.ms, release_notes.stex, - date.ss, primdata.ss, prims.ss -- added immutable strings, vectors, fxvector, bytevectors, and boxes - 5_4.ss, 5_6.ss, bytevector.ss, cmacros.ss, cpnanopass.ss, - fasl.ss, library.ss, mkheader.ss, primdata.ss, prims.ss, - externs.h, types.h, alloc.c, fasl.c, gc.c, scheme.c, - 5_5.ms, 5_6.ms, bytevector.ms, misc.ms, root-experr* - objects.stex -- various tweaks to the immutable object support; also taught cp0 - to simplify ($fxu< (most-positive-fixnum) e) => (fx< e 0) so we - don't have any incentive in special casing length checks where - the maximum length happens to be (most-positive-fixnum). - 5_4.ss, 5_6.ss, bytevector.ss, cmacros.ss, cp0.ss, cpnanopass.ss, - mkheader.ss, primdata.ss, prims.ss, - fasl.c, gc.c, types.h - root-experr*, patch* -- generated bytevector=? procedure now gets out quickly on eq - arguments. cp0 optimizes away a number of additional equality - operations at optimize-level 3 (including bytevector=?) when - applied to the same variable references, as it already did for - eq?, eqv?, and equal?, at all optimize levels. - cpnanopass.ss, cp0.ss, primdata.ss, - cp0.ms -- updated bullyx patches - patch* -- updated release notes and tweaked user's guide. - release-notes.stex, objects.stex -- fixed typo: fxvector-immutable-flag used in place of - bytevector-immutable-flag in computation of type-immutable-bytevector - cmacros.ss -- reallocated typed-object types, using previously unused tag #b010 - for strings and giving bytevectors both #b001 and #b101 (the - latter for immutable bytevectors) so that the maximum bytevector - length on 32-bit machines is once again the most-positive fixnum. - treating bytevectors rather than strings or fxvectors (or even - vectors) special in this regard is appropriate since the maximum - number of bytes in a bytevector is maximum-length x 1 rather than - maximum-length x 4 for strings, fxvectors, and vectors on 32-bit - machines. with this change on 32-bit machines, a vector can - occupy up to 1/2 of virtual memory, strings and fxvectors 1/4, - and bytevectors 1/8. - cmacros.ss -- added record-type-equal-procedure, record-type-hash-procedure, - record-equal-procedure, and record-hash-procedure to enable - per-type customization of the behavior of equal? and equal-hash - for a record value - 5_1.ss, newhash.ss, primdata.ss, - record.ms, root-experr*, - objects.stex -- adding dropped changes - record.ss, - root-experr* -- added entry for record-type-equal-procedure and friends - release_notes.stex -- changed copyright year to 2017 - 7.ss, scheme.1.in, comments of many files -- expanded the CSUG description of the handling of command-line - arguments not recognized as standard options and added a description - of the same to the COMMAND-LINE OPTIONS section of the man page. - did a bit of minor cleanup elsewhere in the man page. - use.stex, scheme.1.in -- destroy_thread now processes guardian entries - thread.c, 4.ms, release_notes.stex -- mutexes and conditions are now freed when no longer used via - $close-resurrected-mutexes&conditions, $keep-live primitive added - externs.h, prim5.c, thread.c, 4.ms, thread.ms, release_notes.stex, - 7.ss, cpnanopass.ss, np-languages.ss, primdata.ss, prims.ss -- fix reduction for map and for-each with optimization level 3 - to drop the expression, check that procedure has the correct - arity and is discardable or unsafe. - Also add a simplification for for-each with empty lists - with optimization level 2. - cp0.ss, 4.ms, primdata.ss -- fix invalid memory reference when enum-set-indexer procedure is not - passed a symbol - enum.ss, enum.ms, root-experr*, release_notes.stex -- fix overflow detection for fxsll, fxarithmetic-shift-left, and - fxarithmetic-shift - library.ss, fx.ms, release_notes.stex -- added ephemeron pairs and changed weak hashtables to use - ephemeron pairs for key--value mapping to avoid the key-in-value - problem - prims.ss, primdata.ss, newhash.ss, fasl.ss, mkheader.ss - cmacro.ss, prim5.c, fasl.c, gc.c, gcwrapper.c, types.h, - 4.ms, hash.ms, objects.stex, smgmt.stex, csug.bib -- check_dirty_ephemeron now puts ephemerons whose keys haven't yet - been seen on the pending list rather than the trigger lists. - gc.c -- removed scan of space_ephemeron from check_heap because check_heap - as written can't handle the two link fields properly. - gcwrapper.c -- in the ephemerons mat that checks interaction between mutation and - collection, added generation arguments to the first two collect - calls so they always collect into the intended generation. - 4.ms -- updated allx and bullyx patches - patch* -- fix strip-fasl-file for immutable strings and vectors, - fix an $oops call, and fix a vector-index increment in hashing - strip.ss, 7.ss, newhash.ss, misc.ms -- fix signature of fxbit-set? - primdata.ss -- more optimizations for map and for-each with explicit list - extend the reductions for map and for-each when the arguments are - explicit lists like (list 1 2 3 ...) or '(1 2 3 ...). - cp0.ss, - 4.ms -- reverted to the preceding version of cp0 due to failure to preserve - the expected evaluation order in one of the mats; removed the - corresponding equivalent-expansion tests. - cp0.ss, - 4.ms -- restored the map and for-each optimizations with a fix for the - evaluation-order bug. - cp0.ss, - 4.ms -- added date-dst? to access the previously-hidden DST information in - date records, and added date-zone-name to provide a time zone name. - date.ss, primdata.ss, - stats.c, - date.ms, root-experr*, patch-compile*, - system.stex -- fixed a bug in flonum-extractor, which on 64-bit machines was using an - 8-byte read instead of a 4-byte read to pick up the 4 highest-order - bytes of a little-endian flonum, potentially reading past the end of - mapped memory for flonums produced by taking the imaginary part of an - inexact complexnum (which, unlike other flonums, are not aligned on - 16-byte boundaries). The 8-byte load would also have failed to produce - correct results on 64-bit big-endian machines (of which we presently - have none) because the offsets passed to flonum-extractor assume the - bits are in the lowest-order 4 bytes of the extracted field. - cp0.ss, - misc.ms, - release_notes.stex -- support Windows build on Bash/WSL - BUILDING, configure, workarea, c/vs.bat (new), mats/vs.bat (new), - c/Mf-*nt, mats/Mf-*, s/Mf-base -- fix c/version.h for FreeBSD (machine types i3fb, ti3fb, a6fb, ta6fb) -- fix reference to libc.so to be libc.so.7 for FreeBSD (machine types - i3fb, ti3fb, a6fb, ta6fb) - foreign.ms -- added CC option to configure for selecting the compiler - configure, - c/Mf-* -- Suppress warnings from implicit fall-through in case labels. - Mf-{a6,arm32,i3,ppc,ta6,ti3,tpp32}le -- added bytevector-compress and bytevector-uncompress - bytevector.ss, primdata.ss, new-io.c, prim5.c, externs.h, - objects.stex, release_notes.stex, - bytevector.ms, root-experr* -- fixed typo in S_abnormal_exit - schsig.c -- don't remove the pariah form in the cp0 pass - cp0.ss, - misc.ms -- revert use of ephemerons in weak hashtables, add ephemeron - hashtables - newhash.ss, hashtable-types.ss, library.ss, primdata.ss, - fasl.ss, fasl.c, gc.c, globals.h, - hash.ms, objects.stex, release_notes.stex -- fixed pariah mat - misc.ms -- minor wordsmithing and fix for an overfull hbox - objects.stex, system.stex -- fix (define-values () ....) to expand to a definition - syntax.ss, 3.ms -- added optional line and column components to a source object, a - locate-source-object-source function that uses the new components, - a current-locate-source-object-source parameter to control looking up - line and column information, a current-make-source-object parameter to - control location recording, an optional use-cache argument to - locate-source, and a 'source-object message for code and continuation - inspectors - read.ss, syntax.ss, 7.ss, compile.ss, cpnanopass.ss, exceptions.ss, - inspect.ss, primdata.ss, prims.ss, print.ss, cmacros.ss, types.ss, - mat.ss, 8.ms, root-experr*, - syntax.stex, debug.stex, system.stex, release_notes.stex -- fixed broken mats on Windows caused by Bash/WSL changes - 7.ms, ftype.ms -- added "ez-grammar" example program - examples/ez-grammar.ss, examples/ez-grammar-test.ss, - examples/Makefile, examples.ms -- updated ez-grammar-test to write temp files to current directory and delete them when finished - examples/ez-grammar-test.ss -- added support for Microsoft Visual Studio 2017 on Windows - BUILDING, c/Mf-a6nt, c/Mf-ta6nt, c/vs.bat, - mats/Mf-a6nt, mats/Mf-ta6nt, mats/ftype.ms -- added support for building Windows installs with Bash/WSL - wininstall/Makefile, candle.bat, light.bat -- added support for building with Visual Studio 2017's BuildTools - c/vs.bat -- check for git before using to get submodules - configure -- fixed windows installer failure when vcredist is not preinstalled by - using the vcredist merge module, split the 32 and 64 bit MSIs and - added a wix bundle to combine the MSIs into a single exe installer, - added a batch script for locating Visual Studio's vcredist merge - modules, updated installer paths and names. - wininstall/* -- fixed np-normalize-context pass to process trivs list in mvset forms - in tail and predicate context and added regression tests. Thanks to - @marcomaggi for reporting the bug and @yjqww6 for providing a - simplified test and finding the initial solution. - cpnanopass.ss, - 3.ms -- removed a useless check in foreign-alloc - record.ss -- fix cp0 reduction of fx[+-*]/carry and their signatures - cp0.ss - primdata.ss - fx.ms -- renamed s_gettime => S_gettime to remain consistent with the - convention that the only undocumented externs are prefixed with - S_. - externs.h, stats.c, thread.c -- added version number to scheme.1.in trailer; updated date. - scheme.1.in, newrelease -- removed version update of no-longer-existing bldnt.bat. "fixed" - sed patterns to replace \? with * for the benefit of the deficient - mac sed. - newrelease - -9.5 changes: -- updated version to 9.5 - bintar BUILDING NOTICE makefiles/Mf-install.in scheme.1.in - c/Makefile.i3nt c/Makefile.a6nt c/Makefile.ti3nt c/Makefile.ta6nt - workarea c/scheme.rc s/7.ss s/cmacros.ss - release_notes/release_notes.stex csug/csug.stex -- updated release notes and fixed user's guide overfull hbox. - release-notes.stex, syntax.stex -- updated install target to do something more sensible - release_notes/Makefile - -9.5.1 changes: -- updated version to 9.5.1 - bintar BUILDING NOTICE makefiles/Mf-install.in scheme.1.in - c/Makefile.i3nt c/Makefile.a6nt c/Makefile.ti3nt c/Makefile.ta6nt - workarea c/scheme.rc s/7.ss s/cmacros.ss - release_notes/release_notes.stex csug/csug.stex csug/use.stex - examples/ez-grammar-test.ss examples/socket.ss - wininstall/Makefile wininstall/*nt.wxs -- Added setting of CHEZSCHEMELIBDIRS to s and mats make files so that - an existing setting will not interfere with the build process, and - added a note to BUILDING that CHEZSCHEMELIBDIRS should be unset in - Version 9.5 and before. - s/Mf-base, mats/Mf-base, BUILDING -- the $case macro used by r6rs:case and case now unconditionally trims - redundant keys and expands into exclusive-cond rather than cond. - it catches references to => before expanding into exclusive-cond - to avoid supporting => as an undocumented and useless extension - of the case syntax. the r6rs:case and case macros now require - multiple clauses rather than leaving the enforcement to exclusive-cond, - and the exclusive-cond macro now requires multiple clauses rather - than leaving the enforcement to cond. - syntax.ss, - 4.ms, root-experr*, patch* -- ifdef'd out include of xlocale.h for glibc, since the glibc - locale.h includes xlocale.h or, in glibc 2.26, its replacement. - expeditor.c -- Updated CSUG to replace \INSERTREVISIONMONTHSPACEYEAR with the current - month and year at the time of generation. - csug.stex, copyright.stex -- Updated configuration to set machine types in the CSUG and release notes - make files, and updated distclean target to remove these files. - configure, makefiles/Makefile-csug.in (renamed from csug/Makefile), - makefiles/Makefile-release_notes.in - (renamed from release_notes/Makefile), - makefiles/Makefile -- added pass-time tracking for pre-cpnanopass passes to compile. - compile.ss -- added inline handler for fxdiv-and-mod - cp0.ss, primdata.ss -- changed order in which return-point operations are done (adjust - sfp first, then store return values, then restore local saves) to - avoid storing return values to homes beyond the end of the stack - in cases where adjusting sfp might result in a call to dooverflood. - cpnanopass.ss, np-languages.ss -- removed unused {make-,}asm-return-registers bindings - cpnanopass.ss -- corrected the max-fv value field of the lambda produced by the - hand-coded bytevector=? handler. - cpnanopass.ss -- reduced live-pointer and inspector free-variable mask computation - overhead - cpnanopass.ss -- moved regvec cset copies to driver so they aren't copied each - time a uvar is assigned to a register. removed checks for - missing register csets, since registers always have csets. - cpnanopass.ss -- added closure-rep else clause in record-inspector-information!. - cpnanopass.ss -- augmented tree representation with a constant representation - for full trees to reduce the overhead of manipulating trees or - subtrees with all bits set. - cpnanopass.ss -- tree-for-each now takes start and end offsets; this cuts the - cost of traversing and applying the action when the range of - applicable offsets is other than 0..tree-size. - cpnanopass.ss -- introduced the notion of poison variables to reduce the cost of - register/frame allocation for procedures with large sets of local - variables. When the number of local variables exceeds a given - limit (currently hardwired to 1000), each variable with a large - live range is considered poison. A reasonable set of variables - with large live ranges (the set of poison variables) is computed - by successive approximation to avoid excessive overhead. Poison - variables directly conflict with all spillables, and all non-poison - spillables indirectly conflict with all poison spillables through - a shared poison-cset. Thus poison variables cannot live in the - same location as any other variable, i.e., they poison the location. - Conflicts between frame locations and poison variables are handled - normally, which allows poison variables to be assigned to - move-related frame homes. Poison variables are spilled prior to - register allocation, so conflicts between registers and poison - variables are not represented. move relations between poison - variables and frame variables are recorded as usual, but other - move relations involving poison variables are not recorded. - cpnanopass.ss, np-languages.ss -- changed the way a uvar's degree is decremented by remove-victim!. - instead of checking for a conflict between each pair of victim - and keeper and decrementing when the conflict is found, remove-victim! - now decrements the degree of each var in each victim's conflict - set. while this might decrement other victims' degrees unnecessarily, - it can be much less expensive when large numbers of variables are - involved, since the number of conflicts between two non-poison - variables should be small due to the selection process for - (non-)poison variables and the fact that the unspillables introduced - by instruction selection should also have few conflicts. That - is, it reduces the worst-case complexity of decrementing degrees - from O(n^2) to O(n). - cpnanopass.ss -- took advice in compute-degree! comment to increment the uvars in - each registers csets rather than looping over the registers for - each uvar asking whether the register conflicts with the uvar. - cpnanopass.ss -- assign-new-frame! now zeros out save-weight for local saves, since - once they are explicitly saved and restored, they are no longer - call-live and thus have no save cost. - cpnanopass.ss -- desensitized the let-values source-caching timing test slightly - 8.ms -- updated allx, bullyx patches - patch* -- attempt to stabilize timing tests let-values source-caching - test and ephemeron gc test while resensitizing the former - 8.ms, 4.ms -- various formatting and comment corrections - workarea, - s/Mf-base, bytevector.ss, cpnanopass.ss, date.ss, - 5_6.ms, examples.ms -- updated newrelease to handle mats/Mf-*nt - newrelease mats/Mf-a6nt mats/Mf-i3nt mats/Mf-ta6nt mats/Mf-ti3nt -- fixed gather-filedata's sort of profile entries. for any two - entries x and y in the list produced by the sort call, if x's - bfp = y's bfp, x should come before y if x's efp < y's efp. - The idea is that enclosing entries should always come later - in the list. this affects only languages where two expressions - can start at the same character position. - pdhtml.ss -- expanded capability of ez-grammar with support for simple - parsing of binary operators w/precedence and associativity - and automatically generated markdown grammar descriptions. - ez-grammar-test.ss now also doubles as a test of pdhtml for - algebraic languages. - mats/examples.ms, - examples/ez-grammar.ss, examples/ez-grammar-test.ss, - examples/Makefile -- maybe-compile-{file,program,library} and automatic import - compilation now treat a malformed object file as if it were - not present and needs to be regenerated. A malformed object - file (particularly a truncated one) might occur if the compiling - processes is killed or aborts before it has a chance to delete - a partial object file. - syntax.ss, - 7.ms -- fix signature of bytevector-[u/s]16-native-set! - primdata.ss -- fix enumerate signature - primdata.ss -- added support for Visual Studio 2017.15.5 - wininstall/locate-vcredist.bat -- fixed substring-fill! and vector-fill! to return void, reflecting the - documented return value of unspecified value. Also changes substring-fill! - to use define-who instead of repeating 'substring-fill! in all the error - messages. - 5_4.ss, 5_6.ss -- fix mat of substring-fill! - after the recent change, the result of substring-fill! is void - 5_5.ms -- fix a few signatures - primdata.ss -- fix comment about Sscheme_program - main.c -- fix even? and odd? to error on exceptional flonums - 5_3.ss, 5_3.ms, fl.ms, root-experr*, patch* -- fix bug in date->time-utc caused by incorrect use of difftime in Windows - stats.c, date.ms, release_notes.stex -- Check that first argument of map is a procedure in cp02 expansion - to raise the same error that the non expanded version - cp0.ss -- avoid building the result list in a map that is called for effect - cp0.ss -- added tests to ensure the optimize-level version 2 of map and for-each raise - a non-procedure exception when the first argument is not a procedure, even - when the rest of the program is compiled at optimize level 3. - 4.ms, root-experr-compile-0-f-f-f, patch-compile-0-t-f-f, - patch-compile-0-f-t-f, patch-interpret-0-f-t-f, patch-interpret-0-f-f-f, - patch-interpret-3-f-t-f, patch-interpret-3-f-f-f -- fix bounds checking with an immediate index on immutable vectors, - fxvectors, strings, and bytevectors - cpnanopass.ss, 5_5.ms, 5_6.ms, bytevector.ms -- fix a few signatures - primdata.ss -- more staid and consistent Mf-cross main target - Mf-cross -- cpletrec now replaces the incoming prelexes with new ones so - that it doesn't have to alter the flags on the incoming ones, since - the same expander output is passed through the compiler twice while - compiling a file with macro definitions or libraries. we were - getting away without this just by luck. - cpletrec.ss -- pure? and ivory? now return #t for a primref only if the prim is - declared to be a proc, since some non-proc prims are mutable, e.g., - $active-threads and $collect-request-pending. - cp0.ss -- $error-handling-mode? and $eol-style? are now properly declared to - be procs rather than system state variables. - primdata.ss -- the new pass $check-prelex-flags verifies that prelex referenced, - multiply-referenced, and assigned flags are set when they - should be. (it doesn't, however, complain if a flag is set - when it need not be.) when the new system parameter - $enable-check-prelex-flags is set, $check-prelex-flags is - called after each major pass that produces Lsrc forms to verify - that the flags are set correctly in the output of the pass. - this parameter is unset by default but set when running the - mats. - cprep.ss, back.ss, compile.ss, primdata.ss, - mats/Mf-base -- removed the unnecessary set of prelex referenced flag from the - build-ref routines when we've just established that it is set. - syntax.ss, compile.ss -- equivalent-expansion? now prints differences to the current output - port to aid in debugging. - mat.ss -- the nanopass that patches calls to library globals into calls to - their local counterparts during whole-program optimization now - creates new prelexes and sets the prelex referenced, multiply - referenced, and assigned flags on the new prelexes rather than - destructively setting flags on the incoming prelexes. The - only known problems this fixes are (1) the multiply referenced - flag was not previously being set for cross-library calls when - it should have been, resulting in overly aggressive inlining - of library exports during whole-program optimization, and (2) - the referenced flag could sometimes be set for library exports - that aren't actually used in the final program, which could - prevent some unreachable code from being eliminated. - compile.ss -- added support for specifying default record-equal and - record-hash procedures. - primdata.ss, cmacros.ss, cpnanopass.ss, prims.ss, newhash.ss, - gc.c, - record.ms -- added missing call to relocate for subset-mode tc field, which - wasn't burning us because the only valid non-false value, the - symbol system, is in the static generation after the initial heap - compaction. - gc.c -- added a lambda-commonization pass that runs after the other - source optimizations, particularly inlining, and a new parameter - that controls how hard it works. the value of commonization-level - ranges from 0 through 9, with 0 disabling commonization and 9 - maximizing it. The default value is 0 (disabled). At present, - for non-zero level n, the commonizer attempts to commonize - lambda expressions consisting of 2^(10-n) or more nodes. - commonization of one or more lambda expressions requires that - they have identical structure down to the leaf nodes for quote - expressions, references to unassigned variables, and primitives. - So that various downstream optimizations aren't disabled, there - are some additional restrictions, the most important of which - being that call-position expressions must be identical. The - commonizer works by abstracting the code into a helper that - takes the values of the differing leaf nodes as arguments. - the name of the helper is formed by concatenating the names of - the original procedures, separated by '&', and this is the name - that will show up in a stack trace. The source location will - be that of one of the original procedures. Profiling inhibits - commonization, because commonization requires profile source - locations to be identical. - cpcommonize.ss (new), compile.ss, interpret.ss, cprep.ss, - primdata.ss, s/Mf-base, - mats/Mf-base -- cpletrec now always produces a letrec rather than a let for - single immutable lambda bindings, even when not recursive, for - consistent expand/optimize output whether the commonizer is - run or not. - cpletrec.ss, - record.ms -- trans-make-ftype-pointer no longer generates a call to - $verify-ftype-address if the address expression is a call to - ftype-pointer-address. - ftype.ss -- Remove special case for (#2%map p '()) in cp0 - so the reduced version checks that p is a procedure. - Also make the same change for #2%for-each. - cp0.ss, 4.ms -- Mitigate a race condition in Windows when deleting files and directories. - windows.c -- add (& ftype) argument/result for foreign-procedure, which supports - struct arguments and results for foreign calls - syntax.ss, ftype.ss, cpnanopass.ss, x86.ss, x86_64.ss, - base-lang.ss, np-languages.ss, cprep.ss, primdata.ss, - schlib.c, prim.c, externs.h - mats/foreign4.c, mats/foreign.ms mats/Mf-* - foreign.stex, release_notes.stex -- reworked the S_call_help/S_return CCHAIN handling to fix a bug in which - the signal handler could trip over the NULL jumpbuf in a CCHAIN record. - schlib.c -- install equates.h, kernel.o, and main.o on unix-like systems - Mf-install.in -- standalone export form now handles (import import-spec ...) - 8.ms, syntax.ss, release_notes.stex -- add collect-rendezvous - prim.c, 7.ss, primdata.ss, 7.ms, smgmt.stex, release_notes.stex -- added identifier? checks to detect attempts to use non-identifier - field names in define-record-type field specs. - syntax.ss, - record.ms, root-experr* -- fixed an issue with the library system where an exception that occurs - during visit or revisit left the library in an inconsistent state that - caused it to appear that it was still in the process of running. This - manifested in it raising a cyclic dependency exception, even though - there really is not a cyclic dependency. The various library - management functions involved will now reset the part of the library - when an exception occurs. This also means that if the library visit - or revisit failed for a transient reason (such as a missing or - incorrect library version that can be fixed by updating the - library-directories) it is now possible to recover from these errors. - expand-lang.ss, syntax.ss, interpret.ss, compile.ss, cprep.ss, - 8.ms -- Added -Wno-implicit-fallthrough flag to macOS C makefiles. - c/Mf-a6osx, c/Mf-i3osx, c/Mf-ta6osx, c/Mf-ti3osx -- handle compiled library code in boot files once base boot is loaded - globals.h, scheme.c, 7.ss, 7.ms, primdata.ss -- add newline to (import-notify) message in compile-whole-library and - compile-whole-program - compile.ss -- add a __collect_safe convention for foreign procedures and callables - to automate thread [de]activation - syntax.ss, ftype.ss, x86.ss, x86_64.ss, ppc32.ss, - cmacros.ss, base-lang.ss, np-languages.ss, cprep.ss, cpcommonize.ss, - cp0.ss, cpcheck.ss, cpvalid.ss, interpret.ss, cpletrec.ss, - thread.c, prim.c, externs.h, foreign.stex, release_notes.stex, - mats/Mf-t*, foreign.ms, foreign4.c -- Don't install equates.h - Mf-install.in, wininstall/*nt.wxs -- Windows install now sets HeapSearchPath in the registry - wininstall/product.wxs -- Use Windows path separator character when finding boot files on Windows. - scheme.c -- Propagate enable-check-prelex-flags to separate-eval sub-process in tests. - mats.ss -- Reject attempts to visit libraries that compile-whole-program has rendered - invisible due to libs-visible? flag. - compile.ss, 7.ms, root-experr-compile-0-f-f-f, root-experr-compile-2-f-f-f, - patch-compile-0-f-t-f, patch-compile-0-t-f-f, patch-interpret-0-f-f-f, - patch-interpret-0-f-t-f, patch-interpret-3-f-f-f, patch-interpret-3-f-t-f -- Double FMTBUFSIZE to fix compilation with gcc-8 - c/prim5.c -- Improved Unicode support for command-line arguments, environment - variables, the C interface and error messages, and the Windows - registry, DLL loading, and process creation - scheme.h, alloc.c, externs.h, fasl.c, foreign.c, io.c, main.c, - prim5.c, scheme.c, schlib.c, schsig.c, stats.c, system.h, - version.h, windows.c, foreign.stex, system.stex, mkheader.ss, - prims.ss -- Repair x86_64 `&` foreign-procedure result type handling for types of a - small size that is not a multiple of the word size - x86_64.ss, foreign.ms, foreign4.c -- Avoid an occasional invalid memory violation on Windows in S_call_help - schlib.c -- Updated csug socket code to match that in examples folder - csug/foreign.stex, examples/socket.ss -- add an option --disable-x11 - c/version.h, configure -- allow s_ee_get_clipboard to use the pastebuffer on macOS even when X11 is not - available. - expeditor.c -- Adjust cp0 to not replace a procedure name from a let wrapper - cp0.ss, misc.ms -- allx now runs all up to three (rather than two) times to eliminate - bootstrap failures after small changes like the recent change to - procedure names, so we don't have to rebuild the boot files as often. - Mf-base -- Fix tests for cp0 procedure-name change - misc.ms, patch-compile-0-f-t-f, patch-interpret-0-f-t-f -- add load-compiled-from-port and Sregister_boot_file_fd for loading modes - based on open files instead of paths - 7.ss, primdata.ss, mkheader.ss, scheme.c - 7.ms, foreign.stex, system.stex -- auto-config improvement, detect if X11 exist on Mac OS X - configure -- added box-cas! and vector-cas! - prims.ss, cpnanopass.ss, np-languages.ss, - cmacros.ss, library.ss, primdata.ss - x86_64.ss x86.ss, ppc32.ss, arm32.ss, - 5_6.ms, 5_8.ms, root-experr*, - objects.stex, release_notes.stex -- add generate-procedure-source-information - cmacros.ss, compile.ss, cpnanopass.ss, inspect.ss, - primdata.ss, prims.ss, misc.ms, - system.stex, release_notes.stex -- fix boot_call and the invoke code object to handle multiple values - scheme.c, cpnanopass.ss, 7.ms, release_notes.stex, system.stex -- the compiler now uses a temporary variable to hold the return - value of a nested call across the restore-local-saves form to - properly handle the case where the destination lvalue is an mref - whose base and/or index is a local save. - cpnanopass.ss, - misc.ms -- flush expand-output and expand/optimize-output ports - compile.ss -- clarify "unknown module" error message in determine-module-imports - syntax.ss -- restore the import code on reset to provide consistent error message - syntax.ss, 8.ms -- add uninstall target - Makefile.in, Makefile-workarea.in, Mf-install.in -- add PDB files for Windows - c/*nt, wininstall/*nt.wxs -- use uuid_generate on unix-like systems for S_unique_id - BUILDING, c/Mf-*le, stats.c, objects.stex, release_notes.stex -- when thread_get_room exhausts the local allocation area, it now - goes through a common path with S_get_more_room to allocate a new - local allocation area when appropriate. this can greatly reduce - the use of global allocation (and the number of tc mutex acquires - in threaded builds) when a lot of small objects are allocated by - C code with no intervening Scheme-side allocation or dirty writes. - alloc.c, types.h, externs.h -- made Windows filename handling in directory-list, file-access-time, - file-change-time, file-directory?, file-exists?, file-modification-time, - get-mode, and path-absolute more consistent with - https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file - 6.ss, 6.ms, io.stex, release_notes.stex -- fix handling of calling code's address for locking around a callable, - where the cp register copy in the thread context could be changed - in the callable prep before S_call_help gets it - cpnanopass.ss, x86_64.ss, x86.ss, foreign2.c, foreign.ms -- added initialization of seginfo sorted and trigger_ephemerons fields. - segment.c -- redirecting output of first two checkboot runs to /dev/null so the - ignored exception, if any, does not show up in the make output. - s/Mf-base -- fixed 7.ms to specify the relative path of testfile.boot - 7.ms -- profile counts are now maintained even for code that has been - reclaimed by the collector and must be released explicitly by the - programmer via (profile-release-counters). - pdhtml.ss, primdata.ss, - globals.h, externs.h, fasl.c, prim5.c, prim.c, alloc.c, scheme.c, - misc.ms, - release_notes.stex, system.stex -- clarified required use of scheme-start to start an application - packaged as a boot file and added a short "myecho" example. - use.stex -- fixed a bug in cp0 bug that could fold the apply of a primitive, where - the last argument is not a list, as if it were a call to the primitive - with those arguments - cp0.ss, cp0.ms -- fix allocation of string/bytevector for a foreign-callable argument - or foreign-call return - cpnanopass.ss, foreign.ms, foreign2.c -- foreign-callable code objects are now flagged as "templates", and - the collector now refuses to discard relocation information for - code objects marked as templates when copying them to the static - generation. - cmacros.ss, cpnanopass.ss, - gc.c, - 7.ms -- add hashtable-cells and add a size argument to hashtable-keys, - hashtable-values, and hashtable-entries - newhash.ss, primdata.ss, - hash.ms, root-experr*, patch*, - objects.stex, release_notes.stex -- the body of load-library is now wrapped in a $pass-time with - to show the time spent loading libraries separately from the time - spent in expand. - syntax.ss -- interpret now plays the pass-time game - interpret.ss -- added compile-time-value? predicate and - compile-time-value-value accessor - syntax.ss, primdata.ss, - 8.ms, primvars.ms, root-experr* -- $pass-stats now returns accurate stats for the currently timed - pass. - 7.ss -- compile-whole-program and compile-whole-library now propagate - recompile info from the named wpo file to the object file - to support maybe-compile-program and maybe-compile-library in - the case where compile-whole-{program,library} overwrites the - original object file. - compile.ss, - 7.ms, mat.ss, primvars.ms -- replaced the ancient and unusable bintar with one that creates - a useful tarball for binary installs - bintar -- generated Mf-install InstallBin (InstallLib, InstallMan) now - correctly indirects through InstallPrefix if the --installbin - (--installlib, --installman) configure flag is not present. - configure -- removed definition of generate-procedure-source-information - patch.ss -- guardian tconc cells are now allocated in generation 0 in the hope - that they can be released more quickly. - gc.c -- added ftype-guardian syntax: (ftype-guardian A) creates a new - guardian for ftype pointers of type A, the first base field (or - one of the first base fields in the case of unions) of which must - be a word-sized integer with native endianness representing a - reference count. ftype pointers are registered with and retrieved - from the guardian just like objects are registered with and - retrieved from any guardian. the difference is that the garbage - collector decrements the reference count before resurrecting an - ftype pointer and resurrects only those whose reference counts - become zero, i.e., are ready for deallocation. - ftype.ss, cp0.ss, cmacros.ss, cpnanopass.ss, prims.ss, primdata.ss, - gc.c, - 4.ms, root-experr* -- fixed a bug in automatic recompilation handling of missing include - files specified with absolute pathnames or pathnames starting with - "./" or "..": was erroring out in file-modification-time with a - file-not-found or other exception rather than recompiling. - syntax.ss, - 7.ms, root-experr*, patch* -- changed inline vector-for-each and string-for-each code to - put the last call to the procedure in tail position, as was - already done for the library definitions and for the inline - code for for-each. - cp0.ss, - 5_4.ms, 5_6.ms -- the compiler now generates better inline code for the bytevector - procedure. instead of one byte memory write for each argument, - it writes up to 4 (32-bit machines) or 8 (64-bit machines) bytes - at a time, which almost always results in fewer instructions and - fewer writes. - cpnanopass.ss, - bytevector.ms -- packaged unchanging implicit reader arguments into a single record - to reduce the number of arguments. - read.ss -- recoded run-vector to handle zero-length vectors. it appears - we're not presently generating empty vectors (representing empty - groups), but the fasl format permits them. - 7.ss -- reverted the earlier change to restore indirection through - InstallPrefix, since it didn't and can't play well with the - generated config.h. Instead removed InstallPrefix entirely so - it isn't an attractive hazard. - configure, makefiles/Mf-install.in -- fixed bug in inline-lists: wasn't setting multiply-referenced flag - on p to account for the procedure? check at optimize-level 2. - cpletrec.ss -- fixed bug in check-prelex-flags: was hardwiring $cpcheck-prelex-flags - "after" argument to 'uncprep rather than passing along its argument. - compile.ss -- commented out local definition of sorry! so that problems detected - by $cpcheck-prelex-flags actually result in a raised exception. - cprep.ss -- exposed the default-library-search-handler and a library-search-handler - parameter to permit more control over the search for libraries during - import, compile-whole-library, and compile-whole-program - syntax.ss, primdata.ss, - 8.ms, - libraries.stex -- added fix for whole program/library compilation bug with help from - @owaddell who originally reported the problem in issue 386. this bug - arises from the way the parts of the combined library, and their - binary dependencies, are invoked when one of the constituent libraries - is invoked. consider, for example, a combined library that contains - (A) and (B), where (B) depends on a binary library (C). depending on - the sort order of (A) and (B), which may be unconstrained in the - partial ordering established by library dependencies, invoking (A) may - result in the invoke code for (B) being run first, without (B) ever - being explicitly invoked. this can result in bindings required from - (C) by the invoke code in (B) to be unbound. even in the case where - (A) comes before (B) in the topological sort, if they are combined - into the same cluster, (B)'s invoke code will be run as part of - invoking (A). the solution is two part: first we extend the invoke - requirements of the first library in the cluster to include the binary - libraries that precede it in the topological sort and add a dependency - on the first library in the cluster to all of the other libraries in - the cluster. this means no matter which library in the cluster is - invoked first, it will cause the first library to be invoked, in turn - ensuring the binary libraries that precede it are invoked. when there - are multiple clusters, a dependency is added from each cluster to the - first library in the cluster that precedes it. this ensures that - invoking a library in a later cluster first, will still cause all of - the dependencies of the previous clusters to be invoked. ultimately, - these extra dependencies enforce an ordering on the invocation of the - source and binary libraries that matches the topological sort, even if - the topological sort was under constrained. to maintain the property - that import requirements are a superset of the invoke and visit - requirements, we also extend the import requirements to include the - extended invoke requirements. the import requirements are also added - to the dependency graph to further constrain the topological sort and - ensure that we do not introduce artificial cycles in the import graph. - compile.ss, - 7.ms, - root-experr*, patch* -- fixed failure to install examples for tarball installs - Mf-install.in -- improved packaging support: - replaced bintar script with bintar directory and make file; - tarballs are created via "make create-tarball" and are placed in - the workarea's bintar directory. added rpm directory and make - file for creating RPMs via "make create-rpm". added pkg directory - and make file for creating OSX packages via "make create-pkg". - bintar (removed), bintar/Makefile (new), rpm/Makefile (new), - pkg/Makefile (new), pkg/rmpkg (new), workarea, checkin, newrelease, - Makefile.in, Makefile-workarea.in. -- improved error message for compile-whole-program and - compile-whole-library when a top-level expression is discovered while - processing a wpo file. - compile.ss -- minor build and new-release updates - checkin, newrelease, Makefile.in, Makefile-workarea.in -- added library-search-handler, compile-whole-library, and improved - packaging to the release notes. - release_notes/release_notes.stex - -9.5.2 changes: -- updated version to 9.5.2 - bintar/Makefile rpm/Makefile pkg/Makefile BUILDING NOTICE - makefiles/Mf-install.in makefiles/Makefile-csug.in scheme.1.in - c/Makefile.a6nt c/Makefile.i3nt c/Makefile.ta6nt c/Makefile.ti3nt - mats/Mf-a6nt mats/Mf-i3nt mats/Mf-ta6nt mats/Mf-ti3nt workarea - c/scheme.rc s/7.ss s/cmacros.ss release_notes/release_notes.stex - csug/copyright.stex csug/csug.stex rpm/Makefile pkg/Makefile - wininstall/Makefile wininstall/a6nt.wxs wininstall/i3nt.wxs - wininstall/ta6nt.wxs wininstall/ti3nt.wxs -- fixed handling of bintar, rpm, pkg make files - newrelease -- fixed a bug in the fasl representation and reading of mutually - recursive ftypes where one of the members of the cycle is the - parent of another, which manifested in the fasl reader raising - bogus "incompatible record type" exceptions. (The bug could also - affect other record-type descriptors with cycles involving parent - rtds and "extra" fields.) object files created before this fix - are incompatible with builds with this fix, and objects files - created after this fix are incompatible builds without this fix. - fasl.ss, strip.ss, - fasl.c, - ftype.ms, - release_notes.stex - -9.5.3 changes: -- updated version to 9.5.3 - BUILDING NOTICE makefiles/Mf-install.in makefiles/Makefile-csug.in - scheme.1.in c/Makefile.a6nt c/Makefile.i3nt c/Makefile.ta6nt - c/Makefile.ti3nt mats/Mf-a6nt mats/Mf-i3nt mats/Mf-ta6nt - mats/Mf-ti3nt workarea c/scheme.rc s/7.ss s/cmacros.ss - release_notes/release_notes.stex csug/copyright.stex csug/csug.stex - bintar/Makefile rpm/Makefile pkg/Makefile wininstall/Makefile - wininstall/a6nt.wxs wininstall/i3nt.wxs wininstall/ta6nt.wxs - wininstall/ti3nt.wxs -- fixed welcome text and copyright year in macOS package - newrelease pkg/Makefile release_notes.stex -- update Windows spin-loop count for deleting files and directories - windows.c -- install a file containing revision information alongside boot files; - embed git revision in exported source archives - bintar/Makefile Mf-install.in wininstall/*nt.wxs - s/Mf-base s/.gitattributes s/update-revision -- ignore multiple-value return from interleaved init expressions in - top-level-program - syntax.ss, 8.ms -- add name fields for mutexes and condition variables, now `make-mutex` and - `make-condition` accept an optional argument `name`, which must be a - symbol or #f. The name, if not #f, is printed every time the object is - printed, which is useful for debugging - primdata.ss prims.ss print.ss - thread.ms threads.stex -- change the default compression mode to LZ4 and add a compress-format - parameter to select a compression format for output; input infers the - compression format - io.ss, bytevector.ss, back.ss, primdata.ss, - compress.c (new), new-io.c, fasl.c, scheme.c, compress.h (new), - externs.h, system.h, expeditor.c, configure, Mf-*, Makefile.*nt, - workarea, mat.ss, io.ms, io.stex, objects.stex, release_notes.stex, - root-experr*, patch* -- added compress-level parameter to select a compression level for - file writing and changed the default for lz4 compression to do a - better job compressing. finished splitting glz input routines - apart from glz output routines and did a bit of other restructuring. - removed gzxfile struct-as-bytevector wrapper and moved its fd - into glzFile. moved DEACTIVATE to before glzdopen_input calls - in S_new_open_input_fd and S_compress_input_fd, since glzdopen_input - reads from the file and could block. the compress format and now - level are now recorded directly the thread context. replaced - as-gz? flag bit in compressed bytevector header word with a small - number of bits recording the compression format at the bottom of - the header word. flushed a couple of bytevector compression mats - that depended on the old representation. (these last few changes - should make adding new compression formats easier.) added - s-directory build options to choose whether to compress and, if - so, the format and level. - compress-io.h, compress-io.c, new-io.c, equates.h, system.h, - scheme.c, gc.c, - io.ss, cmacros.ss, back.ss, bytevector.ss, primdata.ss, s/Mf-base, - io.ms, mat.ss, bytevector.ms, root-experr*, - release_notes.stex, io.stex, system.stex, objects.stex -- improved the effectiveness of LZ4 boot-file compression to within - 15% of gzip by increasing the lz4 output-port in_buffer size to - 1<<18. With the previous size (1<<14) LZ4-compressed boot files - were about 50% larger. set the lz4 input-port in_buffer and - out_buffer sizes to 1<<12 and 1<<14. there's no clear win at - present for larger input-port buffer sizes. - compress-io.c -- To reduce the memory hit for the increased output-port in_buffer - size and the corresponding increase in computed out_buffer size, - one output-side out_buffer is now allocated (lazily) per thread - and stored in the thread context. The other buffers are now - directly a part of the lz4File_out and lz4File_in structures - rather than allocated separately. - compress-io.c, scheme.c, gc.c, - cmacros.ss -- split out the buffer emit code from glzwrite_lz4 into a - separate glzemit_lz4 helper that is now also used by gzclose - so we can avoid dealing with a NULL buffer in glzwrite_lz4. - glzwrite_lz4 also uses it to writing large buffers directly and - avoid the memcpy. - compress-io.c -- replaced lz4File_out and lz4File_in mode enumeration with the - compress format and inputp boolean. using switch to check and - raising exceptions for unexpected values to further simplify - adding new compression formats in the future. - compress-io.c -- replaced the never-defined struct lz4File pointer in glzFile - union with the more specific struct lz4File_in_r and Lz4File_out_r - pointers. - compress-io.h, compress-io.c -- added free of lz4 structures to gzclose. also changed file-close - logic generally so that (1) port is marked closed before anything is - freed to avoid dangling pointers in the case of an interrupt or - error, and (2) structures are freed even in the case of a write - or close error, before the error is reported. also now mallocing - glz and lz4 structures after possibility of errors have passed where - possible and freeing them when not. - compress-io.c, - io.ss -- added return-value checks to malloc calls and to a couple of other - C-library calls. - compress-io.c -- corrected EINTR checks to look at errno rather than return codes. - compress-io.c -- added S_ prefixes to the glz* exports - externs.h, compress-io.c, new-io.c, scheme.c, fasl.c -- added entries for mutex-name and mutex-thread - threads.stex -- fix record-ref reduction in cp0 - in expressions like - (record-ref ... (begin (newline) (record ...))) - the reduction was dropping the possible side effect expressions - in this case the (newline). - cp0.ss -- zero?, fxzero?, positive?, fxpositive?, etc., now go through - (a suitably modified) relop-length so that, for example, - (zero? (length x)) results in the same code as (null? x). added - correctness tests for these and all of the other predicates that - go through relop-length. - cpnanopass.ss, 5_2.ms -- assertion-violationf and friends now show the who, message, and - irritants in the original call when who or message is found not to - be of the right type. - exceptions.ss -- fix incorrect uses of fxzero? x86.ss backend, since a 32-bit - immediate is not necessarily a fixnum - x86.ss -- added MinGW/MSYS build support for Windows and configuration for - Travis-CI testing of all Windows builds - BUILDING, .travis*, wininstall/Makefile -- fix multiply of -2^30 with itself on 64-bit platforms - number.c, 5_3.ms, release_notes.stex -- fixed typo in description of case macro - csug/control.stex -- fix signatures of $annotation-options, $fasl-strip-options, - $file-options, and $library-requirements-options - primdata.ss -- small fix in relop-length to enable the optimization - cpnanopass.ss -- make test for relop-length more sensitive - 5_2.ms -- added support for Microsoft Visual Studio 2019 on Windows - BUILDING, c/vs.bat, wininstall/locate-vcredist.bat -- fixed open-string-input-port on immutable strings - cpnanopass.ss, io.ms, release_notes.stex -- use setenv rather than putenv on non WIN32 environments - prim5.c, system.stex -- restore {Free,Open,Net}BSD build, support Windows cross-compile - via MinGW, add configuration options, and add helper makefile targets - expeditor.c, thread.c, stats.c, statics.c, scheme.c, main.c, types.h, - externs.h, globals.h, nocurses.h, version.h, system.h, segment.h, - a6ob.def, ta6ob.def, a6nb.def, ta6nb.def, i3nt.def, ti3nt.def, - c/Mf-*, build.bat, makefiles/Makefile.in, makefiles/Mf-install.in, - s/update-revision, BUILDING -- export `ee-backward-delete-sexp` binding in the expression-editor module. - expeditor.ss -- fix ee_read_char to handle ^@ properly - expeditor.c -- prevent access before start of array - scheme.c -- remove dead stores in files - compress-io.c, new-io.c -- fixed tab character in makefiles - c/Mf-*nt -- use case-insensitive search for ".exe" on Windows - c/scheme.c -- fix __collect_safe for x86_64 and floating-point arguments or results - x86_64.ss, foreign.ms, release_notes.stex -- annotations are now preserved in object files for debug - only, for profiling only, for both, or not at all, depending - on the settings of generate-inspector-information and - compile-profile. in particular, when inspector information - is not enabled but profiling is, source information does - not leak into error messages and inspector output, though it is - still available via the profile tools. The mechanics of this - involved repurposing the fasl a? parameter to hold an annotation - flags value when it is not #f and remaking annotations with - new flags if necessary before emitting them. - compile.ss, fasl.ss, misc.ms -- altered a number of mats to produce correct results even - when the 's' directory is profiled. - misc.ms, cp0.ms, record.ms -- profile-release-counters is now generation-friendly; that is, - it doesn't look for dropped code objects in generations that have - not been collected since the last call to profile-release-counters. - also, it no longer allocates memory when it releases counters. - pdhtml.ss, - gc.c, gcwrapper.c, globals.h, prim5.c -- removed unused entry points S_ifile, S_ofile, and S_iofile - alloc.c, externs.h -- mats that test loading profile info into the compiler's database - to guide optimization now weed out preexisting entries, in case - the 's' directory is profiled. - 4.ms, mat.ss, misc.ms, primvars.ms -- counters for dropped code objects are now released at the start - of each mat group. - mat.ss -- replaced ehc (enable-heap-check) option with hci (heap-check-interval) - option that allows heap checks to be performed periodically rather - than on each collection. hci=0 is equivalent to ehc=f (disabling - heap checks) and hci=1 is equivalent to ehc=t (enabling heap - checks every collection), while hci=100 enables heap checks only - every 100th collection. allx and bullyx mats use this feature - to reduce heap-checking overhead to a more reasonable level. this - is particularly important when the 's' directory is profiled, - since the amount of static memory to be checked is greatly increased - due to the counters. - mats/Mf-base, mat.ss, primvars.ms -- added a mat that calls #%show-allocation, which was otherwise not - being tested. - misc.ms -- removed a broken primvars mat and updated two others. in each case, - the mat was looking for information about primitives in the wrong - (i.e., old) place and silently succeeding when it didn't find any - primitives to test. the revised mats (along with a few others) now - check to make sure at least one identifier has the information they - look for. the removed mat was checking for library information that - is now compiled in, so the mat is now unnecessary. the others were - (not) doing argument-error checks. fixing these turned up a handful of - problems that have also been fixed: a couple of unbound variables in the - mat driver, two broken primdata declarations, a tardy argument check - by profile-load-data, and a bug in char-ready?, which was requiring - an argument rather than defaulting it to the current input port. - primdata.ss, pdhtml.ss, io.ms, - primdvars.ms, 4.ms, 6.ms, misc.ms, patch* -- added initial support for recording coverage information. when the - new parameter generate-covin-files is set, the compiler generates - .covin files containing the universe of all source objects for which - profile forms are present in the expander output. when profiling - and generation of covin files are enabled in the 's' directory, the - mats optionally generate .covout files for each mat file giving - the subset of the universe covered by the mat file, along with an - all.covout in each mat output directory aggregating the coverage - for the directory and another all.covout in the top-level mat - directory aggregating the coverage for all directories. - back.ss, compile.ss, cprep.ss, primdata.ss, s/Mf-base, - mat.ss, mats/Mf-base, mats/primvars.ms -- support for generating covout files is now built in. with-coverage-output - gathers and dumps coverage information, and aggregate-coverage-output - combines (aggregates) covout files. - pdhtml.ss, primdata.ss, compile.ss, - mat.ss, mats/Mf-base, primvars.ms -- profile-clear now adjusts active coverage trackers to avoid losing - coverage information. - pdhtml.ss, - prim5.c -- nested with-coverage calls are now supported. - pdhtml.ss -- switched to a more compact representation for covin and covout files; - reduces disk space (compressed or not) by about a factor of four - and read time by about a factor of two with no increase in write time. - primdata.ss, pdhtml.ss, cprep.ss, compile.ss, - mat.ss, mats/Mf-base -- added support for determining coverage for an entire run, including - coverage for expressions hit during boot time. 'all' mats now produce - run.covout files in each output directory, and 'allx' mats produce - an aggregate run.covout file in the mat directory. - pdhtml.ss, - mat.ss, mats/Mf-base -- profile-release-counters now adjusts active coverage trackers to - account for the counters that have been released. - pdhtml.ss, - prim5.c -- replaced the artificial "examples" target with a real "build-examples" - target so make won't think it always has to mats that depend upon - the examples directory having been compiled. mats make clean now - runs make clean in the examples directory. - mats/Mf-base -- importing a library from an object file now just visits the object - file rather than doing a full load so that the run-time code for - the library is not retained. The run-time code is still read - because the current fasl format forces the entire file to be read, - but not retaining the code can lower heap size and garbage-collection - cost, particularly when many object-code libraries are imported. - The downside is that the file must be revisited if the run-time - code turns out to be required. This change exposed several - places where the code was failing to check if a revisit is needed. - syntax.ss, - 7.ms, 8.ms, misc.ms, root-experr* -- fixed typos: was passing unquoted load rather than quoted load - to $load-library along one path (where it is loading source code - and therefore irrelevant), and was reporting src-path rather than - obj-path in a message about failing to define a library. - syntax.ss -- compile-file and friends now put all recompile information in - the first fasl object after the header so the library manager can - find it without loading the entire fasl file. The library manager - now does so. It also now checks to see if library object files - need to be recreated before loading them rather than loading them and - possibly recompiling them after discovering they are out of date, since - the latter requires loading the full object file even if it's out of - date, while the former takes advantage of the ability to extract just - recompile information. as well as reducing overhead, this eliminates - possibly undesirable side effects, such as creation and registration - of out-of-date nongenerative record-type descriptors. because the - library manager expects to find recompile information at the front of - an object file, it will not find all recompile information if object - files are "catted" together. also, compile-file has to hold in memory - the object code for all expressions in the file so that it can emit the - unified recompile information, rather than writing to the object file - incrementally, which can significantly increase the memory required - to compile a large file full of individual top-level forms. This does - not affect top-level programs, which were already handled as a whole, - or a typical library file that contains just a single library form. - compile.ss, syntax.ss -- the library manager now checks include files before library dependencies - when compile-imported-libraries is false (as it already did when - compile-imported-libraries is true) in case a source change affects - the set of imported libraries. (A library change can affect the set - of include files as well, but checking dependencies before include - files can cause unneeded libraries to be loaded.) The include-file - check is based on recompile-info rather than dependencies, but the - library checks are still based on dependencies. - syntax.ss -- fixed check for binding of scheme-version. (the check prevents - premature treatment of recompile-info records as Lexpand forms - to be passed to $interpret-backend.) - scheme.c -- strip-fasl-file now preserves recompile-info when compile-time info - is stripped. - strip.ss -- removed include-req* from library/ct-info and ctdesc records; it - is no longer needed now that all recompile information is maintained - separately. - expand-lang.ss, syntax.ss, compile.ss, cprep.ss, syntax.ss -- changed the fasl format and reworked a lot of code in the expander, - compiler, fasl writer, and fasl reader to allow the fasl reader - to skip past run-time information when it isn't needed and - compile-time information when it isn't needed. Skipping past - still involves reading and decoding when encrypted, but the fasl - reader no longer parses or allocates code and data in the portions - to be skipped. Side effects of associating record uids with rtds - are also avoided, as are the side effects of interning symbols - present only in the skipped data. Skipping past code objects - also reduces or eliminates the need to synchronize data and - instruction caches. Since the fasl reader no longer returns - compile-time (visit) or run-time (revisit) code and data when not - needed, the fasl reader no longer wraps these objects in a pair - with a 0 or 1 visit or revisit marker. To support this change, - the fasl writer generates separate top-level fasl entries (and - graphs) for separate forms in the same top-level source form - (e.g., begin or library). This reliably breaks eq-ness of shared - structure across these forms, which was previously broken only - when visit or revisit code was loaded at different times (this - is an incompatible change). Because of the change, fasl "groups" - are no longer needed, so they are no longer handled. - 7.ss, cmacros.ss, compile.ss, expand-lang.ss, strip.ss, - externs.h, fasl.c, scheme.c, - hash.ms -- the change above is surfaced in an optional fasl-read "situation" - argument (visit, revisit, or load). The default is load. visit - causes it to skip past revisit code and data; revisit causes it - to skip past visit code and data; and load causes it not to skip - past either. visit-revisit data produced by (eval-when (visit - revisit) ---) is never skipped. - 7.ss, primdata.ss, - io.stex -- to improve compile-time and run-time error checking, the - Lexpand recompile-info, library/rt-info, library-ct-info, and - program-info forms have been replaced with list-structured forms, - e.g., (recompile-info ,rcinfo). - expand-lang.ss, compile.ss, cprep.ss, interpret.ss, syntax.ss -- added visit-compiled-from-port and revisit-compiled-from-port - to complement the existing load-compiled-from-port. - 7.ss, primdata.ss, - 7.ms, - system.stex -- increased amount read when seeking an lz4-compressed input - file from 32 to 1024 bytes at a time - compress-io.c -- replaced the fasl a? parameter value #t with an "all" flag value - so it's value is consistently a mask. - cmacros.ss, fasl.ss, compile.ss -- split off profile mats into a separate file - misc.ms, profile.ms (new), root-experr*, mats/Mf-base -- added coverage percent computations to mat allx/bullyx output - mat.ss, mats/Mf-base, primvars.ms -- replaced coverage tables with more generic and generally useful - source tables, which map source objects to arbitrary values. - pdhtml.ss, compile.ss, cprep.ss, primdata.ss, - mat.ss, mats/Mf-base, primvars.ms, profile.ms, - syntax.stex -- reduced profile counting overhead by using calls to fold-left - instead of calls to apply and map and by using fixnum operations - for profile counts on 64-bit machines. - pdhtml.ss -- used a critical section to fix a race condition in the calculations - of profile counts that sometimes resulted in bogus (including - negative) counts, especially when the 's' directory is profiled. - pdhtml.ss -- added discard flag to declaration for hashtable-size - primdata.ss -- redesigned the printed representation of source tables and rewrote - get-source-table! to read and store incrementally to reduce memory - overhead. - compile.ss -- added generate-covin-files to the set of parameters preserved - by compile-file, etc. - compile.ss, - system.stex -- moved covop argument before the undocumented machine and hostop - arguments to compile-port and compile-to-port. removed the - undocumented ofn argument from compile-to-port; using - (port-name ip) instead. - compile.ss, primdata.ss, - 7.ms, - system.stex -- compile-port now tries to come up with a file position to supply - to make-read, which it can do if the port's positions are character - positions (presently string ports) or if the port is positioned - at zero. - compile.ss -- audited the argument-type-error fuzz mat exceptions and fixed a - host of problems this turned up (entries follow). added #f as - an invalid argument for every type for which #f is indeed invalid - to catch places where the maybe- prefix was missing on the argument - type. the mat tries hard to determine if the condition raised - (if any) as the result of an invalid argument is appropriate and - redirects the remainder to the mat-output (.mo) file prefixed - with 'Expected error', causing them to show up in the expected - error output so developers will be encouraged to audit them in - the future. - primvars.ms, mat.ss -- added an initial symbol? test on machine type names so we produce - an invalid machine type error message rather than something - confusing like "machine type #f is not supported". - compile.ss -- fixed declarations for many primitives that were specified as - accepting arguments of more general types than they actually - accept, such as number -> real for various numeric operations, - symbol -> endianness for various bytevector operations, - time -> time-utc for time-utc->date, and list -> list-of-string-pairs - for default-library-search-handler. also replaced some of the - sub-xxxx types with specific types such as sub-symbol -> endianness - in utf16->string, but only where they were causing issues with - the primvars argument-type-error fuzz mat. (this should be done - more generally.) - primdata.ss -- fixed incorrect who arguments (was map instead of fold-right, - current-date instead of time-utc->date); switched to using - define-who/set-who! generally. - 4.ss, date.ss -- append! now checks all arguments before any mutation - 5_2.ss -- with-source-path now properly supplies itself as who for the - string? argument check; callers like load now do their own checks. - 7.ss -- added missing integer? check to $fold-bytevector-native-ref whose - lack could have resulted in a compile-time error. - cp0.ss -- fixed typo in output-port-buffer-mode error message - io.ss -- fixed who argument (was fx< rather than fx maybe-timeout) - primdata.ms -- added "invalid code page ~s" to set of messages considered valid - argument-type-check error messages, for Windows multibyte->string - and string->multibyte. - primvars.ms -- used with-object-file to restore accidentally dropped close-port in - compile-whole-program and compile-whole-library - compile.ss -- initialized variable to enable compilation with gcc 9.1.0 at -O3 - c/scheme.c -- added missing Inner wrappers around the library/ct-info and - library-rt-info records in the code for compile-whole-xxx. - compile.ss, - 7.ms -- local-eval-hook now calls eval rather than interpret when profiling - is enabled, so local transformer code can be profiled. - syntax.ss, - profile.ms -- fix compiler bug related to call-with-values and a first argument - whose body result is compiled to an allocation, inline form, or - foreign call - cpnanopass.ss, 3.ms -- improved error reporting for library compilation-instance errors: - now including the name of the object file from which the "wrong" - compilation instance was loaded, if it was loaded from (or compiled - to) an object file and the original importing library, if it was - previously loaded from an object file due to a library import. - syntax.ss, 7.ss, interpret.ss, - 8.ms, root-experr* -- removed situation and for-input? arguments from $make-load-binary, - since the only consumer always passes 'load and #f. - 7.ss, - scheme.c -- $separate-eval now prints the stderr and stdout of the subprocess - to help in diagnosing separate-eval and separate-compile issues. - mat.ss -- added unregister-guardian, which can be used to unregister - the unresurrected objects registered with any guardian. guardian? - can be used to distinguish guardian procedures from other objects. - cp0.ss, cmacros.ss, cpnanopass.ss, ftype.ss, primdata.ss, - prims.ss, - gcwrapper.c, prim.c, externs.h, - 4.ms, primvars.ms - release_notes.stex - smgmt.stex, threads.stex -- added verify-loadability. given a situation (visit, revisit, - or load) and zero or more pathnames (each of which may be optionally - paired with a library search path), verity-loadability checks - whether the set of object files named by those pathnames and any - additional object files required by library requirements in the - given situation can be loaded together. it raises an exception - in each case where actually attempting to load the files would - raise an exception and additionally in cases where loading files - would result in the compilation or loading of source files in - place of the object files. if the check is successful, - verity-loadability returns an unspecified value. in either case, - although portions of the object files are read, none of the - information read from the object files is retained, and none of - the object code is read, so there are no side effects other than - the file operations and possibly the raising of an exception. - library and program info records are now moved to the top of each - object file produced by one of the file compilation routines, - just after recompile info, with a marker to allow verity-loadability - to stop reading once it reads all such records. this change is - not entirely backward compatible; the repositioning of the records - can be detected by a call to list-library made from a loaded file - before the definition of one or more libraries. it is fully - backward compatible for typical library files that contain a - single library definition and nothing else. adding this feature - required changes to the object-file format and corresponding - changes in the compiler and library manager. it also required - moving cross-library optimization information from library/ct-info - records (which verity-loadability must read) to the invoke-code - for each library (which verity-loadability does not read) to - avoid reading and permanently associating record-type descriptors - in the code with their uids. - compile.ss, syntax.ss, expand-lang.ss, primdata.ss, 7.ss, - 7.ms, misc.ms, root-experr*, patch*, - system.stex, release_notes.stex -- fixed a bug that bit only with the compiler compiled at - optimize-level 2: add-library/rt-records was building a library/ct-info - wrapper rather than a library/rt-info wrapper. - compile.ss -- fixed a bug in visit-library that could result in an indefinite - recursion: it was not checking to make sure the call to $visit - actually added compile-time info to the libdesc record. it's not - clear, however, whether the libdesc record can be missing - compile-time information on entry to visit-library, so the code - that calls $visit (and now checks for compile-time information - having been added) might not be reachable. ditto for - revisit-library. - syntax.ss - syntax.ss, primdata.ss, - 7.ms, root-experr*, patch*, - system.stex, release_notes.stex -- added some argument-error checks for library-directories and - library-extensions, and fixed up the error messages a bit. - syntax.ss, - 7.ms, root-experr* -- compile-whole-program now inserts the program record into the - object file for the benefit of verify-loadability. - syntax.ss, - 7.ms, root-experr* -- changed 'loading' import-notify messages to the more precise - 'visiting' or 'revisiting' in a couple of places. - syntax.ss, - 7.ms, 8.ms -- added concatenate-object-files - compile.ss, primdata.ss - 7.ms, root-experr* - system.stex, use.stex, release_notes.stex -- added invoke-library - syntax.ss, primdata.ss, - 8.ms, root-experr*, - libraries.stex, release_notes.stex -- updated the date - release_notes.stex -- libraries contained within a whole program or library are now - marked pending before their invoke code is run so that invoke - cycles are reported as such rather than as attempts to invoke - while still loading. - compile.ss, syntax.ss, primdata.ss, - 7.ms, root-experr* -- the library manager now protects against unbound references - from separately compiled libraries or programs to identifiers - ostensibly but not actually exported by (invisible) libraries - that exist only locally within a whole program. this is done by - marking the invisibility of the library in the library-info and - propagating it to libdesc records; the latter is checked upon - library import, visit, and invoke as well as by verify-loadability. - the import and visit code of each invisible no longer complains - about invisibility since it shouldn't be reachable. - syntax.ss, compile.ss, expand-lang.ss, - 7.ms, 8.ms, root-experr*, patch* -- documented that compile-whole-xxx's linearization of the - library initialization code based on static dependencies might - not work for dynamic dependencies. - system.stex -- optimized bignum right shifts so the code (1) doesn't look at - shifted-off bigits if the bignum is positive, since it doesn't - need to know in that case if any bits are set; (2) doesn't look - at shifted-off bigits if the bignum is negative if it determines - that at least one bit is set in the bits shifted off the low-order - partially retained bigit; (3) quits looking, if it must look, for - one bits as soon as it finds one; (4) looks from both ends under - the assumption that set bits, if any, are most likely to be found - toward the high or low end of the bignum rather than just in the - middle; and (5) doesn't copy the retained bigits and then shift; - rather shifts as it copies. This leads to dramatic improvements - when the shift count is large and often significant improvements - otherwise. - number.c, - 5_3.ms, - release_notes.stex -- threaded tc argument through to all calls to S_bignum and - S_trunc_rem so they don't have to call get_thread_context() - when it might already have been called. - alloc.c, number.c, fasl.c, print.c, prim5.c, externs.h -- added an expand-primitive handler to partially inline integer?. - cpnanopass.ss -- added some special cases for basic arithmetic operations (+, -, *, - /, quotient, remainder, and the div/div0/mod/mod0 operations) to - avoid doing unnecessary work for large bignums when the result - will be zero (e.g,. multiplying by 0), the same as one of the - inputs (e.g., adding 0 or multiplying by 1), or the additive - inverse of one of the inputs (e.g., subtracting from 0, dividing - by -1). This can have a major beneficial affect when operating - on large bignums in the cases handled. also converted some uses - of / into integer/ where going through the former would just add - overhead without the possibility of optimization. - 5_3.ss, - number.c, externs.h, prim5.c, - 5_3.ms, root-experr, patch*, - release_notes.stex -- added a queue to hold pending signals for which handlers have - been registered via register-signal-handler so up to 63 (configurable - in the source code) unhandled signals are buffered before the - handler has to start dropping them. - cmacros.ss, library.ss, prims.ss, primdata.ss, - schsig.c, externs.h, prim5.c, thread.c, gc.c, - unix.ms, - system.stex, release_notes.stex -- bytevector-compress now selects the level of compression based - on the compress-level parameter. Prior to this it always used a - default setting for compression. the compress-level parameter - can now take on the new minimum in addition to low, medium, high, - and maximum. minimum is presently treated the same as low - except in the case of lz4 bytevector compression, where it - results in the use of LZ4_compress_default rather than the - slower but more effective LZ4_compress_HC. - cmacros,ss, back.ss, - compress_io.c, new_io.c, externs.h, - bytevector.ms, mats/Mf-base, root-experr* - io.stex, objects.stex, release_notes.stex -- fix fasl-read signature - primdata.ss -- console I/O on Windows now supports Unicode characters in the BMP - expeditor.c, new-io.c, release_notes.stex -- the collector now releases bignum temporaries in the collector - rather than relocating them so we don't keep around huge bignum - temporaries forever. - gc.c -- removed the presumably useless vector-handling code from load() - which used to be required to handle fasl groups. - scheme.c -- object files are no longer compressed as a whole, and the parameter - compile-compressed is no longer defined. instead, the individual - fasl objects within an object file are compressed whenever the - new parameter fasl-compressed is set to its default value, #t. - this allows the fasl reader to seek past portions of an object - file that are not of interest, i.e., visit-only code and data - when "revisiting" an object file and revisit-only code and data - when "visiting" an object file. the compressed portions are - compressed using the format and level specified by the compress-format - and compress-level parameters. the C-coded fasl reader and - boot-file loader no longer handle compressed files; these are - handled, less efficiently, by the Scheme entry point (fasl-read). - a warning exception is raised the first time a program attempts - to create or read a compressed fasl file. - 7.ss, s/Mf-base, back.ss, bytevector.ss, cmacros.ss, compile.ss, - fasl-helpers.ss, fasl.ss, primdata.ss, strip.ss, syntax.ss, - externs.h, fasl.c, gc.c, scheme.c, thread.c, - mats/6.ms, mats/7.ms, mats/bytevector.ms, mats/misc.ms, patch*, - root-experr*, - intro.stex, use.stex, io.stex, system.stex, - release_notes.stex -- added begin wrappers around many of the Scheme source files that - contained multiple expressions to cut down the number of top-level - fasl objects and increase compressibility. also removed the - string filenames for debugging at the start of each file that had - one---these are best inserted universally by a modified compile-file - during a debugging session when desired. also removed unnecessary - top-level placeholder definitions for the assignments that follow. - 4.ss, 5_1.ss, 5_2.ss, 5_3.ss, 5_7.ss, 6.ss, 7.ss, bytevector.ss, - cafe.ss, cback.ss, compile.ss, cp0.ss, cpcommonize.ss, cpletrec.ss, - cpnanopass.ss, cprep.ss, cpvalid.ss, date.ss, engine.ss, enum.ss, - env.ss, event.ss, exceptions.ss, expeditor.ss, fasl.ss, foreign.ss, - format.ss, front.ss, ftype.ss, inspect.ss, interpret.ss, io.ss, - library.ss, mathprims.ss, newhash.ss, pdhtml.ss, pretty.ss, - prims.ss, primvars.ss, print.ss, read.ss, record.ss, reloc.ss, - strnum.ss, syntax.ss, trace.ss -- updated bullyx patches - patch* -- fixed csug copyright year substitutions and changed revisiondate - to not be generated, making the csug build reproducible - newrelease csug/csug.stex -- fixed Windows build using MSYS2 - c/Mf-a6nt, c/Mf-i3nt, c/Mf-ta6nt, c/Mf-ti3nt, mats/Mf-a6nt, - mats/Mf-i3nt, mats/Mf-ta6nt, mats/Mf-ti3nt -- fixed build on Linux with musl libc - expeditor.c -- extended primitive folding to primitives that return multiple - values. - cp0.ss, primdata.ss, - cp0.ms -- fix handling of calling code's address for locking around a callable - that has a u8*, u16*, or u32* argument, which could cause the - cp register copy in the thread context to be changed before - S_call_help gets it - cpnanopass.ss, schlib.c, foreign2.c, foreign.ms -- the collector now promotes objects one generation higher at a time - by default. previously, it promoted every live oldspace object to - the selected target generation, which could result in objects - prematurely skipping one or more generations and thus being - retained longer than their ages justify. the biggest cost in - terms of code complexity and performance is the recording of - pointers from older newspace objects to younger newspace objects - that could not previously occur. - gc.c, alloc.c, externs.h -- the collect procedure now takes an additional optional minimum - target generation argument to allow the new default behavior to - be overridden. - 7.ss, primdata.ss, - gcwrapper.c, - 7.ms, root-experr* -- added cn flag to control collect-notify - mats/Mf-base -- resweep_weak_pairs now sets sweep_loc to orig_next_loc rather than - first_loc since the latter could result in unnecessary sweeping of - existing target-generation weak pairs. - gc.c -- added set of S_child_processes[newg] to S_child_processes[oldg] - in S_do_gc code handling decreases in the maximum generation. - gcwrapper.c -- a specialized variant of the collector is used in the common case - where the max copied generation is 0, the min and max target - generations are 1, and there are no locked generation 0 objects - is now used. with the default collection parameters and no locking - of generation 0 objects, these collections account for 3/4 of all - collections. - gc.c, gc-011.c (new), gcwrapper.c, externs.h, c/Mf-base -- maybe-fire-collector no longer tries to be so precise and instead - just counts the number of generation-bytes allocated since the - last gc. surprisingly, rebuilding the s directory requires about - the same number of collections with this coarser (and less - expensive) measurement. this change also fixes a problem with - too-frequent collections when the maximum-generation is set to - zero. to make the determination even less expensive, a running - total of bytes in each generation is now maintained in a new - bytes_of_generation vector, and maybe-fire-collector is no longer - called when the collector is running. - alloc.c, gc.c, gcwrapper.c, globals.h -- copy now copies two pairs at once only if they are in the same - segment, which saves a few memory references and tests and turns - out not to reduce the number of opportunities significantly in - tested programs. - gc.c -- occupied_segments, first_loc, base_loc, next_loc, bytes_left, - bytes_of_space, sweep_loc, and orig_next_loc are now indexed - by [g][s] rather than [s][g] to improve locality in the default - (and common) case where there are only a handful of active - generations. - globals.h, types.h, segment.c, gc.c, gcwrapper.c, prim5.c -- documented change to collect procedure - smgmt.stex, release_notes.stex -- now maintaining 16-byte architectural stack alignment (if the - incoming stack is so aligned) on all x86 platforms except - i3nt/ti3nt. more recent versions of gcc sometimes generate sse - instructions that require 16-byte stack alignment. - x86.ss -- added missing #ifndef WIN32 - gcwrapper.c -- added initialization of __to_g to make gcc 7.5.0 happy - gc.c -- updated Windows makefiles - c/Makefile.*nt -- use lowercase for Windows include files - segment.c, windows.c -- proper unicode handling when retrieving error messages from the OS - on Windows - windows.c -- repair collector handling of an ephemerons that refers to a - younger object during incremental promotion - gc.c, 4.ms -- added textual-output-port checks for record-writer write argument - print.ss, - record.ms, root-experr* -- now using 64-bit arithmetic for seconds in S_condition_wait to - prevent a potential 2038 bug, at least on platforms where time_t - is 64 bits. also now rounding rather than truncating nanoseconds - in the conversion to milliseconds on Windows. - thread.c -- fixed a bug in arm32 that caused an error when generating - instructions with immediate operands where the immediate was larger - than 8 bits. - arm32.ss -- fixed formatting in arm32.ss - arm32.ss -- disabled unsupported mats for arm32le - foreign.ms, misc.ms -- fixed callee-save floating point registers for arm32 - arm32.ss, ftype.ss, np-languages.ss, primdata.ss -- added a mat for the add-with-immediate bug - misc.ms, - mats/arm-immediate-1.ss (new), mats/arm-immediate-2.ss (new) -- added a note about arm32 targets requiring a kernel module for the - time stamp counter - prims.ss - -9.5.4 changes: -- updated version to 9.5.4 - BUILDING NOTICE makefiles/Mf-install.in makefiles/Makefile-csug.in - scheme.1.in c/Makefile.a6nt c/Makefile.i3nt c/Makefile.ta6nt - c/Makefile.ti3nt mats/Mf-a6nt mats/Mf-i3nt mats/Mf-ta6nt - mats/Mf-ti3nt workarea c/scheme.rc s/7.ss s/cmacros.ss - release_notes/release_notes.stex csug/copyright.stex csug/csug.stex - bintar/Makefile rpm/Makefile pkg/Makefile wininstall/Makefile - wininstall/a6nt.wxs wininstall/i3nt.wxs wininstall/ta6nt.wxs - wininstall/ti3nt.wxs - -9.5.5 changes: -- updated version to 9.5.5 - BUILDING NOTICE makefiles/Mf-install.in scheme.1.in c/Makefile.a6nt - c/Makefile.i3nt c/Makefile.ta6nt c/Makefile.ti3nt mats/Mf-a6nt - mats/Mf-i3nt mats/Mf-ta6nt mats/Mf-ti3nt workarea c/scheme.rc - s/cmacros.ss release_notes/release_notes.stex csug/copyright.stex - csug/csug.stex bintar/Makefile rpm/Makefile pkg/Makefile - wininstall/Makefile wininstall/a6nt.wxs wininstall/i3nt.wxs - wininstall/ta6nt.wxs wininstall/ti3nt.wxs -- newrelease no longer logs as updated files with no actual changes - newrelease -- repaired continuation for exception handler of error for returning - the wrong number of values to a multiple-value context - cpnanopass.ss, np-languages.ss, 3.ms -- adjust arm32 backend to not choose shorter instructions for larger - return-address offsets, which breaks label address assignment - arm32.ss -- repair remainder and modulo on flonums by using fmod - prim5.c, 5_3.ss, 5_3.ms -- add special case in cpnanopass.ss for (eq? (ftype-pointer-address x) 0) - cpnanopass.ss -- fix missing include in externs.h for struct timespec - c/expeditor.c, c/externs.h, c/prim5.c, c/scheme.c, c/stats.c -- fix signature of generate-temporaries - primdata.ss primvars.ss -- sleep of negative durations now returns immediately - 7.ss -- avoid hard-coded paths for utilities in build scripts - checkin csug/gifs/Makefile csug/math/Makefile examples/Makefile - makefiles/Makefile-csug.in makefiles/Makefile-release_notes.in - makefiles/Mf-install.in makefiles/installsh mats/6.ms mats/Mf-a6fb - mats/Mf-a6le mats/Mf-a6nb mats/Mf-a6ob mats/Mf-a6osx mats/Mf-arm32le - mats/Mf-i3fb mats/Mf-i3le mats/Mf-i3nb mats/Mf-i3ob mats/Mf-i3osx - mats/Mf-i3qnx mats/Mf-ppc32le mats/Mf-ta6fb mats/Mf-ta6le mats/Mf-ta6nb - mats/Mf-ta6ob mats/Mf-ta6osx mats/Mf-ti3fb mats/Mf-ti3le mats/Mf-ti3nb - mats/Mf-ti3ob mats/Mf-ti3osx mats/Mf-tppc32le mats/unix.ms newrelease - pkg/Makefile release_notes/gifs/Makefile release_notes/math/Makefile - s/Mf-base workarea -- fixed configure script for update of nanopass to v1.9.2 - configure -- fixed help description for configure options --installschemename, - --installpetitename, and --installscriptname - configure -- maybe-compile-program now returns void - compile.ss 7.ms -- fixed right shift of a negative bignum by a multiple of 32 - number.c 5_3.ms -- fixed the documentation of load-shared-object to mention an up-to-date - dll for Windows - foreign.stex -- New spellings #true and #false for #t and #f are recognized - read.ss 6.ms -- refactor mats to allow different configurations to run in parallel. - The {partial,all,bully}x targets in Mats/Mf-base now support running - in parallel if make chooses to do so (e.g., if instructed via -j). - Update travis-ci build scripts to use new partialx target and run - jobs in parallel (based on the number of cores available). Also - add the ability to "skip" (i.e., error before building) travis targets - by using a line (or lines) beginning with "travis:only:" and listing - the desired target machine type(s) in the commit message. - .travis.yml .travis/{build,test,maybe-skip-build}.sh - mats/{5_4,6,7,8,bytevector,examples,foreign}.ms - mats/{ftype,hash,io,misc,primvars,profile,record}.ms - mats/Mf-base mats/Mf-*nt mats/mat.ss mats/patch-interpret* -- fix x86_64 (& integer-8) and (& integer-16) foreign-call argument - passing - x86_64, s/Mf-[t]a6{le,osx} -- fixed misnamed pattern variables in bytevector-*-ref - bytevector.ss -- add workaround for Rosetta 2 bug in [t]a6osx builds. The overhead - during native (x86) execution is the addition of a single int compare - and branch in S_bytevector_read, plus a small amount of work at startup - to determine whether we are running under Rosetta translation. - new-io.c, scheme.c, version.h -- use a 7-byte NOP in the x86_64 fasl relocator instead of 7 1-byte NOPs - fasl.c -- Move unused terminals in L4.5 to later languages. - np-languages.ss -- vector literals can be made self-evaluating with the new parameter - self-evaluating-vectors - s/back.ss s/primdata.ss s/syntax.ss csug/objects.tex mats/misc.ms -- remove obsolete travis-ci.org configuration - README.md .travis.yml .travis/* -- add GitHub actions workflow for automated testing - .github/workflows/{build.sh,summary,test.sh,test.yml} -- corrected signature of compile-whole-program and compile-whole-library - s/primdata.ss -- clarify rd-bytevector error message for non-atomic token types, such - as vparen, where the token value is #f - mats/6.ms, mats/root-experr-compile-0-f-f-f, - mats/root-experr-compile-2-f-f-f, release_notes/release_notes.stex, - s/read.ss -- include an identifier name in the syntax error for missing ellipsis - mats/8.ms, mats/root-experr-compile-0-f-f-f, - mats/root-experr-compile-2-f-f-f, release_notes/release_notes.stex, - s/syntax.ss - -9.5.6 changes: -- added back.patch to patchobj - s/Mf-base -- updated version to 9.5.6 - makefiles/Mf-install.in scheme.1.in c/Makefile.a6nt c/Makefile.i3nt - c/Makefile.ta6nt c/Makefile.ti3nt mats/Mf-a6nt mats/Mf-i3nt - mats/Mf-ta6nt mats/Mf-ti3nt workarea c/scheme.rc s/7.ss - s/cmacros.ss release_notes/release_notes.stex csug/copyright.stex - csug/csug.stex rpm/Makefile pkg/Makefile wininstall/Makefile - wininstall/a6nt.wxs wininstall/i3nt.wxs wininstall/ta6nt.wxs - wininstall/ti3nt.wxs - -9.5.7 changes: -- updated version to 9.5.7 - BUILDING NOTICE makefiles/Mf-install.in scheme.1.in c/Makefile.a6nt - c/Makefile.i3nt c/Makefile.ta6nt c/Makefile.ti3nt mats/Mf-a6nt - mats/Mf-i3nt mats/Mf-ta6nt mats/Mf-ti3nt workarea c/scheme.rc - s/cmacros.ss release_notes/release_notes.stex csug/copyright.stex - csug/csug.stex bintar/Makefile rpm/Makefile pkg/Makefile - wininstall/Makefile wininstall/a6nt.wxs wininstall/i3nt.wxs - wininstall/ta6nt.wxs wininstall/ti3nt.wxs -- fix bug in printf with certain control strings and argument counts - s/format.ss mats/format.ms mats/root-experr-compile-{0,2}-fff - release_notes/release_notes.stex -- updated ftypes to allow native ftypes to be used even if another - non-ftype syntactic binding for the type exists. for instance, if a - syntactic binding for integer-32 is introduced which is not bound to - an ftd, using integer-32 in the context of an ftype will still work. - this change also allows an ftype binding to be created for a native - type by using (define-ftype ), allowing - users to create standard ftype bindings for the native-types if that - is preferred. - s/ftype.ss, mats/ftype.ms -- fix occasional 0xC0000409 STATUS_STACK_BUFFER_OVERRUN crash on 64-bit - Windows from Microsoft's longjmp by implementing our own setjmp/longjmp - c/Makefile.{a6nt,ta6nt} c/Mf-{a6nt,ta6nt} c/a6nt-jump.asm c/externs.h - c/types.h c/version.h release_notes/release_notes.stex -- support Microsoft Visual Studio 2022 on Windows - BUILDING, c/vs.bat, wininstall/locate-vcredist.bat -- make threaded foreign mats more robust - mats/foreign.ms -- fix rational-valued? for numbers with an exceptional real part - s/5_3.ss mats/5_1.ms -- change behavior of mixed exact/inexact arithmetic comparisons in - the range where fixnums have greater precision than flonums. This - makes <=, =, and >= transitive as required by R6RS. (< and > were - already transitive, but the behavior is changed to match.) - s/5_3.ss mats/5_3.ms -- consolidate the $thread-check code in misc.ms and thread.ms, keeping - the thread.ms version of the code since it is more recent - mats/misc.ms mats/thread-check.ss mats/thread.ms -- Replace K&R style function declarations with ANSI style - c/alloc.c c/arm32le.c c/externs.h c/fasl.c c/flushcache.c c/foreign.c - c/gc.c c/gcwrapper.c c/i32le.c c/intern.c c/io.c c/itest.c c/new-io.c - c/number.c c/ppc32.c c/ppc32le.c c/prim.c c/prim5.c c/print.c c/scheme.c - c/schlib.c c/schsig.c c/segment.c c/statics.c c/stats.c c/symbol.c - c/thread.c c/windows.c mats/foreign1.c -- Eliminate PROTO macro from scheme.h - boot/*/scheme.h c/Makefile.* c/alloc.c c/externs.h c/fasl.c c/flushcache.c - c/foreign.c c/gc.c c/gcwrapper.c c/intern.c c/io.c c/new-io.c c/number.c - c/prim.c c/prim5.c c/print.c c/scheme.c c/schlib.c c/schsig.c c/segment.c - c/thread.c mats/foreign3.c s/mkheader.ss -- update lz4 to version 1.9.3 - configure -- update zlib to version 1.2.12 (which fixes CVE-2018-25032) - configure c/Mf-*le - -9.5.8 changes: -- updated version to 9.5.8 - BUILDING NOTICE makefiles/Mf-install.in scheme.1.in c/Makefile.a6nt - c/Makefile.i3nt c/Makefile.ta6nt c/Makefile.ti3nt mats/Mf-a6nt - mats/Mf-i3nt mats/Mf-ta6nt mats/Mf-ti3nt workarea c/scheme.rc s/7.ss - s/cmacros.ss release_notes/release_notes.stex csug/copyright.stex - csug/csug.stex bintar/Makefile rpm/Makefile pkg/Makefile - wininstall/Makefile wininstall/a6nt.wxs wininstall/i3nt.wxs - wininstall/ta6nt.wxs wininstall/ti3nt.wxs newrelease - -9.5.9 changes: -- updated version to 9.5.9 - BUILDING NOTICE makefiles/Mf-install.in scheme.1.in c/Makefile.a6nt - c/Makefile.i3nt c/Makefile.ta6nt c/Makefile.ti3nt mats/Mf-a6nt - mats/Mf-i3nt mats/Mf-ta6nt mats/Mf-ti3nt workarea c/scheme.rc - s/cmacros.ss release_notes/release_notes.stex csug/copyright.stex - csug/csug.stex bintar/Makefile rpm/Makefile pkg/Makefile - wininstall/Makefile wininstall/a6nt.wxs wininstall/i3nt.wxs - wininstall/ta6nt.wxs wininstall/ti3nt.wxs -- fix arm32le compilation systems using musl libc - c/arm32le.c -- added install-docs target for make and corresponding configuration - options: --installdoc, --installcsug, and --installreleasenotes - configure makefiles/Makefile.in -- fixed a bug in `char-` that led to returning a large positive integer - result when the second argument had a value greater than the first. - It now returns a negative number in this situation. - cpnanopass.ss - 5_4.ms root-experr-* patch-* -- fix ppc32 conditional-branch code generation when displacement is - exactly 32764 - s/ppc32.ss -- fix callable floating-point argument allocation on x86 - s/cpnanopass.ss -- corrected signature of multibyte->string and string->multibyte - s/primdata.ss -- fix typos found by Eric Lindblad - c/alloc.c c/compress-io.c c/gc.c c/gcwrapper.c c/new-io.c c/prim5.c - c/schsig.c csug/csug.stex csug/syntax.stex examples/template.ss - mats/4.ms mats/6.ms mats/7.ms mats/8.ms mats/bytevector.ms mats/foreign.ms - mats/io.ms mats/mat.ss mats/misc.ms mats/oop.ms mats/oop.ss mats/profile.ms - mats/record.ms mats/unix.ms s/5_3.ss s/7.ss s/arm32.ss s/base-lang.ss - s/cmacros.ss s/cp0.ss s/cpnanopass.ss s/date.ss s/format.ss s/io.ss - s/mkheader.ss s/np-languages.ss s/pdhtml.ss s/ppc32.ss s/print.ss - s/syntax.ss s/x86.ss s/x86_64.ss -- Unicode 14.0 support - unicode/* s/5_4.ss mats/5_4.ms mats/6.ms -- don't rely on signed integer overflow (UB) in symhash implementation - c/foreign.c -- Propagate immutable versions of "", #(), #vu8() and #vfx() in cp0. - s/cp0.ss s/cpnanopass.ss -- correct mislabeling of some functions as macros and vice versa in - docs + correct name of Slocked_objectp from Sunlocked_objectp - csug/foreign.stex diff --git a/ta6ob/Makefile b/ta6ob/Makefile deleted file mode 100644 index e330fd7..0000000 --- a/ta6ob/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -# Makefile-workarea.in -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -MAKEFLAGS += --no-print-directory -PREFIX= - -.PHONY: build -build: - (cd c && $(MAKE)) - (cd s && $(MAKE) bootstrap) - -.PHONY: install -install: build - $(MAKE) -f Mf-install - -.PHONY: uninstall -uninstall: - $(MAKE) -f Mf-install uninstall - -.PHONY: test -test: build - (cd mats && $(MAKE) allx) - @echo "test run complete. check $(PREFIX)mats/summary for errors." - -.PHONY: coverage -coverage: - rm -f s/bootstrap - (cd c && $(MAKE)) - (cd s && $(MAKE) bootstrap p=t c=t) - (cd mats && $(MAKE) allx c=t) - -.PHONY: bootfiles -bootfiles: build - $(MAKE) -f Mf-boot - -.PHONY: bintar -bintar: build - (cd bintar && $(MAKE)) - -.PHONY: rpm -rpm: bintar - (cd rpm && $(MAKE)) - -.PHONY: pkg -pkg: bintar - (cd pkg && $(MAKE)) - -.PHONY: clean -clean: - rm -f petite.1 scheme.1 - (cd s && $(MAKE) clean) - (cd c && $(MAKE) clean) - (cd mats && $(MAKE) clean) - (cd examples && $(MAKE) clean) - (cd bintar && $(MAKE) clean) - (cd rpm && $(MAKE) clean) - (cd pkg && $(MAKE) clean) - rm -f Make.out diff --git a/ta6ob/Mf-boot b/ta6ob/Mf-boot deleted file mode 100644 index 3d657cd..0000000 --- a/ta6ob/Mf-boot +++ /dev/null @@ -1,28 +0,0 @@ -# Mf-boot.in -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -bootfiles=$(addsuffix .boot, $(shell cd ../boot ; echo *)) - -doit: $(bootfiles) - -%.boot: - ( cd .. ; ./workarea $* xc-$* ) - ( cd ../xc-$*/s ; make -f Mf-cross base=../../ta6ob --jobs=2 m=ta6ob xm=$* ) - for x in `echo scheme.boot petite.boot scheme.h equates.h` ; do\ - if [ ! -h ../xc-$*/boot/$*/$$x ] ; then \ - mv -f ../xc-$*/boot/$*/$$x ../boot/$*/$$x ;\ - fi ;\ - done - rm -rf ../xc-$* diff --git a/ta6ob/Mf-install b/ta6ob/Mf-install deleted file mode 100644 index 578da08..0000000 --- a/ta6ob/Mf-install +++ /dev/null @@ -1,164 +0,0 @@ -# Mf-install.in -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -############################################################################### -# the following variables are set up by configure # -############################################################################### - -m=ta6ob - -# The following variables determine where the executables, boot files, -# example programs, and manual pages are installed. - -# executable directory -InstallBin=/usr/local/bin - -# library directory -InstallLib=/usr/local/lib - -# man page directory -InstallMan=/usr/local/man/man1 - -# installation owner -InstallOwner= - -# installation group -InstallGroup= - -# Files are actually installed at ${TempRoot}${InstallBin}, -# ${TempRoot}${InstallLib}, and ${TempRoot}${InstallMan}. -# This useful for testing the install process and for building -# installation scripts -TempRoot= - -# compress man pages? -GzipManPages=yes - -# executable names -InstallSchemeName=scheme -InstallPetiteName=petite -InstallScriptName=scheme-script - -# Whether to install "kernel.o" or "libkernel.a" -InstallKernelTarget=installkernelobj - -# Maybe install libz.a and liblz4.a by setting to "installzlib" and "installliz4" -InstallZlibTarget= -InstallLZ4Target= - -############################################################################### -# no changes should be needed below this point # -############################################################################### - -Version=csv9.5.9 -Include=boot/$m -PetiteBoot=boot/$m/petite.boot -SchemeBoot=boot/$m/scheme.boot -Revision=boot/$m/revision -Scheme=bin/$m/scheme -Petite=bin/$m/petite -InstallLibExamples=${InstallLib}/${Version}/examples -InstallLibBin=${InstallLib}/${Version}/$m - -Bin=${TempRoot}${InstallBin} -Lib=${TempRoot}${InstallLib}/${Version} -LibExamples=${TempRoot}${InstallLibExamples} -LibBin=${TempRoot}${InstallLibBin} -Man=${TempRoot}${InstallMan} -PetitePath=${Bin}/${InstallPetiteName} -SchemePath=${Bin}/${InstallSchemeName} -SchemeScriptPath=${Bin}/${InstallScriptName} - -install: bininstall libbininstall maninstall liblibinstall ${InstallKernelTarget} - -uninstall: - rm -rf ${Lib} - rm -f ${PetitePath} - rm -f ${SchemePath} - rm -f ${SchemeScriptPath} - rm -f ${Man}/${InstallPetiteName}.1{,.gz} - rm -f ${Man}/${InstallSchemeName}.1{,.gz} - -scheme.1 petite.1: scheme.1.in - sed -e "s;{InstallBin};${InstallBin};g" \ - -e "s;{InstallLibExamples};${InstallLibExamples};g" \ - -e "s;{InstallLibBin};${InstallLibBin};g" \ - -e "s;{InstallPetiteName};${InstallPetiteName};g" \ - -e "s;{InstallSchemeName};${InstallSchemeName};g" \ - -e "s;{InstallScriptName};${InstallScriptName};g" \ - scheme.1.in > $@ - -############################################################################### -# no useful external targets below this line # -############################################################################### - -I=./installsh -o "${InstallOwner}" -g "${InstallGroup}" - -bininstall: ${Bin} - $I -m 555 ${Scheme} ${SchemePath} - ln -f ${SchemePath} ${PetitePath} - ln -f ${SchemePath} ${SchemeScriptPath} - -libbininstall: ${LibBin} - $I -m 444 ${PetiteBoot} ${LibBin}/petite.boot - if [ "${InstallPetiteName}" != "petite" ]; then\ - rm -f ${LibBin}/${InstallPetiteName}.boot;\ - ln -f ${LibBin}/petite.boot ${LibBin}/${InstallPetiteName}.boot;\ - fi - $I -m 444 ${SchemeBoot} ${LibBin}/scheme.boot;\ - if [ "${InstallSchemeName}" != "scheme" ]; then\ - rm -f ${LibBin}/${InstallSchemeName}.boot;\ - ln -f ${LibBin}/scheme.boot ${LibBin}/${InstallSchemeName}.boot;\ - fi - ln -f ${LibBin}/scheme.boot ${LibBin}/${InstallScriptName}.boot; - $I -m 444 ${Include}/main.o ${LibBin} - $I -m 444 ${Include}/scheme.h ${LibBin} - $I -m 444 ${Revision} ${LibBin}/revision - -installkernelobj: ${LibBin} - $I -m 444 ${Include}/kernel.o ${LibBin} - -installkernellib: ${LibBin} ${InstallZlibTarget} ${InstallLZ4Target} - $I -m 444 ${Include}/libkernel.a ${LibBin} - -installzlib: ${LibBin} - $I -m 444 zlib/libz.a ${LibBin} - -installlz4: ${LibBin} - $I -m 444 lz4/lib/liblz4.a ${LibBin} - -maninstall: scheme.1 petite.1 ${Man} - $I -m 444 scheme.1 ${Man}/${InstallSchemeName}.1 - if [ ${GzipManPages} = yes ] ; then gzip -f ${Man}/${InstallSchemeName}.1 ; fi - $I -m 444 petite.1 ${Man}/${InstallPetiteName}.1 - if [ ${GzipManPages} = yes ] ; then gzip -f ${Man}/${InstallPetiteName}.1 ; fi - -liblibinstall: ${LibExamples} - $I -m 444 examples/* ${LibExamples} - -${Lib}: - $I -d -m 755 ${Lib} - -${LibBin}: ${Lib} - $I -d -m 755 ${LibBin} - -${LibExamples}: ${Lib} - $I -d -m 755 ${LibExamples} - -${Bin}: - $I -d -m 755 ${Bin} - -${Man}: - $I -d -m 755 ${Man} diff --git a/ta6ob/bin/petite b/ta6ob/bin/petite deleted file mode 100755 index 44364cd..0000000 Binary files a/ta6ob/bin/petite and /dev/null differ diff --git a/ta6ob/bin/scheme b/ta6ob/bin/scheme deleted file mode 100755 index 44364cd..0000000 Binary files a/ta6ob/bin/scheme and /dev/null differ diff --git a/ta6ob/bin/ta6ob/petite b/ta6ob/bin/ta6ob/petite deleted file mode 100755 index 44364cd..0000000 Binary files a/ta6ob/bin/ta6ob/petite and /dev/null differ diff --git a/ta6ob/bin/ta6ob/scheme b/ta6ob/bin/ta6ob/scheme deleted file mode 100755 index 44364cd..0000000 Binary files a/ta6ob/bin/ta6ob/scheme and /dev/null differ diff --git a/ta6ob/bintar/Makefile b/ta6ob/bintar/Makefile deleted file mode 100644 index a928206..0000000 --- a/ta6ob/bintar/Makefile +++ /dev/null @@ -1,86 +0,0 @@ -# Makefile -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -version = 9.5.9 -m := $(shell find ../bin/* -type d | xargs basename) - -R = csv$(version) -TARBALL = $(R)-$(m).tar.gz - -CONTENTS=\ - $(R)/LICENSE\ - $(R)/NOTICE\ - $(R)/scheme.1.in\ - $(R)/installsh\ - $(R)/Makefile\ - $(R)/examples\ - $(R)/boot\ - $(R)/bin - -$(TARBALL): $(CONTENTS) - ( BROKEN=`find -L $R -type l` ; \ - if test -n "$$BROKEN" ; then \ - echo "Error: missing $(BROKEN)" ; \ - exit 1 ; \ - fi ) - tar -czhf $(TARBALL) $R - rm -rf $(R) - -$(R)/LICENSE: $(R) - ( cd $(R) ; ln -s ../../../LICENSE . ) - -$(R)/NOTICE: $(R) - ( cd $(R) ; ln -s ../../../NOTICE . ) - -$(R)/scheme.1.in: $(R) - ( cd $(R) ; ln -s ../../scheme.1.in . ) - -$(R)/installsh: $(R) - ( cd $(R) ; ln -s ../../installsh . ) - -$(R)/Makefile: $(R) - ( cd $(R) ; ln -s ../../Mf-install Makefile ) - -$(R)/examples: $(R) - ( cd $(R) ; ln -s ../../examples . ) - -$(R)/boot: $(R) - mkdir -p $(R)/boot/$(m) - ( cd $(R)/boot/$(m) ; ln -s ../../../../boot/$(m)/{scheme.h,petite.boot,scheme.boot,revision} . ) - case $(m) in \ - *nt) \ - ( cd $R/boot/$(m) ; ln -s ../../../../boot/$(m)/{csv959md.lib,csv959mt.lib,mainmd.obj,mainmt.obj,scheme.res} . ) \ - ;; \ - *) \ - ( cd $R/boot/$(m) ; ln -s ../../../../boot/$(m)/{main.o,kernel.o} . ) \ - ;; \ - esac - -$(R)/bin: $(R) - mkdir -p $(R)/bin/$(m) - case $(m) in \ - *nt) \ - ( cd $R/bin/$(m) ; ln -s ../../../../bin/$(m)/{scheme.exe,csv959.dll,csv959.lib,vcruntime140.lib} . ) \ - ;; \ - *) \ - ( cd $R/bin/$(m) ; ln -s ../../../../bin/$(m)/scheme . ) \ - ;; \ - esac - -$(R): - mkdir $(R) - -clean: - rm -rf $(R) $(TARBALL) diff --git a/ta6ob/boot/ta6ob/equates.h b/ta6ob/boot/ta6ob/equates.h deleted file mode 100644 index ba38a96..0000000 --- a/ta6ob/boot/ta6ob/equates.h +++ /dev/null @@ -1,993 +0,0 @@ -/* equates.h for Chez Scheme Version 9.5.9 */ - -/* Do not edit this file. It is automatically generated and */ -/* specifically tailored to the version of Chez Scheme named */ -/* above. Always be certain that you have the correct version */ -/* of this file for the version of Chez Scheme you are using. */ - -/* Warning: Some macros may evaluate arguments more than once. */ - -/* Integer typedefs */ -typedef char I8; -typedef unsigned char U8; -typedef short I16; -typedef unsigned short U16; -typedef int I32; -typedef unsigned int U32; -typedef long I64; -typedef unsigned long U64; - -/* constants from cmacros.ss */ -#define $c_func_closure_index 0x4 -#define $c_func_closure_record_index 0x3 -#define $c_func_code_object_index 0x2 -#define $c_func_code_record_index 0x1 -#define COMPRESS_FORMAT_BITS 0x3 -#define COMPRESS_GZIP 0x0 -#define COMPRESS_HIGH 0x3 -#define COMPRESS_LOW 0x1 -#define COMPRESS_LZ4 0x1 -#define COMPRESS_MAX 0x4 -#define COMPRESS_MEDIUM 0x2 -#define COMPRESS_MIN 0x0 -#define ERROR_CALL_ARGUMENT_COUNT 0x4 -#define ERROR_CALL_NONPROCEDURE 0x3 -#define ERROR_CALL_NONPROCEDURE_SYMBOL 0x2 -#define ERROR_CALL_UNBOUND 0x1 -#define ERROR_MVLET 0x8 -#define ERROR_NONCONTINUABLE_INTERRUPT 0x6 -#define ERROR_OTHER 0x0 -#define ERROR_RESET 0x5 -#define ERROR_VALUES 0x7 -#define OPEN_ERROR_EXISTS 0x2 -#define OPEN_ERROR_EXISTSNOT 0x3 -#define OPEN_ERROR_OTHER 0x0 -#define OPEN_ERROR_PROTECTION 0x1 -#define PORT_FLAG_BINARY 0x400 -#define PORT_FLAG_BLOCK_BUFFERED 0x20000 -#define PORT_FLAG_BOL 0x8000 -#define PORT_FLAG_CHAR_POSITIONS 0x100000 -#define PORT_FLAG_CLOSED 0x800 -#define PORT_FLAG_COMPRESSED 0x2000 -#define PORT_FLAG_EOF 0x10000 -#define PORT_FLAG_EXCLUSIVE 0x4000 -#define PORT_FLAG_FILE 0x1000 -#define PORT_FLAG_FOLD_CASE 0x400000 -#define PORT_FLAG_INPUT 0x100 -#define PORT_FLAG_INPUT_MODE 0x80000 -#define PORT_FLAG_LINE_BUFFERED 0x40000 -#define PORT_FLAG_NO_FOLD_CASE 0x800000 -#define PORT_FLAG_OUTPUT 0x200 -#define PORT_FLAG_R6RS 0x200000 -#define SAPPEND 0x3 -#define SDEFAULT 0x4 -#define SEOF -0x1 -#define SERROR 0x0 -#define SICONV_DUNNO 0x0 -#define SICONV_INCOMPLETE 0x2 -#define SICONV_INVALID 0x1 -#define SICONV_NOROOM 0x3 -#define SREPLACE 0x2 -#define STRVNCATE 0x1 -#define address_bits 0x40 -#define alloc_waste_maximum 0x800 -#define annotation_all 0x3 -#define annotation_debug 0x1 -#define annotation_profile 0x2 -#define architecture x86_64 -#define asm_arg_reg_cnt 0x3 -#define asm_arg_reg_max 0x5 -#define bigit_bits 0x20 -#define bigit_bytes 0x4 -#define bignum_data_disp 0x9 -#define bignum_length_factor 0x40 -#define bignum_length_offset 0x6 -#define bignum_sign_offset 0x5 -#define bignum_type_disp 0x1 -#define black_hole (ptr)0x46 -#define box_ref_disp 0x9 -#define box_type_disp 0x1 -#define byte_alignment 0x10 -#define byte_constant_mask 0xFFFFFFFFFFFFFFFF -#define bytes_per_card 0x200 -#define bytes_per_segment 0x4000 -#define bytevector_data_disp 0x9 -#define bytevector_immutable_flag 0x4 -#define bytevector_length_factor 0x8 -#define bytevector_length_offset 0x3 -#define bytevector_type_disp 0x1 -#define c_entry_name_vector #(thread-context get-thread-context handle-apply-overflood handle-docall-error handle-overflow handle-overflood handle-nonprocedure-symbol thread-list split-and-resize raw-collect-cond raw-tc-mutex activate-thread deactivate-thread unactivate-thread handle-values-error handle-mvlet-error handle-arg-error foreign-entry install-library-entry get-more-room scan-remembered-set instantiate-code-object Sreturn Scall-one-result Scall-any-results) -#define c_entry_vector_size 0x19 -#define cached_stack_link_disp 0x8 -#define cached_stack_size_disp 0x0 -#define card_offset_bits 0x9 -#define cards_per_segment 0x20 -#define char_data_offset 0x8 -#define char_factor 0x100 -#define closure_code_disp 0x3 -#define closure_data_disp 0xB -#define code_arity_mask_disp 0x21 -#define code_closure_length_disp 0x29 -#define code_data_disp 0x41 -#define code_flag_continuation 0x2 -#define code_flag_guardian 0x8 -#define code_flag_system 0x1 -#define code_flag_template 0x4 -#define code_flags_offset 0x8 -#define code_info_disp 0x31 -#define code_length_disp 0x9 -#define code_name_disp 0x19 -#define code_pinfos_disp 0x39 -#define code_reloc_disp 0x11 -#define code_type_disp 0x1 -#define collect_interrupt_index 0x1 -#define continuation_code_disp 0x3 -#define continuation_link_disp 0x23 -#define continuation_return_address_disp 0x2B -#define continuation_stack_clength_disp 0x1B -#define continuation_stack_disp 0xB -#define continuation_stack_length_disp 0x13 -#define continuation_winders_disp 0x33 -#define countof_bignum 0x5 -#define countof_box 0x9 -#define countof_bytevector 0x15 -#define countof_closure 0x3 -#define countof_code 0xB -#define countof_continuation 0x4 -#define countof_ephemeron 0x19 -#define countof_exactnum 0x8 -#define countof_flonum 0x2 -#define countof_fxvector 0x14 -#define countof_guardian 0x17 -#define countof_inexactnum 0x7 -#define countof_locked 0x16 -#define countof_oblist 0x18 -#define countof_pair 0x0 -#define countof_port 0xA -#define countof_ratnum 0x6 -#define countof_relocation_table 0x10 -#define countof_rtd_counts 0xE -#define countof_stack 0xF -#define countof_string 0x13 -#define countof_symbol 0x1 -#define countof_thread 0xC -#define countof_tlc 0xD -#define countof_types 0x1A -#define countof_vector 0x12 -#define countof_weakpair 0x11 -#define default_collect_trip_bytes 0x800000 -#define default_heap_reserve_ratio 1.0 -#define default_max_nonstatic_generation 0x4 -#define default_stack_size 0xFFF0 -#define default_timer_ticks 0x3E8 -#define dtvec_hour 0x3 -#define dtvec_isdst 0x9 -#define dtvec_mday 0x4 -#define dtvec_min 0x2 -#define dtvec_mon 0x5 -#define dtvec_nsec 0x0 -#define dtvec_sec 0x1 -#define dtvec_size 0xC -#define dtvec_tzname 0xB -#define dtvec_tzoff 0xA -#define dtvec_wday 0x7 -#define dtvec_yday 0x8 -#define dtvec_year 0x6 -#define ephemeron_car_disp 0x7 -#define ephemeron_cdr_disp 0xF -#define ephemeron_next_disp 0x17 -#define ephemeron_trigger_next_disp 0x1F -#define eq_hashtable_subtype_ephemeron 0x2 -#define eq_hashtable_subtype_normal 0x0 -#define eq_hashtable_subtype_weak 0x1 -#define exactnum_imag_disp 0x11 -#define exactnum_real_disp 0x9 -#define exactnum_type_disp 0x1 -#define fasl_fld_double 0xA -#define fasl_fld_i16 0x2 -#define fasl_fld_i24 0x3 -#define fasl_fld_i32 0x4 -#define fasl_fld_i40 0x5 -#define fasl_fld_i48 0x6 -#define fasl_fld_i56 0x7 -#define fasl_fld_i64 0x8 -#define fasl_fld_ptr 0x0 -#define fasl_fld_single 0x9 -#define fasl_fld_u8 0x1 -#define fasl_header #vu8(0 0 0 0 99 104 101 122) -#define fasl_type_base_rtd 0x1A -#define fasl_type_box 0x1 -#define fasl_type_bytevector 0x1D -#define fasl_type_closure 0x6 -#define fasl_type_code 0xB -#define fasl_type_entry 0xD -#define fasl_type_ephemeron 0x1C -#define fasl_type_eq_hashtable 0x1F -#define fasl_type_exactnum 0x14 -#define fasl_type_flonum 0x8 -#define fasl_type_fxvector 0x1B -#define fasl_type_gensym 0x13 -#define fasl_type_graph 0x10 -#define fasl_type_graph_def 0x11 -#define fasl_type_graph_ref 0x12 -#define fasl_type_gzip 0x2B -#define fasl_type_header 0x0 -#define fasl_type_immediate 0xC -#define fasl_type_immutable_box 0x29 -#define fasl_type_immutable_bytevector 0x28 -#define fasl_type_immutable_fxvector 0x27 -#define fasl_type_immutable_string 0x26 -#define fasl_type_immutable_vector 0x25 -#define fasl_type_inexactnum 0x5 -#define fasl_type_large_integer 0xA -#define fasl_type_library 0xE -#define fasl_type_library_code 0xF -#define fasl_type_lz4 0x2C -#define fasl_type_pair 0x7 -#define fasl_type_ratnum 0x3 -#define fasl_type_record 0x17 -#define fasl_type_revisit 0x23 -#define fasl_type_rtd 0x18 -#define fasl_type_small_integer 0x19 -#define fasl_type_string 0x9 -#define fasl_type_symbol 0x2 -#define fasl_type_symbol_hashtable 0x20 -#define fasl_type_uncompressed 0x2A -#define fasl_type_vector 0x4 -#define fasl_type_visit 0x22 -#define fasl_type_visit_revisit 0x24 -#define fasl_type_weak_pair 0x1E -#define fixnum_bits 0x3D -#define fixnum_factor 0x8 -#define fixnum_offset 0x3 -#define fld_byte_index 0x4 -#define fld_mutablep_index 0x2 -#define fld_name_index 0x1 -#define fld_type_index 0x3 -#define flonum_data_disp 0x6 -#define forward_address_disp 0x8 -#define forward_marker (ptr)0x2E -#define forward_marker_disp 0x0 -#define ftype_guardian_rep (ptr)0x56 -#define fxvector_data_disp 0x9 -#define fxvector_immutable_flag 0x8 -#define fxvector_length_factor 0x10 -#define fxvector_length_offset 0x4 -#define fxvector_type_disp 0x1 -#define guardian_entry_next_disp 0x18 -#define guardian_entry_obj_disp 0x0 -#define guardian_entry_rep_disp 0x8 -#define guardian_entry_tconc_disp 0x10 -#define hashtable_default_size 0x8 -#define header_size_bignum 0x8 -#define header_size_bytevector 0x8 -#define header_size_closure 0x8 -#define header_size_code 0x40 -#define header_size_fxvector 0x8 -#define header_size_record 0x8 -#define header_size_reloc_table 0x10 -#define header_size_string 0x8 -#define header_size_vector 0x8 -#define ignore_event_flag 0x0 -#define inexactnum_imag_disp 0x19 -#define inexactnum_pad_disp 0x9 -#define inexactnum_real_disp 0x11 -#define inexactnum_type_disp 0x1 -#define int_bits 0x20 -#define integer_divide_instruction 1 -#define keyboard_interrupt_index 0x3 -#define library_entry_vector_size 0x210 -#define libspec_closure_index 0xD -#define libspec_does_not_expect_headroom_index 0x0 -#define libspec_error_index 0xE -#define libspec_fake_index 0x10 -#define libspec_flags_index 0x2 -#define libspec_has_does_not_expect_headroom_version_index 0xF -#define libspec_index_base_offset 0x1 -#define libspec_index_base_size 0x9 -#define libspec_index_offset 0x0 -#define libspec_index_size 0xA -#define libspec_interface_offset 0xA -#define libspec_interface_size 0x3 -#define libspec_name_index 0x1 -#define log2_ptr_bytes 0x3 -#define long_bits 0x40 -#define long_long_bits 0x40 -#define machine_type 0x10 -#define machine_type_a6fb 0x15 -#define machine_type_a6le 0xB -#define machine_type_a6nb 0x19 -#define machine_type_a6nt 0x1B -#define machine_type_a6ob 0xF -#define machine_type_a6osx 0xD -#define machine_type_a6s2 0x11 -#define machine_type_alist ((0 . any) (1 . i3le) (2 . ti3le) (3 . i3nt) (4 . ti3nt) (5 . i3fb) (6 . ti3fb) (7 . i3ob) (8 . ti3ob) (9 . i3osx) (10 . ti3osx) (11 . a6le) (12 . ta6le) (13 . a6osx) (14 . ta6osx) (15 . a6ob) (16 . ta6ob) (17 . a6s2) (18 . ta6s2) (19 . i3s2) (20 . ti3s2) (21 . a6fb) (22 . ta6fb) (23 . i3nb) (24 . ti3nb) (25 . a6nb) (26 . ta6nb) (27 . a6nt) (28 . ta6nt) (29 . i3qnx) (30 . ti3qnx) (31 . arm32le) (32 . tarm32le) (33 . ppc32le) (34 . tppc32le)) -#define machine_type_any 0x0 -#define machine_type_arm32le 0x1F -#define machine_type_i3fb 0x5 -#define machine_type_i3le 0x1 -#define machine_type_i3nb 0x17 -#define machine_type_i3nt 0x3 -#define machine_type_i3ob 0x7 -#define machine_type_i3osx 0x9 -#define machine_type_i3qnx 0x1D -#define machine_type_i3s2 0x13 -#define machine_type_limit 0x23 -#define machine_type_name ta6ob -#define machine_type_ppc32le 0x21 -#define machine_type_ta6fb 0x16 -#define machine_type_ta6le 0xC -#define machine_type_ta6nb 0x1A -#define machine_type_ta6nt 0x1C -#define machine_type_ta6ob 0x10 -#define machine_type_ta6osx 0xE -#define machine_type_ta6s2 0x12 -#define machine_type_tarm32le 0x20 -#define machine_type_ti3fb 0x6 -#define machine_type_ti3le 0x2 -#define machine_type_ti3nb 0x18 -#define machine_type_ti3nt 0x4 -#define machine_type_ti3ob 0x8 -#define machine_type_ti3osx 0xA -#define machine_type_ti3qnx 0x1E -#define machine_type_ti3s2 0x14 -#define machine_type_tppc32le 0x22 -#define mask_bignum 0x1F -#define mask_bignum_sign 0x20 -#define mask_binary_input_port 0x5FF -#define mask_binary_output_port 0x6FF -#define mask_binary_port 0x4FF -#define mask_boolean 0xF7 -#define mask_box 0x7F -#define mask_bwp 0xFFFFFFFFFFFFFFFF -#define mask_bytevector 0x3 -#define mask_char 0xFF -#define mask_closure 0x7 -#define mask_code 0xFF -#define mask_continuation_code 0x2FF -#define mask_eof 0xFFFFFFFFFFFFFFFF -#define mask_exactnum 0xFFFFFFFFFFFFFFFF -#define mask_false 0xFFFFFFFFFFFFFFFF -#define mask_fixnum 0x7 -#define mask_flonum 0x7 -#define mask_fxvector 0x7 -#define mask_guardian_code 0x8FF -#define mask_immediate 0x7 -#define mask_inexactnum 0xFFFFFFFFFFFFFFFF -#define mask_input_port 0x1FF -#define mask_mutable_box 0xFFFFFFFFFFFFFFFF -#define mask_mutable_bytevector 0x7 -#define mask_mutable_fxvector 0xF -#define mask_mutable_string 0xF -#define mask_mutable_vector 0xF -#define mask_nil 0xFFFFFFFFFFFFFFFF -#define mask_octet -0x7F9 -#define mask_other_number 0xF -#define mask_output_port 0x2FF -#define mask_pair 0x7 -#define mask_port 0xFF -#define mask_ratnum 0xFFFFFFFFFFFFFFFF -#define mask_record 0x7 -#define mask_rtd_counts 0xFFFFFFFFFFFFFFFF -#define mask_signed_bignum 0x3F -#define mask_string 0x7 -#define mask_symbol 0x7 -#define mask_system_code 0x1FF -#define mask_textual_input_port 0x5FF -#define mask_textual_output_port 0x6FF -#define mask_textual_port 0x4FF -#define mask_thread 0xFFFFFFFFFFFFFFFF -#define mask_tlc 0xFFFFFFFFFFFFFFFF -#define mask_typed_object 0x7 -#define mask_unbound 0xFFFFFFFFFFFFFFFF -#define mask_vector 0x7 -#define max_float_alignment 0x8 -#define max_integer_alignment 0x8 -#define max_real_space 0xB -#define max_space 0xC -#define max_sweep_space 0xA -#define maximum_bignum_length (iptr)0x3FFFFFFFFFFFFFF -#define maximum_bytevector_length (iptr)0xFFFFFFFFFFFFFFF -#define maximum_fxvector_length (iptr)0xFFFFFFFFFFFFFFF -#define maximum_interrupt_index 0x4 -#define maximum_string_length (iptr)0xFFFFFFFFFFFFFFF -#define maximum_vector_length (iptr)0xFFFFFFFFFFFFFFF -#define minimum_segment_request 0x80 -#define most_negative_fixnum (iptr)-0x1000000000000000 -#define most_positive_fixnum (iptr)0xFFFFFFFFFFFFFFF -#define native_endianness little -#define one_shot_headroom 0xC00 -#define ordinary_type_bits 0x8 -#define pair_car_disp 0x7 -#define pair_cdr_disp 0xF -#define pair_shift 0x4 -#define port_flag_binary 0x4 -#define port_flag_block_buffered 0x200 -#define port_flag_bol 0x80 -#define port_flag_char_positions 0x1000 -#define port_flag_closed 0x8 -#define port_flag_compressed 0x20 -#define port_flag_eof 0x100 -#define port_flag_exclusive 0x40 -#define port_flag_file 0x10 -#define port_flag_fold_case 0x4000 -#define port_flag_input 0x1 -#define port_flag_input_mode 0x800 -#define port_flag_line_buffered 0x400 -#define port_flag_no_fold_case 0x8000 -#define port_flag_output 0x2 -#define port_flag_r6rs 0x2000 -#define port_flags_offset 0x8 -#define port_handler_disp 0x9 -#define port_ibuffer_disp 0x39 -#define port_icount_disp 0x19 -#define port_ilast_disp 0x31 -#define port_info_disp 0x41 -#define port_name_disp 0x49 -#define port_obuffer_disp 0x29 -#define port_ocount_disp 0x11 -#define port_olast_disp 0x21 -#define port_type_disp 0x1 -#define prelex_is_flags_offset 0x8 -#define prelex_is_mask 0xFF00 -#define prelex_sticky_mask 0xFF -#define prelex_was_flags_offset 0x10 -#define primary_type_bits 0x3 -#define ptr_bits 0x40 -#define ptr_bytes 0x8 -#define ptrdiff_t_bits 0x40 -#define ratnum_denominator_disp 0x11 -#define ratnum_numerator_disp 0x9 -#define ratnum_type_disp 0x1 -#define real_space_alist ((new . 0) (impure . 1) (symbol . 2) (port . 3) (weakpair . 4) (ephemeron . 5) (pure . 6) (continuation . 7) (code . 8) (pure-typed-object . 9) (impure-record . 10) (data . 11)) -#define record_data_disp 0x9 -#define record_type_counts_disp 0x49 -#define record_type_disp 0x1 -#define record_type_flags_disp 0x39 -#define record_type_flds_disp 0x31 -#define record_type_mpm_disp 0x21 -#define record_type_name_disp 0x29 -#define record_type_parent_disp 0x9 -#define record_type_pm_disp 0x19 -#define record_type_size_disp 0x11 -#define record_type_type_disp 0x1 -#define record_type_uid_disp 0x41 -#define reloc_abs 0x0 -#define reloc_code_offset_index 0x3 -#define reloc_code_offset_mask 0x3FFFFFF -#define reloc_code_offset_offset 0x4 -#define reloc_extended_format 0x1 -#define reloc_item_offset_index 0x2 -#define reloc_item_offset_mask 0x3FFFFFF -#define reloc_item_offset_offset 0x1E -#define reloc_longp_index 0x4 -#define reloc_table_code_disp 0x8 -#define reloc_table_data_disp 0x10 -#define reloc_table_size_disp 0x0 -#define reloc_type_index 0x1 -#define reloc_type_mask 0x7 -#define reloc_type_offset 0x1 -#define reloc_x86_64_call 0x1 -#define reloc_x86_64_jump 0x2 -#define return_address_frame_size_disp -0x10 -#define return_address_livemask_disp -0x20 -#define return_address_mv_return_address_disp -0x8 -#define return_address_toplink_disp -0x18 -#define rp_header_frame_size_disp 0x10 -#define rp_header_livemask_disp 0x0 -#define rp_header_mv_return_address_disp 0x18 -#define rp_header_toplink_disp 0x8 -#define rtd_counts_data_disp 0x11 -#define rtd_counts_timestamp_disp 0x9 -#define rtd_counts_type_disp 0x1 -#define rtd_generative 0x1 -#define rtd_opaque 0x2 -#define rtd_sealed 0x4 -#define sbwp (ptr)0x4E -#define scaled_shot_1_shot_flag -0x8 -#define scheme_version 0x90509 -#define segment_card_offset_bits 0x5 -#define segment_offset_bits 0xE -#define segment_t1_bits 0x10 -#define segment_t2_bits 0x11 -#define segment_t3_bits 0x11 -#define segment_table_levels 0x3 -#define seof (ptr)0x36 -#define sfalse (ptr)0x6 -#define short_bits 0x10 -#define signal_interrupt_index 0x4 -#define size_box 0x10 -#define size_cached_stack 0x10 -#define size_continuation 0x40 -#define size_ephemeron 0x20 -#define size_exactnum 0x20 -#define size_flonum 0x10 -#define size_forward 0x10 -#define size_guardian_entry 0x20 -#define size_inexactnum 0x20 -#define size_pair 0x10 -#define size_port 0x50 -#define size_ratnum 0x20 -#define size_record_type 0x50 -#define size_rp_header 0x20 -#define size_rtd_counts 0x810 -#define size_symbol 0x30 -#define size_tc 0x2C0 -#define size_thread 0x10 -#define size_tlc 0x20 -#define size_typed_object 0x10 -#define size_t_bits 0x40 -#define snil (ptr)0x26 -#define space_char_list (#\n #\i #\x #\q #\w #\e #\p #\k #\c #\r #\s #\d #\e) -#define space_cname_list ("new" "impure" "symbol" "port" "weakpr" "emph" "pure" "cont" "code" "p-tobj" "ip-rec" "data" "empty") -#define space_code 0x8 -#define space_continuation 0x7 -#define space_data 0xB -#define space_empty 0xC -#define space_ephemeron 0x5 -#define space_impure 0x1 -#define space_impure_record 0xA -#define space_locked 0x20 -#define space_new 0x0 -#define space_old 0x40 -#define space_port 0x3 -#define space_pure 0x6 -#define space_pure_typed_object 0x9 -#define space_symbol 0x2 -#define space_weakpair 0x4 -#define stack_frame_limit 0x200 -#define stack_slop 0x400 -#define static_generation 0xFF -#define string_char_bits 0x20 -#define string_char_bytes 0x4 -#define string_char_offset 0x2 -#define string_data_disp 0x9 -#define string_immutable_flag 0x8 -#define string_length_factor 0x10 -#define string_length_offset 0x4 -#define string_type_disp 0x1 -#define strue (ptr)0xE -#define sunbound (ptr)0x1E -#define svoid (ptr)0x3E -#define symbol_hash_disp 0x2D -#define symbol_name_disp 0x1D -#define symbol_plist_disp 0x15 -#define symbol_pvalue_disp 0xD -#define symbol_splist_disp 0x25 -#define symbol_value_disp 0x5 -#define tc_DSTBV_disp 0x2A8 -#define tc_SRCBV_disp 0x2B0 -#define tc_U_disp 0x160 -#define tc_V_disp 0x168 -#define tc_W_disp 0x170 -#define tc_X_disp 0x178 -#define tc_Y_disp 0x180 -#define tc_ac0_disp 0x28 -#define tc_ac1_disp 0x30 -#define tc_active_disp 0x134 -#define tc_alloc_counter_disp 0x298 -#define tc_ap_disp 0x50 -#define tc_arg_regs_disp 0x0 -#define tc_block_counter_disp 0x1D8 -#define tc_cchain_disp 0x120 -#define tc_code_ranges_to_flush_disp 0x128 -#define tc_compile_profile_disp 0x230 -#define tc_compress_format_disp 0x278 -#define tc_compress_level_disp 0x280 -#define tc_cp_disp 0x40 -#define tc_current_error_disp 0x1D0 -#define tc_current_input_disp 0x1C0 -#define tc_current_mso_disp 0x1E8 -#define tc_current_output_disp 0x1C8 -#define tc_default_record_equal_procedure_disp 0x268 -#define tc_default_record_hash_procedure_disp 0x270 -#define tc_disable_count_disp 0x198 -#define tc_eap_disp 0x58 -#define tc_esp_disp 0x48 -#define tc_fxfirst_bit_set_bv_disp 0x200 -#define tc_fxlength_bv_disp 0x1F8 -#define tc_generate_inspector_information_disp 0x238 -#define tc_generate_procedure_source_information_disp 0x240 -#define tc_generate_profile_forms_disp 0x248 -#define tc_guardian_entries_disp 0x118 -#define tc_instr_counter_disp 0x290 -#define tc_keyboard_interrupt_pending_disp 0x1B0 -#define tc_lz4_out_buffer_disp 0x288 -#define tc_meta_level_disp 0x228 -#define tc_null_immutable_bytevector_disp 0x218 -#define tc_null_immutable_fxvector_disp 0x210 -#define tc_null_immutable_string_disp 0x220 -#define tc_null_immutable_vector_disp 0x208 -#define tc_optimize_level_disp 0x250 -#define tc_parameters_disp 0x2A0 -#define tc_random_seed_disp 0x130 -#define tc_real_eap_disp 0x90 -#define tc_ret_disp 0x60 -#define tc_scheme_stack_disp 0x138 -#define tc_scheme_stack_size_disp 0x150 -#define tc_sfd_disp 0x1E0 -#define tc_sfp_disp 0x38 -#define tc_signal_interrupt_pending_disp 0x1A0 -#define tc_signal_interrupt_queue_disp 0x1A8 -#define tc_something_pending_disp 0x188 -#define tc_stack_cache_disp 0x140 -#define tc_stack_link_disp 0x148 -#define tc_subset_mode_disp 0x258 -#define tc_suppress_primitive_inlining_disp 0x260 -#define tc_target_machine_disp 0x1F0 -#define tc_td_disp 0x88 -#define tc_threadno_disp 0x1B8 -#define tc_timer_ticks_disp 0x190 -#define tc_trap_disp 0x68 -#define tc_ts_disp 0x80 -#define tc_virtual_registers_disp 0x98 -#define tc_winders_disp 0x158 -#define tc_xp_disp 0x70 -#define tc_yp_disp 0x78 -#define thread_tc_disp 0x9 -#define thread_type_disp 0x1 -#define time_collector_cpu 0x5 -#define time_collector_real 0x6 -#define time_duration 0x2 -#define time_monotonic 0x3 -#define time_process 0x0 -#define time_t_bits 0x40 -#define time_thread 0x1 -#define time_utc 0x4 -#define timer_interrupt_index 0x2 -#define tlc_ht_disp 0x11 -#define tlc_keyval_disp 0x9 -#define tlc_next_disp 0x19 -#define tlc_type_disp 0x1 -#define type_bignum 0x6 -#define type_binary_input_port 0x51E -#define type_binary_output_port 0x61E -#define type_binary_port 0x41E -#define type_boolean 0x6 -#define type_box 0xE -#define type_bytevector 0x1 -#define type_char 0x16 -#define type_closure 0x5 -#define type_code 0x3E -#define type_continuation_code 0x23E -#define type_exactnum 0x56 -#define type_fixnum 0x0 -#define type_flonum 0x2 -#define type_fxvector 0x3 -#define type_guardian_code 0x83E -#define type_immediate 0x6 -#define type_immutable_box 0x8E -#define type_immutable_bytevector 0x5 -#define type_immutable_fxvector 0xB -#define type_immutable_string 0xA -#define type_immutable_vector 0x8 -#define type_inexactnum 0x36 -#define type_input_port 0x11E -#define type_io_port 0x31E -#define type_mutable_box 0xE -#define type_mutable_bytevector 0x1 -#define type_mutable_fxvector 0x3 -#define type_mutable_string 0x2 -#define type_mutable_vector 0x0 -#define type_negative_bignum 0x26 -#define type_octet 0x0 -#define type_other_number 0x6 -#define type_output_port 0x21E -#define type_pair 0x1 -#define type_port 0x1E -#define type_positive_bignum 0x6 -#define type_ratnum 0x16 -#define type_record 0x7 -#define type_rtd_counts 0x6E -#define type_string 0x2 -#define type_symbol 0x3 -#define type_system_code 0x13E -#define type_textual_input_port 0x11E -#define type_textual_output_port 0x21E -#define type_textual_port 0x1E -#define type_thread 0x4E -#define type_tlc 0x5E -#define type_typed_object 0x7 -#define type_vector 0x0 -#define typed_object_type_disp 0x1 -#define typedef_i16 "short" -#define typedef_i32 "int" -#define typedef_i64 "long" -#define typedef_i8 "char" -#define typedef_iptr "long int" -#define typedef_ptr "void *" -#define typedef_string_char "unsigned int" -#define typedef_u16 "unsigned short" -#define typedef_u32 "unsigned int" -#define typedef_u64 "unsigned long" -#define typedef_u8 "unsigned char" -#define typedef_uptr "unsigned long int" -#define typemod 0x8 -#define unactivate_mode_deactivate 0x1 -#define unactivate_mode_destroy 0x2 -#define unactivate_mode_noop 0x0 -#define unaligned_floats 1 -#define unaligned_integers 1 -#define underflow_limit 0x80 -#define unscaled_shot_1_shot_flag -0x1 -#define vector_data_disp 0x9 -#define vector_immutable_flag 0x8 -#define vector_length_factor 0x10 -#define vector_length_offset 0x4 -#define vector_type_disp 0x1 -#define virtual_register_count 0x10 -#define wchar_bits 0x20 - -/* constants from declare-c-entries */ -#define CENTRY_Scall_any_results 24 -#define CENTRY_Scall_one_result 23 -#define CENTRY_Sreturn 22 -#define CENTRY_activate_thread 11 -#define CENTRY_deactivate_thread 12 -#define CENTRY_foreign_entry 17 -#define CENTRY_get_more_room 19 -#define CENTRY_get_thread_context 1 -#define CENTRY_handle_apply_overflood 2 -#define CENTRY_handle_arg_error 16 -#define CENTRY_handle_docall_error 3 -#define CENTRY_handle_mvlet_error 15 -#define CENTRY_handle_nonprocedure_symbol 6 -#define CENTRY_handle_overflood 5 -#define CENTRY_handle_overflow 4 -#define CENTRY_handle_values_error 14 -#define CENTRY_install_library_entry 18 -#define CENTRY_instantiate_code_object 21 -#define CENTRY_raw_collect_cond 9 -#define CENTRY_raw_tc_mutex 10 -#define CENTRY_scan_remembered_set 20 -#define CENTRY_split_and_resize 8 -#define CENTRY_thread_context 0 -#define CENTRY_thread_list 7 -#define CENTRY_unactivate_thread 13 - -/* displacements for records */ -#define eq_hashtable_rtd_disp 1 -#define eq_hashtable_type_disp 9 -#define eq_hashtable_mutablep_disp 17 -#define eq_hashtable_vec_disp 25 -#define eq_hashtable_minlen_disp 33 -#define eq_hashtable_size_disp 41 -#define eq_hashtable_subtype_disp 49 -#define symbol_hashtable_rtd_disp 1 -#define symbol_hashtable_type_disp 9 -#define symbol_hashtable_mutablep_disp 17 -#define symbol_hashtable_vec_disp 25 -#define symbol_hashtable_minlen_disp 33 -#define symbol_hashtable_size_disp 41 -#define symbol_hashtable_equivp_disp 49 -#define code_info_rtd_disp 1 -#define code_info_src_disp 9 -#define code_info_sexpr_disp 17 -#define code_info_free_disp 25 -#define code_info_live_disp 33 -#define code_info_rpis_disp 41 - -/* predicates */ -#define Simmediatep(x) (((uptr)(x)&0x7)==0x6) -#define Sportp(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0xFF)==0x1E)) -#define Scodep(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0xFF)==0x3E)) - -/* structure accessors */ -#define INITCAR(x) (*((ptr *)((uptr)(x)+7))) -#define INITCDR(x) (*((ptr *)((uptr)(x)+15))) -#define SETCAR(x,y) DIRTYSET(((ptr *)((uptr)(x)+7)),(y)) -#define SETCDR(x,y) DIRTYSET(((ptr *)((uptr)(x)+15)),(y)) -#define BOXTYPE(x) (*((iptr *)((uptr)(x)+1))) -#define INITBOXREF(x) (*((ptr *)((uptr)(x)+9))) -#define SETBOXREF(x,y) DIRTYSET(((ptr *)((uptr)(x)+9)),(y)) -#define EPHEMERONNEXT(x) (*((ptr *)((uptr)(x)+23))) -#define INITEPHEMERONNEXT(x) (*((ptr *)((uptr)(x)+23))) -#define EPHEMERONTRIGGERNEXT(x) (*((ptr *)((uptr)(x)+31))) -#define INITEPHEMERONTRIGGERNEXT(x) (*((ptr *)((uptr)(x)+31))) -#define TLCTYPE(x) (*((iptr *)((uptr)(x)+1))) -#define TLCKEYVAL(x) (*((ptr *)((uptr)(x)+9))) -#define TLCHT(x) (*((ptr *)((uptr)(x)+17))) -#define TLCNEXT(x) (*((ptr *)((uptr)(x)+25))) -#define INITTLCKEYVAL(x) (*((ptr *)((uptr)(x)+9))) -#define INITTLCHT(x) (*((ptr *)((uptr)(x)+17))) -#define INITTLCNEXT(x) (*((ptr *)((uptr)(x)+25))) -#define SETTLCNEXT(x,y) DIRTYSET(((ptr *)((uptr)(x)+25)),(y)) -#define SYMVAL(x) (*((ptr *)((uptr)(x)+5))) -#define SYMPVAL(x) (*((ptr *)((uptr)(x)+13))) -#define SYMPLIST(x) (*((ptr *)((uptr)(x)+21))) -#define SYMNAME(x) (*((ptr *)((uptr)(x)+29))) -#define SYMSPLIST(x) (*((ptr *)((uptr)(x)+37))) -#define SYMHASH(x) (*((ptr *)((uptr)(x)+45))) -#define INITSYMVAL(x) (*((ptr *)((uptr)(x)+5))) -#define INITSYMPVAL(x) (*((ptr *)((uptr)(x)+13))) -#define INITSYMPLIST(x) (*((ptr *)((uptr)(x)+21))) -#define INITSYMNAME(x) (*((ptr *)((uptr)(x)+29))) -#define INITSYMSPLIST(x) (*((ptr *)((uptr)(x)+37))) -#define INITSYMHASH(x) (*((ptr *)((uptr)(x)+45))) -#define SETSYMVAL(x,y) DIRTYSET(((ptr *)((uptr)(x)+5)),(y)) -#define SETSYMPVAL(x,y) DIRTYSET(((ptr *)((uptr)(x)+13)),(y)) -#define SETSYMPLIST(x,y) DIRTYSET(((ptr *)((uptr)(x)+21)),(y)) -#define SETSYMNAME(x,y) DIRTYSET(((ptr *)((uptr)(x)+29)),(y)) -#define SETSYMSPLIST(x,y) DIRTYSET(((ptr *)((uptr)(x)+37)),(y)) -#define SETSYMHASH(x,y) DIRTYSET(((ptr *)((uptr)(x)+45)),(y)) -#define VECTTYPE(x) (*((iptr *)((uptr)(x)+1))) -#define INITVECTIT(x,i) (((ptr *)((uptr)(x)+9))[i]) -#define SETVECTIT(x,i,y) DIRTYSET((((ptr *)((uptr)(x)+9))+i),(y)) -#define FXVECTOR_TYPE(x) (*((iptr *)((uptr)(x)+1))) -#define FXVECTIT(x,i) (((ptr *)((uptr)(x)+9))[i]) -#define BYTEVECTOR_TYPE(x) (*((iptr *)((uptr)(x)+1))) -#define BVIT(x,i) (((octet *)((uptr)(x)+9))[i]) -#define INEXACTNUM_TYPE(x) (*((iptr *)((uptr)(x)+1))) -#define INEXACTNUM_REAL_PART(x) (*((double *)((uptr)(x)+17))) -#define INEXACTNUM_IMAG_PART(x) (*((double *)((uptr)(x)+25))) -#define EXACTNUM_TYPE(x) (*((iptr *)((uptr)(x)+1))) -#define EXACTNUM_REAL_PART(x) (*((ptr *)((uptr)(x)+9))) -#define EXACTNUM_IMAG_PART(x) (*((ptr *)((uptr)(x)+17))) -#define RATTYPE(x) (*((iptr *)((uptr)(x)+1))) -#define RATNUM(x) (*((ptr *)((uptr)(x)+9))) -#define RATDEN(x) (*((ptr *)((uptr)(x)+17))) -#define CLOSENTRY(x) (*((ptr *)((uptr)(x)+3))) -#define CLOSIT(x,i) (((ptr *)((uptr)(x)+11))[i]) -#define FLODAT(x) (*((double *)((uptr)(x)+6))) -#define PORTTYPE(x) (*((iptr *)((uptr)(x)+1))) -#define PORTNAME(x) (*((ptr *)((uptr)(x)+73))) -#define PORTHANDLER(x) (*((ptr *)((uptr)(x)+9))) -#define PORTINFO(x) (*((ptr *)((uptr)(x)+65))) -#define PORTOCNT(x) (*((iptr *)((uptr)(x)+17))) -#define PORTOLAST(x) (*((ptr *)((uptr)(x)+33))) -#define PORTOBUF(x) (*((ptr *)((uptr)(x)+41))) -#define PORTICNT(x) (*((iptr *)((uptr)(x)+25))) -#define PORTILAST(x) (*((ptr *)((uptr)(x)+49))) -#define PORTIBUF(x) (*((ptr *)((uptr)(x)+57))) -#define STRTYPE(x) (*((iptr *)((uptr)(x)+1))) -#define STRIT(x,i) (((string_char *)((uptr)(x)+9))[i]) -#define BIGTYPE(x) (*((iptr *)((uptr)(x)+1))) -#define BIGIT(x,i) (((bigit *)((uptr)(x)+9))[i]) -#define CODETYPE(x) (*((iptr *)((uptr)(x)+1))) -#define CODELEN(x) (*((iptr *)((uptr)(x)+9))) -#define CODERELOC(x) (*((ptr *)((uptr)(x)+17))) -#define CODENAME(x) (*((ptr *)((uptr)(x)+25))) -#define CODEARITYMASK(x) (*((ptr *)((uptr)(x)+33))) -#define CODEFREE(x) (*((iptr *)((uptr)(x)+41))) -#define CODEINFO(x) (*((ptr *)((uptr)(x)+49))) -#define CODEPINFOS(x) (*((ptr *)((uptr)(x)+57))) -#define CODEIT(x,i) (((octet *)((uptr)(x)+65))[i]) -#define RELOCSIZE(x) (*((iptr *)((uptr)(x)+0))) -#define RELOCCODE(x) (*((ptr *)((uptr)(x)+8))) -#define RELOCIT(x,i) (((uptr *)((uptr)(x)+16))[i]) -#define CONTSTACK(x) (*((ptr *)((uptr)(x)+11))) -#define CONTLENGTH(x) (*((iptr *)((uptr)(x)+19))) -#define CONTCLENGTH(x) (*((iptr *)((uptr)(x)+27))) -#define CONTLINK(x) (*((ptr *)((uptr)(x)+35))) -#define CONTRET(x) (*((ptr *)((uptr)(x)+43))) -#define CONTWINDERS(x) (*((ptr *)((uptr)(x)+51))) -#define RTDCOUNTSTYPE(x) (*((iptr *)((uptr)(x)+1))) -#define RTDCOUNTSTIMESTAMP(x) (*((U64 *)((uptr)(x)+9))) -#define RTDCOUNTSIT(x,i) (((uptr *)((uptr)(x)+17))[i]) -#define RECORDDESCPARENT(x) (*((ptr *)((uptr)(x)+9))) -#define RECORDDESCSIZE(x) (*((ptr *)((uptr)(x)+17))) -#define RECORDDESCPM(x) (*((ptr *)((uptr)(x)+25))) -#define RECORDDESCMPM(x) (*((ptr *)((uptr)(x)+33))) -#define RECORDDESCNAME(x) (*((ptr *)((uptr)(x)+41))) -#define RECORDDESCFLDS(x) (*((ptr *)((uptr)(x)+49))) -#define RECORDDESCFLAGS(x) (*((ptr *)((uptr)(x)+57))) -#define RECORDDESCUID(x) (*((ptr *)((uptr)(x)+65))) -#define RECORDDESCCOUNTS(x) (*((ptr *)((uptr)(x)+73))) -#define RECORDINSTTYPE(x) (*((ptr *)((uptr)(x)+1))) -#define RECORDINSTIT(x,i) (((ptr *)((uptr)(x)+9))[i]) -#define CLOSCODE(p) ((ptr)((uptr)CLOSENTRY(p)-code_data_disp)) -#define CODEENTRYPOINT(x) ((ptr)((uptr)(x)+code_data_disp)) -#define SETCLOSCODE(p,x) (CLOSENTRY(p) = CODEENTRYPOINT(x)) -#define SYMCODE(p) ((ptr)((uptr)SYMPVAL(p)-code_data_disp)) -#define INITSYMCODE(p,x) (INITSYMPVAL(p) = CODEENTRYPOINT(x)) -#define SETSYMCODE(p,x) SETSYMPVAL(p,CODEENTRYPOINT(x)) -#define BIGLEN(x) ((iptr)((uptr)BIGTYPE(x) >> bignum_length_offset)) -#define BIGSIGN(x) ((BIGTYPE(x) & mask_bignum_sign) >> bignum_sign_offset) -#define SETBIGLENANDSIGN(x,xl,xs) BIGTYPE(x) = (uptr)(xl) << bignum_length_offset | (xs) << bignum_sign_offset | type_bignum -#define CLOSLEN(p) CODEFREE(CLOSCODE(p)) -#define GUARDIANOBJ(x) (*((ptr *)((uptr)(x)+0))) -#define GUARDIANREP(x) (*((ptr *)((uptr)(x)+8))) -#define GUARDIANTCONC(x) (*((ptr *)((uptr)(x)+16))) -#define GUARDIANNEXT(x) (*((ptr *)((uptr)(x)+24))) -#define INITGUARDIANOBJ(x) (*((ptr *)((uptr)(x)+0))) -#define INITGUARDIANREP(x) (*((ptr *)((uptr)(x)+8))) -#define INITGUARDIANTCONC(x) (*((ptr *)((uptr)(x)+16))) -#define INITGUARDIANNEXT(x) (*((ptr *)((uptr)(x)+24))) -#define FORWARDMARKER(x) (*((ptr *)((uptr)(x)+0))) -#define FORWARDADDRESS(x) (*((ptr *)((uptr)(x)+8))) -#define CACHEDSTACKSIZE(x) (*((iptr *)((uptr)(x)+0))) -#define CACHEDSTACKLINK(x) (*((ptr *)((uptr)(x)+8))) -#define RPHEADERFRAMESIZE(x) (*((iptr *)((uptr)(x)+16))) -#define RPHEADERLIVEMASK(x) (*((ptr *)((uptr)(x)+0))) -#define RPHEADERTOPLINK(x) (*((uptr *)((uptr)(x)+8))) - -/* machine types */ -#define machine_type_names {"any", "i3le", "ti3le", "i3nt", "ti3nt", "i3fb", "ti3fb", "i3ob", "ti3ob", "i3osx", "ti3osx", "a6le", "ta6le", "a6osx", "ta6osx", "a6ob", "ta6ob", "a6s2", "ta6s2", "i3s2", "ti3s2", "a6fb", "ta6fb", "i3nb", "ti3nb", "a6nb", "ta6nb", "a6nt", "ta6nt", "i3qnx", "ti3qnx", "arm32le", "tarm32le", "ppc32le", "tppc32le"} - -/* allocation-space names */ -#define alloc_space_names "new", "impure", "symbol", "port", "weakpr", "emph", "pure", "cont", "code", "p-tobj", "ip-rec", "data", "empty" - -/* allocation-space characters */ -#define alloc_space_chars 'n', 'i', 'x', 'q', 'w', 'e', 'p', 'k', 'c', 'r', 's', 'd', 'e' - -/* threads */ -#define THREADTC(x) (*((uptr *)((uptr)(x)+9))) - -/* thread-context data */ -#define DSTBV(x) (*((ptr *)((uptr)(x)+680))) -#define SRCBV(x) (*((ptr *)((uptr)(x)+688))) -#define U(x) (*((ptr *)((uptr)(x)+352))) -#define V(x) (*((ptr *)((uptr)(x)+360))) -#define W(x) (*((ptr *)((uptr)(x)+368))) -#define X(x) (*((ptr *)((uptr)(x)+376))) -#define Y(x) (*((ptr *)((uptr)(x)+384))) -#define AC0(x) (*((void* *)((uptr)(x)+40))) -#define AC1(x) (*((void* *)((uptr)(x)+48))) -#define ACTIVE(x) (*((I32 *)((uptr)(x)+308))) -#define ALLOCCOUNTER(x) (*((U64 *)((uptr)(x)+664))) -#define AP(x) (*((void* *)((uptr)(x)+80))) -#define ARGREGS(x,i) (((void* *)((uptr)(x)+0))[i]) -#define BLOCKCOUNTER(x) (*((ptr *)((uptr)(x)+472))) -#define CCHAIN(x) (*((ptr *)((uptr)(x)+288))) -#define CODERANGESTOFLUSH(x) (*((ptr *)((uptr)(x)+296))) -#define COMPILEPROFILE(x) (*((ptr *)((uptr)(x)+560))) -#define COMPRESSFORMAT(x) (*((ptr *)((uptr)(x)+632))) -#define COMPRESSLEVEL(x) (*((ptr *)((uptr)(x)+640))) -#define CP(x) (*((void* *)((uptr)(x)+64))) -#define CURRENTERROR(x) (*((ptr *)((uptr)(x)+464))) -#define CURRENTINPUT(x) (*((ptr *)((uptr)(x)+448))) -#define CURRENTMSO(x) (*((ptr *)((uptr)(x)+488))) -#define CURRENTOUTPUT(x) (*((ptr *)((uptr)(x)+456))) -#define DEFAULTRECORDEQUALPROCEDURE(x) (*((ptr *)((uptr)(x)+616))) -#define DEFAULTRECORDHASHPROCEDURE(x) (*((ptr *)((uptr)(x)+624))) -#define DISABLECOUNT(x) (*((ptr *)((uptr)(x)+408))) -#define EAP(x) (*((void* *)((uptr)(x)+88))) -#define ESP(x) (*((void* *)((uptr)(x)+72))) -#define FXFIRSTBITSETBV(x) (*((ptr *)((uptr)(x)+512))) -#define FXLENGTHBV(x) (*((ptr *)((uptr)(x)+504))) -#define GENERATEINSPECTORINFORMATION(x) (*((ptr *)((uptr)(x)+568))) -#define GENERATEPROCEDURESOURCEINFORMATION(x) (*((ptr *)((uptr)(x)+576))) -#define GENERATEPROFILEFORMS(x) (*((ptr *)((uptr)(x)+584))) -#define GUARDIANENTRIES(x) (*((ptr *)((uptr)(x)+280))) -#define INSTRCOUNTER(x) (*((U64 *)((uptr)(x)+656))) -#define KEYBOARDINTERRUPTPENDING(x) (*((ptr *)((uptr)(x)+432))) -#define LZ4OUTBUFFER(x) (*((void* *)((uptr)(x)+648))) -#define METALEVEL(x) (*((ptr *)((uptr)(x)+552))) -#define NULLIMMUTABLEBYTEVECTOR(x) (*((ptr *)((uptr)(x)+536))) -#define NULLIMMUTABLEFXVECTOR(x) (*((ptr *)((uptr)(x)+528))) -#define NULLIMMUTABLESTRING(x) (*((ptr *)((uptr)(x)+544))) -#define NULLIMMUTABLEVECTOR(x) (*((ptr *)((uptr)(x)+520))) -#define OPTIMIZELEVEL(x) (*((ptr *)((uptr)(x)+592))) -#define PARAMETERS(x) (*((ptr *)((uptr)(x)+672))) -#define RANDOMSEED(x) (*((U32 *)((uptr)(x)+304))) -#define REAL_EAP(x) (*((void* *)((uptr)(x)+144))) -#define RET(x) (*((void* *)((uptr)(x)+96))) -#define SCHEMESTACK(x) (*((void* *)((uptr)(x)+312))) -#define SCHEMESTACKSIZE(x) (*((iptr *)((uptr)(x)+336))) -#define SFD(x) (*((ptr *)((uptr)(x)+480))) -#define SFP(x) (*((void* *)((uptr)(x)+56))) -#define SIGNALINTERRUPTPENDING(x) (*((ptr *)((uptr)(x)+416))) -#define SIGNALINTERRUPTQUEUE(x) (*((ptr *)((uptr)(x)+424))) -#define SOMETHINGPENDING(x) (*((ptr *)((uptr)(x)+392))) -#define STACKCACHE(x) (*((ptr *)((uptr)(x)+320))) -#define STACKLINK(x) (*((ptr *)((uptr)(x)+328))) -#define SUBSETMODE(x) (*((ptr *)((uptr)(x)+600))) -#define SUPPRESSPRIMITIVEINLINING(x) (*((ptr *)((uptr)(x)+608))) -#define TARGETMACHINE(x) (*((ptr *)((uptr)(x)+496))) -#define TD(x) (*((void* *)((uptr)(x)+136))) -#define THREADNO(x) (*((ptr *)((uptr)(x)+440))) -#define TIMERTICKS(x) (*((ptr *)((uptr)(x)+400))) -#define TRAP(x) (*((void* *)((uptr)(x)+104))) -#define TS(x) (*((void* *)((uptr)(x)+128))) -#define VIRTUALREGISTERS(x,i) (((ptr *)((uptr)(x)+152))[i]) -#define WINDERS(x) (*((ptr *)((uptr)(x)+344))) -#define XP(x) (*((void* *)((uptr)(x)+112))) -#define YP(x) (*((void* *)((uptr)(x)+120))) -#define ARGREG(x,i) (((void* *)((uptr)(x)+0))[i]) -#define VIRTREG(x,i) (((ptr *)((uptr)(x)+152))[i]) - -/* library entries we access from C code */ -#define library_nonprocedure_code 152 -#define library_dounderflow 154 diff --git a/ta6ob/boot/ta6ob/kernel.o b/ta6ob/boot/ta6ob/kernel.o deleted file mode 100644 index 18f2ee2..0000000 Binary files a/ta6ob/boot/ta6ob/kernel.o and /dev/null differ diff --git a/ta6ob/boot/ta6ob/main.o b/ta6ob/boot/ta6ob/main.o deleted file mode 100644 index 5255463..0000000 Binary files a/ta6ob/boot/ta6ob/main.o and /dev/null differ diff --git a/ta6ob/boot/ta6ob/petite.boot b/ta6ob/boot/ta6ob/petite.boot deleted file mode 100644 index 38997ee..0000000 Binary files a/ta6ob/boot/ta6ob/petite.boot and /dev/null differ diff --git a/ta6ob/boot/ta6ob/revision b/ta6ob/boot/ta6ob/revision deleted file mode 100644 index e00319a..0000000 --- a/ta6ob/boot/ta6ob/revision +++ /dev/null @@ -1,2 +0,0 @@ -43e68af625b650124dc0a2c2f22fac26a3449c24 -git diff --git a/ta6ob/boot/ta6ob/scheme.boot b/ta6ob/boot/ta6ob/scheme.boot deleted file mode 100644 index c839f7d..0000000 Binary files a/ta6ob/boot/ta6ob/scheme.boot and /dev/null differ diff --git a/ta6ob/boot/ta6ob/scheme.h b/ta6ob/boot/ta6ob/scheme.h deleted file mode 100644 index 434b811..0000000 --- a/ta6ob/boot/ta6ob/scheme.h +++ /dev/null @@ -1,245 +0,0 @@ -/* scheme.h for Chez Scheme Version 9.5.9 (ta6ob) */ - -/* Do not edit this file. It is automatically generated and */ -/* specifically tailored to the version of Chez Scheme named */ -/* above. Always be certain that you have the correct scheme.h */ -/* for the version of Chez Scheme you are using. */ - -/* Warning: Some macros may evaluate arguments more than once. */ - -/* Specify declaration of exports. */ -#ifdef _WIN32 -# if __cplusplus -# ifdef SCHEME_IMPORT -# define EXPORT extern "C" __declspec (dllimport) -# elif SCHEME_STATIC -# define EXPORT extern "C" -# else -# define EXPORT extern "C" __declspec (dllexport) -# endif -# else -# ifdef SCHEME_IMPORT -# define EXPORT extern __declspec (dllimport) -# elif SCHEME_STATIC -# define EXPORT extern -# else -# define EXPORT extern __declspec (dllexport) -# endif -# endif -#else -# if __cplusplus -# define EXPORT extern "C" -# else -# define EXPORT extern -# endif -#endif - -/* Chez Scheme Version and machine type */ -#define VERSION "9.5.9" -#define MACHINE_TYPE "ta6ob" - -/* All Scheme objects are of type ptr. Type iptr and */ -/* uptr are signed and unsigned ints of the same size */ -/* as a ptr */ -typedef void * ptr; -typedef long int iptr; -typedef unsigned long int uptr; - -/* String elements are 32-bit tagged char objects */ -typedef unsigned int string_char; - -/* Bytevector elements are 8-bit unsigned "octets" */ -typedef unsigned char octet; - -/* Type predicates */ -#define Sfixnump(x) (((uptr)(x)&0x7)==0x0) -#define Scharp(x) (((uptr)(x)&0xFF)==0x16) -#define Snullp(x) ((uptr)(x)==0x26) -#define Seof_objectp(x) ((uptr)(x)==0x36) -#define Sbwp_objectp(x) ((uptr)(x)==0x4E) -#define Sbooleanp(x) (((uptr)(x)&0xF7)==0x6) -#define Spairp(x) (((uptr)(x)&0x7)==0x1) -#define Ssymbolp(x) (((uptr)(x)&0x7)==0x3) -#define Sprocedurep(x) (((uptr)(x)&0x7)==0x5) -#define Sflonump(x) (((uptr)(x)&0x7)==0x2) -#define Svectorp(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0x7)==0x0)) -#define Sfxvectorp(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0x7)==0x3)) -#define Sbytevectorp(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0x3)==0x1)) -#define Sstringp(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0x7)==0x2)) -#define Sbignump(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0x1F)==0x6)) -#define Sboxp(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0x7F)==0xE)) -#define Sinexactnump(x) ((((uptr)(x)&0x7)==0x7) &&\ - ((uptr)((*((ptr *)((uptr)(x)+1))))==0x36)) -#define Sexactnump(x) ((((uptr)(x)&0x7)==0x7) &&\ - ((uptr)((*((ptr *)((uptr)(x)+1))))==0x56)) -#define Sratnump(x) ((((uptr)(x)&0x7)==0x7) &&\ - ((uptr)((*((ptr *)((uptr)(x)+1))))==0x16)) -#define Sinputportp(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0x1FF)==0x11E)) -#define Soutputportp(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0x2FF)==0x21E)) -#define Srecordp(x) ((((uptr)(x)&0x7)==0x7) &&\ - (((uptr)((*((ptr *)((uptr)(x)+1))))&0x7)==0x7)) - -/* Accessors */ -#define Sfixnum_value(x) ((iptr)(x)/8) -#define Schar_value(x) ((string_char)((uptr)(x)>>8)) -#define Sboolean_value(x) ((x) != Sfalse) -#define Scar(x) (*((ptr *)((uptr)(x)+7))) -#define Scdr(x) (*((ptr *)((uptr)(x)+15))) -#define Sflonum_value(x) (*((double *)((uptr)(x)+6))) -#define Svector_length(x) ((iptr)((uptr)(*((iptr *)((uptr)(x)+1)))>>4)) -#define Svector_ref(x,i) (((ptr *)((uptr)(x)+9))[i]) -#define Sfxvector_length(x) ((iptr)((uptr)(*((iptr *)((uptr)(x)+1)))>>4)) -#define Sfxvector_ref(x,i) (((ptr *)((uptr)(x)+9))[i]) -#define Sbytevector_length(x) ((iptr)((uptr)(*((iptr *)((uptr)(x)+1)))>>3)) -#define Sbytevector_u8_ref(x,i) (((octet *)((uptr)(x)+9))[i]) -/* Warning: Sbytevector_data(x) returns a pointer into x. */ -#define Sbytevector_data(x) &Sbytevector_u8_ref(x,0) -#define Sstring_length(x) ((iptr)((uptr)(*((iptr *)((uptr)(x)+1)))>>4)) -#define Sstring_ref(x,i) Schar_value(((string_char *)((uptr)(x)+9))[i]) -#define Sunbox(x) (*((ptr *)((uptr)(x)+9))) -EXPORT iptr Sinteger_value(ptr); -#define Sunsigned_value(x) (uptr)Sinteger_value(x) -EXPORT int Sinteger32_value(ptr); -#define Sunsigned32_value(x) (unsigned int)Sinteger32_value(x) -EXPORT long Sinteger64_value(ptr); -#define Sunsigned64_value(x) (unsigned long)Sinteger64_value(x) - -/* Mutators */ -EXPORT void Sset_box(ptr, ptr); -EXPORT void Sset_car(ptr, ptr); -EXPORT void Sset_cdr(ptr, ptr); -#define Sstring_set(x,i,c) ((void)((((string_char *)((uptr)(x)+9))[i]) = (string_char)(uptr)Schar(c))) -#define Sfxvector_set(x,i,n) ((void)(Sfxvector_ref(x,i) = (n))) -#define Sbytevector_u8_set(x,i,n) ((void)(Sbytevector_u8_ref(x,i) = (n))) -EXPORT void Svector_set(ptr, iptr, ptr); - -/* Constructors */ -#define Sfixnum(x) ((ptr)(uptr)((x)*8)) -#define Schar(x) ((ptr)(uptr)((x)<<8|0x16)) -#define Snil ((ptr)0x26) -#define Strue ((ptr)0xE) -#define Sfalse ((ptr)0x6) -#define Sboolean(x) ((x)?Strue:Sfalse) -#define Sbwp_object ((ptr)0x4E) -#define Seof_object ((ptr)0x36) -#define Svoid ((ptr)0x3E) -EXPORT ptr Scons(ptr, ptr); -EXPORT ptr Sstring_to_symbol(const char *); -EXPORT ptr Ssymbol_to_string(ptr); -EXPORT ptr Sflonum(double); -EXPORT ptr Smake_vector(iptr, ptr); -EXPORT ptr Smake_fxvector(iptr, ptr); -EXPORT ptr Smake_bytevector(iptr, int); -EXPORT ptr Smake_string(iptr, int); -EXPORT ptr Smake_uninitialized_string(iptr); -EXPORT ptr Sstring(const char *); -EXPORT ptr Sstring_of_length(const char *, iptr); -EXPORT ptr Sstring_utf8(const char*, iptr); -EXPORT ptr Sbox(ptr); -EXPORT ptr Sinteger(iptr); -EXPORT ptr Sunsigned(uptr); -EXPORT ptr Sinteger32(int); -EXPORT ptr Sunsigned32(unsigned int); -EXPORT ptr Sinteger64(long); -EXPORT ptr Sunsigned64(unsigned long); - -/* Miscellaneous */ -EXPORT ptr Stop_level_value(ptr); -EXPORT void Sset_top_level_value(ptr, ptr); -EXPORT void Slock_object(ptr); -EXPORT void Sunlock_object(ptr); -EXPORT int Slocked_objectp(ptr); -EXPORT void Sforeign_symbol(const char *, void *); -EXPORT void Sregister_symbol(const char *, void *); - -/* Support for calls into Scheme */ -EXPORT ptr Scall0(ptr); -EXPORT ptr Scall1(ptr, ptr); -EXPORT ptr Scall2(ptr, ptr, ptr); -EXPORT ptr Scall3(ptr, ptr, ptr, ptr); -EXPORT void Sinitframe(iptr); -EXPORT void Sput_arg(iptr, ptr); -EXPORT ptr Scall(ptr, iptr); -/* Warning: Sforeign_callable_entry_point(x) returns a pointer into x. */ -#define Sforeign_callable_entry_point(x) ((void (*)(void))((uptr)(x)+65)) -#define Sforeign_callable_code_object(x) ((ptr)((uptr)(x)-65)) - -/* Customization support. */ -EXPORT const char * Skernel_version(void); -EXPORT void Sretain_static_relocation(void); -EXPORT void Sset_verbose(int); -EXPORT void Sscheme_init(void (*)(void)); -EXPORT void Sregister_boot_file(const char *); -EXPORT void Sregister_boot_file_fd(const char *, int fd); -EXPORT void Sregister_heap_file(const char *); -EXPORT void Scompact_heap(void); -EXPORT void Ssave_heap(const char *, int); -EXPORT void Sbuild_heap(const char *, void (*)(void)); -EXPORT void Senable_expeditor(const char *); -EXPORT int Sscheme_start(int, const char *[]); -EXPORT int Sscheme_script(const char *, int, const char *[]); -EXPORT int Sscheme_program(const char *, int, const char *[]); -EXPORT void Sscheme_deinit(void); - -/* Thread support. */ -EXPORT int Sactivate_thread(void); -EXPORT void Sdeactivate_thread(void); -EXPORT int Sdestroy_thread(void); - -/* Features. */ -#define FEATURE_ICONV -#define FEATURE_EXPEDITOR -#define FEATURE_PTHREADS - -/* Locking macros. */ -#define INITLOCK(addr) \ - __asm__ __volatile__ ("movq $0, (%0)"\ - : \ - : "r" (addr) \ - : "memory") - -#define SPINLOCK(addr) \ - __asm__ __volatile__ ("0:\n\t"\ - "movq $1, %%rax\n\t"\ - "xchgq (%0), %%rax\n\t"\ - "cmpq $0, %%rax\n\t"\ - "je 2f\n\t"\ - "1:\n\t"\ - "pause\n\t"\ - "cmpq $0, (%0)\n\t"\ - "je 0b\n\t"\ - "jmp 1b\n\t"\ - "2:"\ - : \ - : "r" (addr) \ - : "rax", "flags", "memory") - -#define UNLOCK(addr) \ - __asm__ __volatile__ ("movq $0, (%0)"\ - : \ - : "r" (addr) \ - :"memory") - -#define LOCKED_INCR(addr, ret) \ - __asm__ __volatile__ ("lock; incq (%1)\n\t"\ - "sete %b0\n\t"\ - "movzx %b0, %0\n\t"\ - : "=q" (ret) \ - : "r" (addr) \ - : "flags", "memory") - -#define LOCKED_DECR(addr, ret) \ - __asm__ __volatile__ ("lock; decq (%1)\n\t"\ - "sete %b0\n\t"\ - "movzx %b0, %0\n\t"\ - : "=q" (ret) \ - : "r" (addr) \ - : "flags", "memory") diff --git a/ta6ob/c/Makefile b/ta6ob/c/Makefile deleted file mode 100644 index 74857da..0000000 --- a/ta6ob/c/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# Mf-ta6ob -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -m = ta6ob -Cpu = X86_64 - -mdinclude = -I/usr/local/include -I/usr/X11R6/include -mdclib = -L/usr/local/lib -liconv -lm ${ncursesLib} -lpthread -lossp-uuid -C = ${CC} ${CPPFLAGS} -Wpointer-arith -Werror -O2 -D_REENTRANT -pthread ${CFLAGS} -o = o -mdsrc = i3le.c -mdobj = i3le.o - -.SUFFIXES: -.SUFFIXES: .c .o - -.c.o: - $C -c -D${Cpu} -I${Include} ${zlibInc} ${LZ4Inc} ${mdinclude} $*.c - -include Mf-base - -${KernelO}: ${kernelobj} ${zlibDep} ${LZ4Dep} - ${LD} -r -X -o ${KernelO} ${kernelobj} ${zlibLib} ${LZ4Lib} - -${KernelLib}: ${kernelobj} - ${AR} ${ARFLAGS} ${KernelLib} ${kernelobj} - -${Scheme}: ${Kernel} ${KernelLinkDeps} ${Main} - $C -rdynamic -Wl,--export-dynamic -Wl,-zwxneeded -o ${Scheme} ${Main} ${Kernel} ${mdclib} ${KernelLinkLibs} ${LDFLAGS} - -../zlib/configure.log: - (cd ../zlib; CFLAGS="${CFLAGS} -m64" ./configure --64) - -../lz4/lib/liblz4.a: ${LZ4Sources} - (cd ../lz4/lib; CFLAGS="${CFLAGS} -m64" ${MAKE} liblz4.a) diff --git a/ta6ob/c/Mf-base b/ta6ob/c/Mf-base deleted file mode 100644 index d97cf91..0000000 --- a/ta6ob/c/Mf-base +++ /dev/null @@ -1,82 +0,0 @@ -# Mf-base -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -include Mf-config -export CC CFLAGS LD LDFLAGS - -Include=../boot/$m -PetiteBoot=../boot/$m/petite.boot -SchemeBoot=../boot/$m/scheme.boot -Main=../boot/$m/main.$o -Scheme=../bin/$m/scheme - -# One of these sets is referenced in Mf-config to select between -# linking with kernel.o or libkernel.a - -KernelO=../boot/$m/kernel.$o -KernelOLinkDeps= -KernelOLinkLibs= - -KernelLib=../boot/$m/libkernel.a -KernelLibLinkDeps=${zlibDep} ${LZ4Dep} -KernelLibLinkLibs=${zlibLib} ${LZ4Lib} - -kernelsrc=statics.c segment.c alloc.c symbol.c intern.c gcwrapper.c gc-011.c gc-ocd.c gc-oce.c\ - number.c schsig.c io.c new-io.c print.c fasl.c stats.c foreign.c prim.c prim5.c flushcache.c\ - schlib.c thread.c expeditor.c scheme.c compress-io.c - -kernelobj=${kernelsrc:%.c=%.$o} ${mdobj} - -kernelhdr=system.h types.h version.h globals.h externs.h segment.h gc.c sort.h thread.h config.h compress-io.h itest.c nocurses.h - -mainsrc=main.c - -mainobj:=${mainsrc:%.c=%.$o} - -doit: ${Scheme} - -source: ${kernelsrc} ${kernelhdr} ${mdsrc} ${mainsrc} - -${Main}: ${mainobj} - cp -p ${mainobj} ${Main} - -rootsrc=$(shell cd ../../c; echo *) -${rootsrc}: -ifeq ($(OS),Windows_NT) - cp -p ../../c/$@ $@ -else - ln -s ../../c/$@ $@ -endif - -scheme.o: itest.c -scheme.o main.o: config.h -${kernelobj}: system.h types.h version.h externs.h globals.h segment.h thread.h sort.h compress-io.h nocurses.h -${kernelobj}: ${Include}/equates.h ${Include}/scheme.h -${mainobj}: ${Include}/scheme.h -${kernelobj}: ${zlibHeaderDep} ${LZ4HeaderDep} -gc-011.o gc-ocd.o gc-oce.o: gc.c - -../zlib/zlib.h ../zlib/zconf.h: ../zlib/configure.log - -../zlib/libz.a: ../zlib/configure.log - (cd ../zlib; ${MAKE}) - -LZ4Sources=../lz4/lib/lz4.h ../lz4/lib/lz4frame.h \ - ../lz4/lib/lz4.c ../lz4/lib/lz4frame.c \ - ../lz4/lib/lz4hc.c ../lz4/lib/xxhash.c - -clean: - rm -f *.$o ${mdclean} - rm -f Make.out diff --git a/ta6ob/c/Mf-config b/ta6ob/c/Mf-config deleted file mode 100644 index 168f559..0000000 --- a/ta6ob/c/Mf-config +++ /dev/null @@ -1,22 +0,0 @@ -CC=gcc -CPPFLAGS= -CFLAGS= -LD=ld -LDFLAGS= -AR=ar -ARFLAGS=rc -RANLIB=ranlib -WINDRES=windres -cursesLib=-lcurses -ncursesLib=-lncurses -zlibInc=-I../zlib -LZ4Inc=-I../lz4/lib -zlibDep=../zlib/libz.a -LZ4Dep=../lz4/lib/liblz4.a -zlibLib=../zlib/libz.a -LZ4Lib=../lz4/lib/liblz4.a -zlibHeaderDep=../zlib/zconf.h ../zlib/zlib.h -LZ4HeaderDep=../lz4/lib/lz4.h ../lz4/lib/lz4frame.h -Kernel=${KernelO} -KernelLinkDeps=${KernelOLinkDeps} -KernelLinkLibs=${KernelOLinkLibs} diff --git a/ta6ob/c/Mf-ta6ob b/ta6ob/c/Mf-ta6ob deleted file mode 100644 index 74857da..0000000 --- a/ta6ob/c/Mf-ta6ob +++ /dev/null @@ -1,47 +0,0 @@ -# Mf-ta6ob -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -m = ta6ob -Cpu = X86_64 - -mdinclude = -I/usr/local/include -I/usr/X11R6/include -mdclib = -L/usr/local/lib -liconv -lm ${ncursesLib} -lpthread -lossp-uuid -C = ${CC} ${CPPFLAGS} -Wpointer-arith -Werror -O2 -D_REENTRANT -pthread ${CFLAGS} -o = o -mdsrc = i3le.c -mdobj = i3le.o - -.SUFFIXES: -.SUFFIXES: .c .o - -.c.o: - $C -c -D${Cpu} -I${Include} ${zlibInc} ${LZ4Inc} ${mdinclude} $*.c - -include Mf-base - -${KernelO}: ${kernelobj} ${zlibDep} ${LZ4Dep} - ${LD} -r -X -o ${KernelO} ${kernelobj} ${zlibLib} ${LZ4Lib} - -${KernelLib}: ${kernelobj} - ${AR} ${ARFLAGS} ${KernelLib} ${kernelobj} - -${Scheme}: ${Kernel} ${KernelLinkDeps} ${Main} - $C -rdynamic -Wl,--export-dynamic -Wl,-zwxneeded -o ${Scheme} ${Main} ${Kernel} ${mdclib} ${KernelLinkLibs} ${LDFLAGS} - -../zlib/configure.log: - (cd ../zlib; CFLAGS="${CFLAGS} -m64" ./configure --64) - -../lz4/lib/liblz4.a: ${LZ4Sources} - (cd ../lz4/lib; CFLAGS="${CFLAGS} -m64" ${MAKE} liblz4.a) diff --git a/ta6ob/c/alloc.c b/ta6ob/c/alloc.c deleted file mode 100644 index cb7c967..0000000 --- a/ta6ob/c/alloc.c +++ /dev/null @@ -1,862 +0,0 @@ -/* alloc.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" - -/* locally defined functions */ -static void maybe_fire_collector(void); - -void S_alloc_init(void) { - ISPC s; IGEN g; UINT i; - - if (S_boot_time) { - /* reset the allocation tables */ - for (g = 0; g <= static_generation; g++) { - S_G.bytes_of_generation[g] = 0; - for (s = 0; s <= max_real_space; s++) { - S_G.base_loc[g][s] = FIX(0); - S_G.first_loc[g][s] = FIX(0); - S_G.next_loc[g][s] = FIX(0); - S_G.bytes_left[g][s] = 0; - S_G.bytes_of_space[g][s] = 0; - } - } - - /* initialize the dirty-segment lists. */ - for (i = 0; i < DIRTY_SEGMENT_LISTS; i += 1) { - S_G.dirty_segments[i] = NULL; - } - - S_G.collect_trip_bytes = default_collect_trip_bytes; - S_G.g0_bytes_after_last_gc = 0; - - /* set to final value in prim.c when known */ - S_protect(&S_G.nonprocedure_code); - S_G.nonprocedure_code = FIX(0); - - S_protect(&S_G.null_vector); - find_room(space_new, 0, type_typed_object, size_vector(0), S_G.null_vector); - VECTTYPE(S_G.null_vector) = (0 << vector_length_offset) | type_vector; - - S_protect(&S_G.null_fxvector); - find_room(space_new, 0, type_typed_object, size_fxvector(0), S_G.null_fxvector); - FXVECTOR_TYPE(S_G.null_fxvector) = (0 << fxvector_length_offset) | type_fxvector; - - S_protect(&S_G.null_bytevector); - find_room(space_new, 0, type_typed_object, size_bytevector(0), S_G.null_bytevector); - BYTEVECTOR_TYPE(S_G.null_bytevector) = (0 << bytevector_length_offset) | type_bytevector; - - S_protect(&S_G.null_string); - find_room(space_new, 0, type_typed_object, size_string(0), S_G.null_string); - STRTYPE(S_G.null_string) = (0 << string_length_offset) | type_string; - } -} - -void S_protect(ptr *p) { - if (S_G.protect_next > max_protected) - S_error_abort("max_protected constant too small"); - *p = snil; - S_G.protected[S_G.protect_next++] = p; -} - -/* S_reset_scheme_stack is always called with mutex */ -void S_reset_scheme_stack(ptr tc, iptr n) { - ptr *x; iptr m; - - /* we allow less than one_shot_headroom here for no truly justifiable - reason */ - n = ptr_align(n + (one_shot_headroom >> 1)); - - x = &STACKCACHE(tc); - for (;;) { - if (*x == snil) { - if (n < default_stack_size) n = default_stack_size; - /* stacks are untyped objects */ - find_room(space_new, 0, typemod, n, SCHEMESTACK(tc)); - break; - } - if ((m = CACHEDSTACKSIZE(*x)) >= n) { - n = m; - SCHEMESTACK(tc) = *x; -/* if we decide to leave KEEPSMALLPUPPIES undefined permanently, we should - rewrite this code to remove the indirect on x */ -/* #define KEEPSMALLPUPPIES */ -#ifdef KEEPSMALLPUPPIES - *x = CACHEDSTACKLINK(*x); -#else - STACKCACHE(tc) = CACHEDSTACKLINK(*x); -#endif - break; - } - x = &CACHEDSTACKLINK(*x); - } - SCHEMESTACKSIZE(tc) = n; - ESP(tc) = (ptr)((uptr)SCHEMESTACK(tc) + n - stack_slop); - SFP(tc) = (ptr)SCHEMESTACK(tc); -} - -ptr S_compute_bytes_allocated(ptr xg, ptr xs) { - ptr tc = get_thread_context(); - ISPC s, smax, smin; IGEN g, gmax, gmin; - uptr n; - - gmin = (IGEN)UNFIX(xg); - if (gmin < 0) { - gmin = 0; - gmax = static_generation; - } else if (gmin == S_G.new_max_nonstatic_generation) { - /* include virtual inhabitents too */ - gmax = S_G.max_nonstatic_generation; - } else { - gmax = gmin; - } - - smin = (ISPC)(UNFIX(xs)); - smax = smin < 0 ? max_real_space : smin; - smin = smin < 0 ? 0 : smin; - - n = 0; - - g = gmin; - while (g <= gmax) { - for (s = smin; s <= smax; s++) { - ptr next_loc = S_G.next_loc[g][s]; - /* add in bytes previously recorded */ - n += S_G.bytes_of_space[g][s]; - /* add in bytes in active segments */ - if (next_loc != FIX(0)) - n += (char *)next_loc - (char *)S_G.base_loc[g][s]; - } - if (g == S_G.max_nonstatic_generation) - g = static_generation; - else - g += 1; - } - - /* subtract off bytes not allocated */ - if (gmin == 0 && smin <= space_new && space_new <= smax) - n -= (uptr)REAL_EAP(tc) - (uptr)AP(tc); - - return Sunsigned(n); -} - -static void maybe_fire_collector(void) { - if (S_G.bytes_of_generation[0] - S_G.g0_bytes_after_last_gc >= S_G.collect_trip_bytes) - S_fire_collector(); -} - -/* find_more_room - * S_find_more_room is called from the macro find_room when - * the current segment is too full to fit the allocation. - * - * A forward_marker followed by a pointer to - * the newly obtained segment is placed at next_loc to show - * gc where the end of this segment is and where the next - * segment of this type resides. Allocation occurs from the - * beginning of the newly obtained segment. The need for the - * eos marker explains the (2 * ptr_bytes) byte factor in - * S_find_more_room. - */ -/* S_find_more_room is always called with mutex */ -ptr S_find_more_room(ISPC s, IGEN g, iptr n, ptr old) { - iptr nsegs, seg; - ptr new; - - S_pants_down += 1; - - nsegs = (uptr)(n + 2 * ptr_bytes + bytes_per_segment - 1) >> segment_offset_bits; - - /* block requests to minimize fragmentation and improve cache locality */ - if (s == space_code && nsegs < 16) nsegs = 16; - - seg = S_find_segments(s, g, nsegs); - new = build_ptr(seg, 0); - - if (old == FIX(0)) { - /* first object of this space */ - S_G.first_loc[g][s] = new; - } else { - uptr bytes = (char *)old - (char *)S_G.base_loc[g][s]; - /* increment bytes_allocated by the closed-off partial segment */ - S_G.bytes_of_space[g][s] += bytes; - S_G.bytes_of_generation[g] += bytes; - /* lay down an end-of-segment marker */ - *(ptr*)old = forward_marker; - *((ptr*)old + 1) = new; - } - - /* base address of current block of segments to track amount of allocation */ - S_G.base_loc[g][s] = new; - - S_G.next_loc[g][s] = (ptr)((uptr)new + n); - S_G.bytes_left[g][s] = (nsegs * bytes_per_segment - n) - 2 * ptr_bytes; - - if (g == 0 && S_pants_down == 1) maybe_fire_collector(); - - S_pants_down -= 1; - return new; -} - -/* S_reset_allocation_pointer is always called with mutex */ -/* We always allocate exactly one segment for the allocation area, since - we can get into hot water with formerly locked objects, specifically - symbols and impure records, that cross segment boundaries. This allows - us to maintain the invariant that no object crosses a segment boundary - unless it starts on a segment boundary (and is thus at least one - segment long). NB. This invariant does not apply to code objects - since we grab large blocks of segments for them. -*/ - -void S_reset_allocation_pointer(ptr tc) { - iptr seg; - - S_pants_down += 1; - - seg = S_find_segments(space_new, 0, 1); - - /* NB: if allocate_segments didn't already ensure we don't use the last segment - of memory, we'd have to reject it here so cp2-alloc can avoid a carry check for - small allocation requests, using something like this: - - if (seg == (((uptr)1 << (ptr_bits - segment_offset_bits)) - 1)) - seg = S_find_segments(space_new, 0, 1); - */ - - S_G.bytes_of_space[0][space_new] += bytes_per_segment; - S_G.bytes_of_generation[0] += bytes_per_segment; - - if (S_pants_down == 1) maybe_fire_collector(); - - AP(tc) = build_ptr(seg, 0); - REAL_EAP(tc) = EAP(tc) = (ptr)((uptr)AP(tc) + bytes_per_segment); - - S_pants_down -= 1; -} - - -FORCEINLINE void mark_segment_dirty(seginfo *si, IGEN from_g, IGEN to_g) { - IGEN old_to_g = si->min_dirty_byte; - if (to_g < old_to_g) { - seginfo **pointer_to_first, *oldfirst; - if (old_to_g != 0xff) { - seginfo *next = si->dirty_next, **prev = si->dirty_prev; - /* presently on some other list, so remove */ - *prev = next; - if (next != NULL) next->dirty_prev = prev; - } - oldfirst = *(pointer_to_first = &DirtySegments(from_g, to_g)); - *pointer_to_first = si; - si->dirty_prev = pointer_to_first; - si->dirty_next = oldfirst; - if (oldfirst != NULL) oldfirst->dirty_prev = &si->dirty_next; - si->min_dirty_byte = to_g; - } -} - -void S_dirty_set(ptr *loc, ptr x) { - *loc = x; - if (!Sfixnump(x)) { - seginfo *si = SegInfo(addr_get_segment(loc)); - IGEN from_g = si->generation; - if (from_g != 0) { - si->dirty_bytes[((uptr)loc >> card_offset_bits) & ((1 << segment_card_offset_bits) - 1)] = 0; - mark_segment_dirty(si, from_g, 0); - } - } -} - -void S_mark_card_dirty(uptr card, IGEN to_g) { - uptr loc = card << card_offset_bits; - uptr seg = addr_get_segment(loc); - seginfo *si = SegInfo(seg); - uptr cardno = card & ((1 << segment_card_offset_bits) - 1); - if (to_g < si->dirty_bytes[cardno]) { - si->dirty_bytes[cardno] = to_g; - mark_segment_dirty(si, si->generation, to_g); - } -} - -/* scan remembered set from P to ENDP, transferring to dirty vector */ -void S_scan_dirty(ptr **p, ptr **endp) { - uptr this, last; - - last = 0; - - while (p < endp) { - ptr *loc = *p; - /* whether building s directory or running UXLB code, the most - common situations are that *loc is a fixnum, this == last, or loc - is in generation 0. the generated code no longer adds elements - to the remembered set if the RHS val is a fixnum. the other - checks we do here. we don't bother looking for *loc being an - immediate or outside the heap, nor for the generation of *loc - being the same or older than the generation of loc, since these - don't seem to weed out many dirty writes, and we don't want to - waste time here on fruitless memory reads and comparisions */ - if ((this = (uptr)loc >> card_offset_bits) != last) { - seginfo *si = SegInfo(addr_get_segment(loc)); - IGEN from_g = si->generation; - if (from_g != 0) { - si->dirty_bytes[((uptr)loc >> card_offset_bits) & ((1 << segment_card_offset_bits) - 1)] = 0; - if (this >> segment_card_offset_bits != last >> segment_card_offset_bits) mark_segment_dirty(si, from_g, 0); - } - last = this; - } - p += 1; - } -} - -/* S_scan_remembered_set is called from generated machine code when there - * is insufficient room for a remembered set addition. - */ - -void S_scan_remembered_set(void) { - ptr tc = get_thread_context(); - uptr ap, eap, real_eap; - - tc_mutex_acquire() - - ap = (uptr)AP(tc); - eap = (uptr)EAP(tc); - real_eap = (uptr)REAL_EAP(tc); - - S_scan_dirty((ptr **)eap, (ptr **)real_eap); - eap = real_eap; - - if (eap - ap > alloc_waste_maximum) { - AP(tc) = (ptr)ap; - EAP(tc) = (ptr)eap; - } else { - uptr bytes = eap - ap; - S_G.bytes_of_space[0][space_new] -= bytes; - S_G.bytes_of_generation[0] -= bytes; - S_reset_allocation_pointer(tc); - } - - tc_mutex_release() -} - -/* S_get_more_room is called from generated machine code when there is - * insufficient room for an allocation. ap has already been incremented - * by the size of the object and xp is a (typed) pointer to the value of - * ap before the allocation attempt. xp must be set to a new object of - * the appropriate type and size. - */ - -void S_get_more_room(void) { - ptr tc = get_thread_context(); - ptr xp; uptr ap, type, size; - - xp = XP(tc); - if ((type = TYPEBITS(xp)) == 0) type = typemod; - ap = (uptr)UNTYPE(xp, type); - size = (uptr)((iptr)AP(tc) - (iptr)ap); - - XP(tc) = S_get_more_room_help(tc, ap, type, size); -} - -ptr S_get_more_room_help(ptr tc, uptr ap, uptr type, uptr size) { - ptr x; uptr eap, real_eap; - - eap = (uptr)EAP(tc); - real_eap = (uptr)REAL_EAP(tc); - - tc_mutex_acquire() - - S_scan_dirty((ptr **)eap, (ptr **)real_eap); - eap = real_eap; - - if (eap - ap >= size) { - x = TYPE(ap, type); - ap += size; - if (eap - ap > alloc_waste_maximum) { - AP(tc) = (ptr)ap; - EAP(tc) = (ptr)eap; - } else { - uptr bytes = eap - ap; - S_G.bytes_of_space[0][space_new] -= bytes; - S_G.bytes_of_generation[0] -= bytes; - S_reset_allocation_pointer(tc); - } - } else if (eap - ap > alloc_waste_maximum) { - AP(tc) = (ptr)ap; - EAP(tc) = (ptr)eap; - find_room(space_new, 0, type, size, x); - } else { - uptr bytes = eap - ap; - S_G.bytes_of_space[0][space_new] -= bytes; - S_G.bytes_of_generation[0] -= bytes; - S_reset_allocation_pointer(tc); - ap = (uptr)AP(tc); - if (size + alloc_waste_maximum <= (uptr)EAP(tc) - ap) { - x = TYPE(ap, type); - AP(tc) = (ptr)(ap + size); - } else { - find_room(space_new, 0, type, size, x); - } - } - - tc_mutex_release() - - return x; -} - -/* S_cons_in is always called with mutex */ -ptr S_cons_in(ISPC s, IGEN g, ptr car, ptr cdr) { - ptr p; - - find_room(s, g, type_pair, size_pair, p); - INITCAR(p) = car; - INITCDR(p) = cdr; - return p; -} - -ptr Scons(ptr car, ptr cdr) { - ptr tc = get_thread_context(); - ptr p; - - thread_find_room(tc, type_pair, size_pair, p); - INITCAR(p) = car; - INITCDR(p) = cdr; - return p; -} - -ptr Sbox(ptr ref) { - ptr tc = get_thread_context(); - ptr p; - - thread_find_room(tc, type_typed_object, size_box, p); - BOXTYPE(p) = type_box; - INITBOXREF(p) = ref; - return p; -} - -ptr S_symbol(ptr name) { - ptr tc = get_thread_context(); - ptr p; - - thread_find_room(tc, type_symbol, size_symbol, p); - /* changes here should be reflected in the oblist collection code in gc.c */ - INITSYMVAL(p) = sunbound; - INITSYMCODE(p,S_G.nonprocedure_code); - INITSYMPLIST(p) = snil; - INITSYMSPLIST(p) = snil; - INITSYMNAME(p) = name; - INITSYMHASH(p) = Sfalse; - return p; -} - -ptr S_rational(ptr n, ptr d) { - if (d == FIX(1)) return n; - else { - ptr tc = get_thread_context(); - ptr p; - - thread_find_room(tc, type_typed_object, size_ratnum, p); - RATTYPE(p) = type_ratnum; - RATNUM(p) = n; - RATDEN(p) = d; - return p; - } -} - -ptr S_tlc(ptr keyval, ptr ht, ptr next) { - ptr tc = get_thread_context(); - ptr p; - - thread_find_room(tc, type_typed_object, size_tlc, p); - TLCTYPE(p) = type_tlc; - INITTLCKEYVAL(p) = keyval; - INITTLCHT(p) = ht; - INITTLCNEXT(p) = next; - return p; -} - -/* S_vector_in is always called with mutex */ -ptr S_vector_in(ISPC s, IGEN g, iptr n) { - ptr p; iptr d; - - if (n == 0) return S_G.null_vector; - - if ((uptr)n >= maximum_vector_length) - S_error("", "invalid vector size request"); - - d = size_vector(n); - /* S_vector_in always called with mutex */ - find_room(s, g, type_typed_object, d, p); - VECTTYPE(p) = (n << vector_length_offset) | type_vector; - return p; -} - -ptr S_vector(iptr n) { - ptr tc; - ptr p; iptr d; - - if (n == 0) return S_G.null_vector; - - if ((uptr)n >= maximum_vector_length) - S_error("", "invalid vector size request"); - - tc = get_thread_context(); - - d = size_vector(n); - thread_find_room(tc, type_typed_object, d, p); - VECTTYPE(p) = (n << vector_length_offset) | type_vector; - return p; -} - -ptr S_fxvector(iptr n) { - ptr tc; - ptr p; iptr d; - - if (n == 0) return S_G.null_fxvector; - - if ((uptr)n > (uptr)maximum_fxvector_length) - S_error("", "invalid fxvector size request"); - - tc = get_thread_context(); - - d = size_fxvector(n); - thread_find_room(tc, type_typed_object, d, p); - FXVECTOR_TYPE(p) = (n << fxvector_length_offset) | type_fxvector; - return p; -} - -ptr S_bytevector(iptr n) { - ptr tc; - ptr p; iptr d; - - if (n == 0) return S_G.null_bytevector; - - if ((uptr)n > (uptr)maximum_bytevector_length) - S_error("", "invalid bytevector size request"); - - tc = get_thread_context(); - - d = size_bytevector(n); - thread_find_room(tc, type_typed_object, d, p); - BYTEVECTOR_TYPE(p) = (n << bytevector_length_offset) | type_bytevector; - return p; -} - -ptr S_null_immutable_vector(void) { - ptr v; - find_room(space_new, 0, type_typed_object, size_vector(0), v); - VECTTYPE(v) = (0 << vector_length_offset) | type_vector | vector_immutable_flag; - return v; -} - -ptr S_null_immutable_fxvector(void) { - ptr v; - find_room(space_new, 0, type_typed_object, size_fxvector(0), v); - VECTTYPE(v) = (0 << fxvector_length_offset) | type_fxvector | fxvector_immutable_flag; - return v; -} - -ptr S_null_immutable_bytevector(void) { - ptr v; - find_room(space_new, 0, type_typed_object, size_bytevector(0), v); - VECTTYPE(v) = (0 << bytevector_length_offset) | type_bytevector | bytevector_immutable_flag; - return v; -} - -ptr S_null_immutable_string(void) { - ptr v; - find_room(space_new, 0, type_typed_object, size_string(0), v); - VECTTYPE(v) = (0 << string_length_offset) | type_string | string_immutable_flag; - return v; -} - -ptr S_record(iptr n) { - ptr tc = get_thread_context(); - ptr p; - - thread_find_room(tc, type_typed_object, n, p); - return p; -} - -ptr S_closure(ptr cod, iptr n) { - ptr tc = get_thread_context(); - ptr p; iptr d; - - d = size_closure(n); - thread_find_room(tc, type_closure, d, p); - CLOSENTRY(p) = cod; - return p; -} - -/* S_mkcontinuation is always called with mutex */ -ptr S_mkcontinuation(ISPC s, IGEN g, ptr nuate, ptr stack, iptr length, iptr clength, - ptr link, ptr ret, ptr winders) { - ptr p; - - find_room(s, g, type_closure, size_continuation, p); - CLOSENTRY(p) = nuate; - CONTSTACK(p) = stack; - CONTLENGTH(p) = length; - CONTCLENGTH(p) = clength; - CONTLINK(p) = link; - CONTRET(p) = ret; - CONTWINDERS(p) = winders; - return p; -} - -ptr Sflonum(double x) { - ptr tc = get_thread_context(); - ptr p; - - thread_find_room(tc, type_flonum, size_flonum, p); - FLODAT(p) = x; - return p; -} - -ptr S_inexactnum(double rp, double ip) { - ptr tc = get_thread_context(); - ptr p; - - thread_find_room(tc, type_typed_object, size_inexactnum, p); - INEXACTNUM_TYPE(p) = type_inexactnum; - INEXACTNUM_REAL_PART(p) = rp; - INEXACTNUM_IMAG_PART(p) = ip; - return p; -} - -/* S_thread is always called with mutex */ -ptr S_thread(ptr xtc) { - ptr p; - - /* don't use thread_find_room since we may be building the current thread */ - find_room(space_new, 0, type_typed_object, size_thread, p); - TYPEFIELD(p) = (ptr)type_thread; - THREADTC(p) = (uptr)xtc; - return p; -} - -ptr S_exactnum(ptr a, ptr b) { - ptr tc = get_thread_context(); - ptr p; - - thread_find_room(tc, type_typed_object, size_exactnum, p); - EXACTNUM_TYPE(p) = type_exactnum; - EXACTNUM_REAL_PART(p) = a; - EXACTNUM_IMAG_PART(p) = b; - return p; -} - -/* S_string returns a new string of length n. If s is not NULL, it is - * copied into the new string. If n < 0, then s must be non-NULL, - * and the length of s (by strlen) determines the length of the string */ -ptr S_string(const char *s, iptr n) { - ptr tc; - ptr p; iptr d; - iptr i; - - if (n < 0) n = strlen(s); - - if (n == 0) return S_G.null_string; - - if ((uptr)n > (uptr)maximum_string_length) - S_error("", "invalid string size request"); - - tc = get_thread_context(); - - d = size_string(n); - thread_find_room(tc, type_typed_object, d, p); - STRTYPE(p) = (n << string_length_offset) | type_string; - - /* fill the string with valid characters */ - i = 0; - - /* first copy input string, if any */ - if (s != (char *)NULL) { - while (i != n && *s != 0) { - Sstring_set(p, i, *s++); - i += 1; - } - } - - /* fill remaining slots with nul */ - while (i != n) { - Sstring_set(p, i, 0); - i += 1; - } - - return p; -} - -ptr Sstring_utf8(const char *s, iptr n) { - const char* u8; - iptr cc, d, i, n8; - ptr p, tc; - - if (n < 0) n = strlen(s); - - if (n == 0) return S_G.null_string; - - /* determine code point count cc */ - u8 = s; - n8 = n; - cc = 0; - while (n8 > 0) { - unsigned char b1 = *(const unsigned char*)u8++; - n8--; - cc++; - if ((b1 & 0x80) == 0) - ; - else if ((b1 & 0x40) == 0) - ; - else if ((b1 & 0x20) == 0) { - if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) { - u8++; - n8--; - } - } else if ((b1 & 0x10) == 0) { - if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) { - u8++; - n8--; - if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) { - u8++; - n8--; - } - } - } else if ((b1 & 0x08) == 0) { - if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) { - u8++; - n8--; - if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) { - u8++; - n8--; - if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) { - u8++; - n8--; - } - } - } - } - } - - if ((uptr)cc > (uptr)maximum_string_length) - S_error("", "invalid string size request"); - - tc = get_thread_context(); - d = size_string(cc); - thread_find_room(tc, type_typed_object, d, p); - STRTYPE(p) = (cc << string_length_offset) | type_string; - - /* fill the string */ - u8 = s; - n8 = n; - i = 0; - while (n8 > 0) { - unsigned char b1 = *u8++; - int c = 0xfffd; - n8--; - if ((b1 & 0x80) == 0) - c = b1; - else if ((b1 & 0x40) == 0) - ; - else if ((b1 & 0x20) == 0) { - unsigned char b2; - if ((n8 >= 1) && (((b2 = *u8) & 0xc0) == 0x80)) { - int x = ((b1 & 0x1f) << 6) | (b2 & 0x3f); - u8++; - n8--; - if (x >= 0x80) - c = x; - } - } else if ((b1 & 0x10) == 0) { - unsigned char b2; - if ((n8 >= 1) && (((b2 = *u8) & 0xc0) == 0x80)) { - unsigned char b3; - u8++; - n8--; - if ((n8 >= 1) && (((b3 = *u8) & 0xc0) == 0x80)) { - int x = ((b1 & 0x0f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); - u8++; - n8--; - if ((x >= 0x800) && ((x < 0xd800) || (x > 0xdfff))) - c = x; - } - } - } else if ((b1 & 0x08) == 0) { - unsigned char b2; - if ((n8 >= 1) && (((b2 = *u8) & 0xc0) == 0x80)) { - unsigned char b3; - u8++; - n8--; - if ((n8 >= 1) && (((b3 = *u8) & 0xc0) == 0x80)) { - unsigned char b4; - u8++; - n8--; - if ((n8 >= 1) && (((b4 = *u8) & 0xc0) == 0x80)) { - int x = ((b1 & 0x07) << 18) | ((b2 & 0x3f) << 12) | ((b3 & 0x3f) << 6) | (b4 & 0x3f); - u8++; - n8--; - if ((x >= 0x10000) && (x <= 0x10ffff)) - c = x; - } - } - } - } - Sstring_set(p, i++, c); - } - return p; -} - -ptr S_bignum(ptr tc, iptr n, IBOOL sign) { - ptr p; iptr d; - - if ((uptr)n > (uptr)maximum_bignum_length) - S_error("", "invalid bignum size request"); - - d = size_bignum(n); - thread_find_room(tc, type_typed_object, d, p); - BIGTYPE(p) = (uptr)n << bignum_length_offset | sign << bignum_sign_offset | type_bignum; - return p; -} - -/* S_code is always called with mutex */ -ptr S_code(ptr tc, iptr type, iptr n) { - ptr p; iptr d; - - d = size_code(n); - find_room(space_code, 0, type_typed_object, d, p); - CODETYPE(p) = type; - CODELEN(p) = n; - /* we record the code modification here, even though we haven't - even started modifying the code yet, since we always create - and fill the code object within a critical section. */ - S_record_code_mod(tc, (uptr)&CODEIT(p,0), (uptr)n); - return p; -} - -ptr S_relocation_table(iptr n) { - ptr tc = get_thread_context(); - ptr p; iptr d; - - d = size_reloc_table(n); - thread_find_room(tc, typemod, d, p); - RELOCSIZE(p) = n; - return p; -} - -ptr S_weak_cons(ptr car, ptr cdr) { - ptr p; - tc_mutex_acquire(); - p = S_cons_in(space_weakpair, 0, car, cdr); - tc_mutex_release(); - return p; -} diff --git a/ta6ob/c/alloc.o b/ta6ob/c/alloc.o deleted file mode 100644 index 1219037..0000000 Binary files a/ta6ob/c/alloc.o and /dev/null differ diff --git a/ta6ob/c/compress-io.c b/ta6ob/c/compress-io.c deleted file mode 100644 index 6333648..0000000 --- a/ta6ob/c/compress-io.c +++ /dev/null @@ -1,672 +0,0 @@ -/* compress-io.c - * Copyright 1984-2019 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Dispatch to zlib or LZ4 */ - -#include "system.h" -#include "zlib.h" -#include "lz4.h" -#include "lz4frame.h" -#include "lz4hc.h" -#include -#include - -#ifdef WIN32 -#include -# define WIN32_IZE(id) _ ## id -# define GLZ_O_BINARY O_BINARY -#else -# define WIN32_IZE(id) id -# define GLZ_O_BINARY 0 -#endif - -/* the value of LZ4_OUTPUT_PORT_IN_BUFFER_SIZE was determined - through experimentation on an intel linux server and an intel - osx laptop. smaller sizes result in significantly worse compression - of object files, and larger sizes don't have much beneficial effect. - don't increase the output-port in-buffer size unless you're sure - it reduces object-file size or reduces compression time - significantly. don't decrease it unless you're sure it doesn't - increase object-file size significantly. one buffer of size - LZ4_OUTPUT_PORT_IN_BUFFER_SIZE is allocated per lz4-compressed - output port. another buffer of a closely related size is allocated - per thread. */ -#define LZ4_OUTPUT_PORT_IN_BUFFER_SIZE (1 << 18) - -/* the values we choose for LZ4_INPUT_PORT_IN_BUFFER_SIZE and - LZ4_INPUT_PORT_OUT_BUFFER_SIZE don't seem to make much difference - in decompression speed, so we keep them fairly small. one buffer - of size LZ4_INPUT_PORT_IN_BUFFER_SIZE and one buffer of size - LZ4_INPUT_PORT_OUT_BUFFER_SIZE are allocated per lz4-compressed - input port. */ -#define LZ4_INPUT_PORT_IN_BUFFER_SIZE (1 << 12) -#define LZ4_INPUT_PORT_OUT_BUFFER_SIZE (1 << 14) - -typedef struct lz4File_out_r { - LZ4F_preferences_t preferences; - INT fd; - INT out_buffer_size; - INT in_pos; - INT err; - size_t stream_pos; - char in_buffer[LZ4_OUTPUT_PORT_IN_BUFFER_SIZE]; -} lz4File_out; - -typedef struct lz4File_in_r { - INT fd; - LZ4F_dctx *dctx; - INT in_pos, in_len, out_pos, out_len; - INT frame_ended; - INT err; - size_t stream_pos; - off_t init_pos; - char in_buffer[LZ4_INPUT_PORT_IN_BUFFER_SIZE]; - char out_buffer[LZ4_INPUT_PORT_OUT_BUFFER_SIZE]; -} lz4File_in; - -typedef struct sized_buffer_r { - INT size; - char buffer[0]; -} sized_buffer; - -/* local functions */ -static glzFile glzdopen_output_gz(INT fd, INT compress_level); -static glzFile glzdopen_output_lz4(INT fd, INT compress_level); -static glzFile glzdopen_input_gz(INT fd); -static glzFile glzdopen_input_lz4(INT fd, off_t init_pos); -static INT glzread_lz4(lz4File_in *lz4, void *buffer, UINT count); -static INT glzemit_lz4(lz4File_out *lz4, void *buffer, UINT count); -static INT glzwrite_lz4(lz4File_out *lz4, void *buffer, UINT count); - -INT S_zlib_compress_level(INT compress_level) { - switch (compress_level) { - case COMPRESS_MIN: - case COMPRESS_LOW: - return Z_BEST_SPEED; - case COMPRESS_MEDIUM: - return (Z_BEST_SPEED + Z_BEST_COMPRESSION) / 2; - case COMPRESS_HIGH: - return (Z_BEST_SPEED + (3 * Z_BEST_COMPRESSION)) / 4; - case COMPRESS_MAX: - return Z_BEST_COMPRESSION; - default: - S_error1("S_zlib_compress_level", "unexpected compress level ~s", Sinteger(compress_level)); - return 0; - } -} - -static glzFile glzdopen_output_gz(INT fd, INT compress_level) { - gzFile gz; - glzFile glz; - INT as_append; - INT level; - -#ifdef WIN32 - as_append = 0; -#else - as_append = fcntl(fd, F_GETFL) & O_APPEND; -#endif - - if ((gz = gzdopen(fd, as_append ? "ab" : "wb")) == Z_NULL) return Z_NULL; - - level = S_zlib_compress_level(compress_level); - - gzsetparams(gz, level, Z_DEFAULT_STRATEGY); - - if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) { - (void)gzclose(gz); - return Z_NULL; - } - glz->fd = fd; - glz->inputp = 0; - glz->format = COMPRESS_GZIP; - glz->gz = gz; - return glz; -} - -INT S_lz4_compress_level(INT compress_level) { - switch (compress_level) { - case COMPRESS_MIN: - case COMPRESS_LOW: - return 1; - case COMPRESS_MEDIUM: - return LZ4HC_CLEVEL_MIN; - case COMPRESS_HIGH: - return (LZ4HC_CLEVEL_MIN + LZ4HC_CLEVEL_MAX) / 2; - case COMPRESS_MAX: - return LZ4HC_CLEVEL_MAX; - default: - S_error1("S_lz4_compress_level", "unexpected compress level ~s", Sinteger(compress_level)); - return 0; - } -} - -static glzFile glzdopen_output_lz4(INT fd, INT compress_level) { - glzFile glz; - lz4File_out *lz4; - INT level; - - level = S_lz4_compress_level(compress_level); - - if ((lz4 = malloc(sizeof(lz4File_out))) == NULL) return Z_NULL; - memset(&lz4->preferences, 0, sizeof(LZ4F_preferences_t)); - lz4->preferences.compressionLevel = level; - lz4->fd = fd; - lz4->out_buffer_size = (INT)LZ4F_compressFrameBound(LZ4_OUTPUT_PORT_IN_BUFFER_SIZE, &lz4->preferences); - lz4->in_pos = 0; - lz4->err = 0; - lz4->stream_pos = 0; - - if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) { - free(lz4); - return Z_NULL; - } - glz->fd = fd; - glz->inputp = 0; - glz->format = COMPRESS_LZ4; - glz->lz4_out = lz4; - return glz; -} - -glzFile S_glzdopen_output(INT fd, INT compress_format, INT compress_level) { - switch (compress_format) { - case COMPRESS_GZIP: - return glzdopen_output_gz(fd, compress_level); - case COMPRESS_LZ4: - return glzdopen_output_lz4(fd, compress_level); - default: - S_error1("glzdopen_output", "unexpected compress format ~s", Sinteger(compress_format)); - return Z_NULL; - } -} - -static glzFile glzdopen_input_gz(INT fd) { - gzFile gz; - glzFile glz; - - if ((gz = gzdopen(fd, "rb")) == Z_NULL) return Z_NULL; - - if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) { - (void)gzclose(gz); - return Z_NULL; - } - glz->fd = fd; - glz->inputp = 1; - glz->format = COMPRESS_GZIP; - glz->gz = gz; - return glz; -} - -static glzFile glzdopen_input_lz4(INT fd, off_t init_pos) { - glzFile glz; - LZ4F_dctx *dctx; - LZ4F_errorCode_t r; - lz4File_in *lz4; - - r = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION); - if (LZ4F_isError(r)) - return Z_NULL; - - if ((lz4 = malloc(sizeof(lz4File_in))) == NULL) { - (void)LZ4F_freeDecompressionContext(dctx); - return Z_NULL; - } - lz4->fd = fd; - lz4->dctx = dctx; - lz4->in_pos = 0; - lz4->in_len = 0; - lz4->out_len = 0; - lz4->out_pos = 0; - lz4->frame_ended = 0; - lz4->err = 0; - lz4->stream_pos = 0; - lz4->init_pos = init_pos; - - if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) { - (void)LZ4F_freeDecompressionContext(lz4->dctx); - free(lz4); - return Z_NULL; - } - glz->fd = fd; - glz->inputp = 1; - glz->format = COMPRESS_LZ4; - glz->lz4_in = lz4; - return glz; -} - -glzFile S_glzdopen_input(INT fd) { - INT r, pos = 0; - unsigned char buffer[4]; - off_t init_pos; - - /* check for LZ4 magic number, otherwise defer to gzdopen */ - - if ((init_pos = WIN32_IZE(lseek)(fd, 0, SEEK_CUR)) == -1) return Z_NULL; - - while (pos < 4) { - r = WIN32_IZE(read)(fd, (char*)buffer + pos, 4 - pos); - if (r == 0) - break; - else if (r > 0) - pos += r; -#ifdef EINTR - else if (errno == EINTR) - continue; -#endif - else - break; /* error reading */ - } - - if (pos > 0) { - if (WIN32_IZE(lseek)(fd, init_pos, SEEK_SET) == -1) return Z_NULL; - } - - if ((pos == 4) - && (buffer[0] == 0x04) - && (buffer[1] == 0x22) - && (buffer[2] == 0x4d) - && (buffer[3] == 0x18)) - return glzdopen_input_lz4(fd, init_pos); - - return glzdopen_input_gz(fd); -} - -glzFile S_glzopen_input(const char *path) { - INT fd; - - fd = WIN32_IZE(open)(path, O_RDONLY | GLZ_O_BINARY); - - if (fd == -1) - return Z_NULL; - else - return S_glzdopen_input(fd); -} - -#ifdef WIN32 -glzFile S_glzopen_input_w(const wchar_t *path) { - INT fd; - - fd = _wopen(path, O_RDONLY | GLZ_O_BINARY); - - if (fd == -1) - return Z_NULL; - else - return S_glzdopen_input(fd); -} -#endif - -IBOOL S_glzdirect(glzFile glz) { - if (glz->format == COMPRESS_GZIP) - return gzdirect(glz->gz); - else - return 0; -} - -INT S_glzclose(glzFile glz) { - INT r = Z_OK, saved_errno = 0; - switch (glz->format) { - case COMPRESS_GZIP: - r = gzclose(glz->gz); - break; - case COMPRESS_LZ4: - if (glz->inputp) { - lz4File_in *lz4 = glz->lz4_in; - while (1) { - INT r = WIN32_IZE(close)(lz4->fd); -#ifdef EINTR - if (r < 0 && errno == EINTR) continue; -#endif - if (r == 0) { saved_errno = errno; } - break; - } - (void)LZ4F_freeDecompressionContext(lz4->dctx); - free(lz4); - } else { - lz4File_out *lz4 = glz->lz4_out; - if (lz4->in_pos != 0) { - r = glzemit_lz4(lz4, lz4->in_buffer, lz4->in_pos); - if (r >= 0) r = Z_OK; else { r = Z_ERRNO; saved_errno = errno; } - } - while (1) { - int r1 = WIN32_IZE(close)(lz4->fd); -#ifdef EINTR - if (r1 < 0 && errno == EINTR) continue; -#endif - if (r == Z_OK && r1 < 0) { r = Z_ERRNO; saved_errno = errno; } - break; - } - free(lz4); - } - break; - default: - S_error1("S_glzclose", "unexpected compress format ~s", Sinteger(glz->format)); - } - free(glz); - if (saved_errno) errno = saved_errno; - return r; -} - -static INT glzread_lz4(lz4File_in *lz4, void *buffer, UINT count) { - while (lz4->out_pos == lz4->out_len) { - INT in_avail; - - in_avail = lz4->in_len - lz4->in_pos; - if (!in_avail) { - while (1) { - in_avail = WIN32_IZE(read)(lz4->fd, lz4->in_buffer, LZ4_INPUT_PORT_IN_BUFFER_SIZE); - if (in_avail >= 0) { - lz4->in_len = in_avail; - lz4->in_pos = 0; - break; -#ifdef EINTR - } else if (errno == EINTR) { - /* try again */ -#endif - } else { - lz4->err = Z_ERRNO; - return -1; - } - } - } - - if (in_avail > 0) { - size_t amt, out_len = LZ4_INPUT_PORT_OUT_BUFFER_SIZE, in_len = in_avail; - - /* For a large enough result buffer, try to decompress directly - to that buffer: */ - if (count >= (out_len >> 1)) { - size_t direct_out_len = count; - - if (lz4->frame_ended && lz4->in_buffer[lz4->in_pos] == 0) - return 0; /* count 0 after frame as stream terminator */ - - amt = LZ4F_decompress(lz4->dctx, - buffer, &direct_out_len, - lz4->in_buffer + lz4->in_pos, &in_len, - NULL); - lz4->frame_ended = (amt == 0); - - if (LZ4F_isError(amt)) { - lz4->err = Z_STREAM_ERROR; - return -1; - } - - lz4->in_pos += (INT)in_len; - - if (direct_out_len) { - lz4->stream_pos += direct_out_len; - return (INT)direct_out_len; - } - - in_len = in_avail - in_len; - } - - if (in_len > 0) { - if (lz4->frame_ended && lz4->in_buffer[lz4->in_pos] == 0) - return 0; /* count 0 after frame as stream terminator */ - - amt = LZ4F_decompress(lz4->dctx, - lz4->out_buffer, &out_len, - lz4->in_buffer + lz4->in_pos, &in_len, - NULL); - lz4->frame_ended = (amt == 0); - - if (LZ4F_isError(amt)) { - lz4->err = Z_STREAM_ERROR; - return -1; - } - - lz4->in_pos += (INT)in_len; - lz4->out_len = (INT)out_len; - lz4->out_pos = 0; - } - } else { - /* EOF on read */ - break; - } - } - - if (lz4->out_pos < lz4->out_len) { - UINT amt = lz4->out_len - lz4->out_pos; - if (amt > count) amt = count; - memcpy(buffer, lz4->out_buffer + lz4->out_pos, amt); - lz4->out_pos += amt; - lz4->stream_pos += amt; - return amt; - } - - return 0; -} - -INT S_glzread(glzFile glz, void *buffer, UINT count) { - switch (glz->format) { - case COMPRESS_GZIP: - return gzread(glz->gz, buffer, count); - case COMPRESS_LZ4: - return glzread_lz4(glz->lz4_in, buffer, count); - default: - S_error1("S_glzread", "unexpected compress format ~s", Sinteger(glz->format)); - return -1; - } -} - -static INT glzemit_lz4(lz4File_out *lz4, void *buffer, UINT count) { - ptr tc = get_thread_context(); - sized_buffer *cached_out_buffer; - char *out_buffer; - INT out_len, out_pos; - INT r = 0; - - /* allocate one out_buffer (per thread) since we don't need one for each file. - the buffer is freed by destroy_thread. */ - if ((cached_out_buffer = LZ4OUTBUFFER(tc)) == NULL || cached_out_buffer->size < lz4->out_buffer_size) { - if (cached_out_buffer != NULL) free(cached_out_buffer); - if ((LZ4OUTBUFFER(tc) = cached_out_buffer = malloc(sizeof(sized_buffer) + lz4->out_buffer_size)) == NULL) return -1; - cached_out_buffer->size = lz4->out_buffer_size; - } - out_buffer = cached_out_buffer->buffer; - - out_len = (INT)LZ4F_compressFrame(out_buffer, lz4->out_buffer_size, - buffer, count, - &lz4->preferences); - if (LZ4F_isError(out_len)) { - lz4->err = Z_STREAM_ERROR; - return -1; - } - - out_pos = 0; - while (out_pos < out_len) { - r = WIN32_IZE(write)(lz4->fd, out_buffer + out_pos, out_len - out_pos); - if (r >= 0) - out_pos += r; -#ifdef EINTR - else if (errno == EINTR) - continue; -#endif - else - break; - } - - return r; -} - -static INT glzwrite_lz4(lz4File_out *lz4, void *buffer, UINT count) { - UINT amt; INT r; - - if ((amt = LZ4_OUTPUT_PORT_IN_BUFFER_SIZE - lz4->in_pos) > count) amt = count; - - if (amt == LZ4_OUTPUT_PORT_IN_BUFFER_SIZE) { - /* full buffer coming from input...skip the memcpy */ - if ((r = glzemit_lz4(lz4, buffer, LZ4_OUTPUT_PORT_IN_BUFFER_SIZE)) < 0) return 0; - } else { - memcpy(lz4->in_buffer + lz4->in_pos, buffer, amt); - if ((lz4->in_pos += amt) == LZ4_OUTPUT_PORT_IN_BUFFER_SIZE) { - lz4->in_pos = 0; - if ((r = glzemit_lz4(lz4, lz4->in_buffer, LZ4_OUTPUT_PORT_IN_BUFFER_SIZE)) < 0) return 0; - } - } - - lz4->stream_pos += amt; - return amt; -} - -INT S_glzwrite(glzFile glz, void *buffer, UINT count) { - switch (glz->format) { - case COMPRESS_GZIP: - return gzwrite(glz->gz, buffer, count); - case COMPRESS_LZ4: - return glzwrite_lz4(glz->lz4_out, buffer, count); - default: - S_error1("S_glzwrite", "unexpected compress format ~s", Sinteger(glz->format)); - return -1; - } -} - -long S_glzseek(glzFile glz, long offset, INT whence) { - switch (glz->format) { - case COMPRESS_GZIP: - return gzseek(glz->gz, offset, whence); - case COMPRESS_LZ4: - if (glz->inputp) { - lz4File_in *lz4 = glz->lz4_in; - if (whence == SEEK_CUR) - offset += (long)lz4->stream_pos; - if (offset < 0) - offset = 0; - if ((size_t)offset < lz4->stream_pos) { - /* rewind and read from start */ - if (WIN32_IZE(lseek)(lz4->fd, lz4->init_pos, SEEK_SET) < 0) { - lz4->err = Z_ERRNO; - return -1; - } - LZ4F_resetDecompressionContext(lz4->dctx); - lz4->in_pos = 0; - lz4->in_len = 0; - lz4->out_len = 0; - lz4->out_pos = 0; - lz4->err = 0; - lz4->stream_pos = 0; - } - while ((size_t)offset > lz4->stream_pos) { - static char buffer[1024]; - size_t amt = (size_t)offset - lz4->stream_pos; - if (amt > sizeof(buffer)) amt = sizeof(buffer); - if (glzread_lz4(lz4, buffer, (UINT)amt) < 0) - return -1; - } - return (long)lz4->stream_pos; - } else { - lz4File_out *lz4 = glz->lz4_out; - if (whence == SEEK_CUR) - offset += (long)lz4->stream_pos; - if (offset >= 0) { - while ((size_t)offset > lz4->stream_pos) { - size_t amt = (size_t)offset - lz4->stream_pos; - if (amt > 8) amt = 8; - if (glzwrite_lz4(lz4, "\0\0\0\0\0\0\0\0", (UINT)amt) < 0) - return -1; - } - } - return (long)lz4->stream_pos; - } - default: - S_error1("S_glzseek", "unexpected compress format ~s", Sinteger(glz->format)); - return -1; - } -} - -INT S_glzgetc(glzFile glz) { - switch (glz->format) { - case COMPRESS_GZIP: - return gzgetc(glz->gz); - case COMPRESS_LZ4: - { - unsigned char buffer[1]; - INT r; - r = S_glzread(glz, buffer, 1); - if (r == 1) - return buffer[0]; - else - return -1; - } - default: - S_error1("S_glzgetc", "unexpected compress format ~s", Sinteger(glz->format)); - return -1; - } -} - -INT S_glzungetc(INT c, glzFile glz) { - switch (glz->format) { - case COMPRESS_GZIP: - return gzungetc(c, glz->gz); - case COMPRESS_LZ4: - { - lz4File_in *lz4 = glz->lz4_in; - if (lz4->out_len == 0) - lz4->out_len = lz4->out_pos = 1; - if (lz4->out_pos) { - lz4->out_pos--; - lz4->out_buffer[lz4->out_pos] = c; - lz4->stream_pos--; - return c; - } else { - /* support ungetc only just after a getc, in which case there - should have been room */ - return -1; - } - } - default: - S_error1("S_glzungetc", "unexpected compress format ~s", Sinteger(glz->format)); - return -1; - } -} - -INT S_glzrewind(glzFile glz) { - return S_glzseek(glz, 0, SEEK_SET); -} - -void S_glzerror(glzFile glz, INT *errnum) { - switch (glz->format) { - case COMPRESS_GZIP: - (void)gzerror(glz->gz, errnum); - break; - case COMPRESS_LZ4: - if (glz->inputp) - *errnum = glz->lz4_in->err; - else - *errnum = glz->lz4_out->err; - break; - default: - S_error1("S_glzerror", "unexpected compress format ~s", Sinteger(glz->format)); - *errnum = 0; - } -} - -void S_glzclearerr(glzFile glz) { - switch (glz->format) { - case COMPRESS_GZIP: - gzclearerr(glz->gz); - break; - case COMPRESS_LZ4: - if (glz->inputp) - glz->lz4_in->err = 0; - else - glz->lz4_out->err = 0; - break; - default: - S_error1("S_glzerror", "unexpected compress format ~s", Sinteger(glz->format)); - } -} diff --git a/ta6ob/c/compress-io.h b/ta6ob/c/compress-io.h deleted file mode 100644 index a5f988b..0000000 --- a/ta6ob/c/compress-io.h +++ /dev/null @@ -1,26 +0,0 @@ -/* compress-io.h - * Copyright 1984-2019 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -typedef struct glzFile_r { - INT fd; - IBOOL inputp; - INT format; - union { - struct gzFile_s *gz; - struct lz4File_in_r *lz4_in; - struct lz4File_out_r *lz4_out; - }; -} *glzFile; diff --git a/ta6ob/c/compress-io.o b/ta6ob/c/compress-io.o deleted file mode 100644 index 7487efe..0000000 Binary files a/ta6ob/c/compress-io.o and /dev/null differ diff --git a/ta6ob/c/config.h b/ta6ob/c/config.h deleted file mode 100644 index 2817b36..0000000 --- a/ta6ob/c/config.h +++ /dev/null @@ -1,4 +0,0 @@ -#define SCHEME_SCRIPT "scheme-script" -#ifndef WIN32 -#define DEFAULT_HEAP_PATH "/usr/local/lib/csv%v/%m" -#endif diff --git a/ta6ob/c/expeditor.c b/ta6ob/c/expeditor.c deleted file mode 100644 index c148e96..0000000 --- a/ta6ob/c/expeditor.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* expeditor.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" - -#ifdef FEATURE_EXPEDITOR - -/* locally defined functions */ -static IBOOL s_ee_init_term(void); -static ptr s_ee_read_char(IBOOL blockp); -static void s_ee_write_char(wchar_t c); -static void s_ee_flush(void); -static ptr s_ee_get_screen_size(void); -static void s_ee_raw(void); -static void s_ee_noraw(void); -static void s_ee_enter_am_mode(void); -static void s_ee_exit_am_mode(void); -static void s_ee_pause(void); -static void s_ee_nanosleep(U32 secs, U32 nanosecs); -static ptr s_ee_get_clipboard(void); -static void s_ee_up(I32); -static void s_ee_down(I32); -static void s_ee_left(I32); -static void s_ee_right(I32); -static void s_ee_clear_eol(void); -static void s_ee_clear_eos(void); -static void s_ee_clear_screen(void); -static void s_ee_scroll_reverse(I32); -static void s_ee_bell(void); -static void s_ee_carriage_return(void); -static void s_ee_line_feed(void); - -static INT init_status = -1; - -#ifdef WIN32 - -#include -#include - -static HANDLE hStdout, hStdin; -static DWORD InMode, OutMode; - -static IBOOL s_ee_init_term(void) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - - if (init_status != -1) return init_status; - - init_status = - (hStdin = GetStdHandle(STD_INPUT_HANDLE)) != INVALID_HANDLE_VALUE - && (hStdout = GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE - && GetConsoleScreenBufferInfo(hStdout, &csbiInfo) - && GetConsoleMode(hStdin, &InMode) - && GetConsoleMode(hStdout, &OutMode); - - return init_status; -} - -/* returns char, eof, #t (winched), or #f (nothing ready), the latter - only if blockp is false */ -static ptr s_ee_read_char(IBOOL blockp) { - DWORD cNumRead; - INPUT_RECORD irInBuf[1]; -#ifdef PTHREADS - ptr tc; -#endif /* PTHREADS */ - BOOL succ; - static wchar_t buf[10]; - static int bufidx = 0; - static int buflen = 0; - static int rptcnt = 0; - - for (;;) { - if (buflen != 0) { - int i = bufidx++; - if (bufidx == buflen) { - bufidx = 0; - if (--rptcnt == 0) buflen = 0; - } - return Schar(buf[i]); - } - - if (!blockp) { - DWORD NumberOfEvents; - if (!GetNumberOfConsoleInputEvents(hStdin, &NumberOfEvents)) - S_error1("expeditor", "error getting console input: ~a", - S_LastErrorString()); - if (NumberOfEvents == 0) return Sfalse; - } - -#ifdef PTHREADS - tc = get_thread_context(); - if (DISABLECOUNT(tc) == FIX(0)) { - deactivate_thread(tc); - succ = ReadConsoleInputW(hStdin, irInBuf, 1, &cNumRead); - reactivate_thread(tc); - } else { - succ = ReadConsoleInputW(hStdin, irInBuf, 1, &cNumRead); - } -#else /* PTHREADS */ - succ = ReadConsoleInputW(hStdin, irInBuf, 1, &cNumRead); -#endif /* PTHREADS */ - - - if (!succ) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - if (cNumRead == 0) return Seof_object; - - switch(irInBuf[0].EventType) { - case KEY_EVENT: { - KEY_EVENT_RECORD ker = irInBuf[0].Event.KeyEvent; - rptcnt = ker.wRepeatCount; - if (ker.bKeyDown) { - wchar_t c; - - if (c = ker.uChar.UnicodeChar) { - /* translate ^ to nul */ - if (c == 0x20 && (ker.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))) - buf[0] = 0; - else - buf[0] = c; - buflen = 1; - } else { - switch (ker.wVirtualKeyCode) { - case VK_DELETE: - buf[0] = '\033'; - buf[1] = '['; - buf[2] = '3'; - buf[3] = '~'; - buflen = 4; - break; - case VK_NEXT: /* page-down */ - buf[0] = '\033'; - buf[1] = '['; - buf[2] = '6'; - buf[3] = '~'; - buflen = 4; - break; - case VK_PRIOR: /* page-up */ - buf[0] = '\033'; - buf[1] = '['; - buf[2] = '5'; - buf[3] = '~'; - buflen = 4; - break; - case VK_END: - buf[0] = '\033'; - buf[1] = '['; - buf[2] = 'F'; - buflen = 3; - break; - case VK_HOME: - buf[0] = '\033'; - buf[1] = '['; - buf[2] = 'H'; - buflen = 3; - break; - case VK_LEFT: - buf[0] = '\033'; - buf[1] = '['; - buf[2] = 'D'; - buflen = 3; - break; - case VK_UP: - buf[0] = '\033'; - buf[1] = '['; - buf[2] = 'A'; - buflen = 3; - break; - case VK_RIGHT: - buf[0] = '\033'; - buf[1] = '['; - buf[2] = 'C'; - buflen = 3; - break; - case VK_DOWN: - buf[0] = '\033'; - buf[1] = '['; - buf[2] = 'B'; - buflen = 3; - break; - /* translate ^@ to nul */ - case 0x32: - if (ker.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) { - buf[0] = 0; - buflen = 1; - } - break; - default: - break; - } - } - } - break; - } - - /* this tells us when the buffer size changes, but nothing comes through - when the window size changes. */ - case WINDOW_BUFFER_SIZE_EVENT: // scrn buf. resizing - return Strue; - - default: - break; - } - } -} - -/* probably need write-char too */ - -static ptr s_ee_get_screen_size(void) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - return Scons(Sinteger(csbiInfo.srWindow.Bottom - csbiInfo.srWindow.Top + 1), - Sinteger(csbiInfo.srWindow.Right - csbiInfo.srWindow.Left + 1)); -} - -static void s_ee_raw(void) { - /* see http://msdn2.microsoft.com/en-us/library/ms686033.aspx */ - if (!SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT) - || !SetConsoleMode(hStdout, 0)) - S_error1("expeditor", "error setting console mode: ~a", - S_LastErrorString()); -} - -static void s_ee_noraw(void) { - if (!SetConsoleMode(hStdin, InMode) || !SetConsoleMode(hStdout, OutMode)) - S_error1("expeditor", "error setting console mode: ~a", - S_LastErrorString()); -} - -static void s_ee_enter_am_mode(void) { return; } - -static void s_ee_exit_am_mode(void) { return; } - -static void s_ee_pause(void) { return; } - -static void s_ee_nanosleep(U32 secs, U32 nanosecs) { - Sleep((secs * 1000) + (nanosecs / 1000000)); -} - -static void s_ee_up(I32 n) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - COORD cursor_pos; - - fflush(stdout); - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - cursor_pos.X = csbiInfo.dwCursorPosition.X; - cursor_pos.Y = csbiInfo.dwCursorPosition.Y - n; - - /* ignore error, which can occur only if someone else screwed with screen */ - SetConsoleCursorPosition(hStdout, cursor_pos); -} - -static void s_ee_down(I32 n) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - COORD cursor_pos; - - fflush(stdout); - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - cursor_pos.X = csbiInfo.dwCursorPosition.X; - cursor_pos.Y = csbiInfo.dwCursorPosition.Y + n; - - /* ignore error, which can occur only if someone else screwed with screen */ - SetConsoleCursorPosition(hStdout, cursor_pos); -} - -static void s_ee_left(I32 n) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - COORD cursor_pos; - - fflush(stdout); - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - cursor_pos.X = csbiInfo.dwCursorPosition.X - n; - cursor_pos.Y = csbiInfo.dwCursorPosition.Y; - - /* ignore error, which can occur only if someone else screwed with screen */ - SetConsoleCursorPosition(hStdout, cursor_pos); -} - -static void s_ee_right(I32 n) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - COORD cursor_pos; - - fflush(stdout); - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - cursor_pos.X = csbiInfo.dwCursorPosition.X + n; - cursor_pos.Y = csbiInfo.dwCursorPosition.Y; - - /* ignore error, which can occur only if someone else screwed with screen */ - SetConsoleCursorPosition(hStdout, cursor_pos); -} - -static void s_ee_clear_eol(void) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - DWORD ntowrite, numwritten; - - fflush(stdout); - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - ntowrite = csbiInfo.dwSize.X - csbiInfo.dwCursorPosition.X; - - if (!FillConsoleOutputCharacter(hStdout, (TCHAR)' ', - ntowrite, csbiInfo.dwCursorPosition, &numwritten)) - S_error1("expeditor", "error clearing section of screen buffer: ~a", - S_LastErrorString()); - - if (!FillConsoleOutputAttribute(hStdout, csbiInfo.wAttributes, - ntowrite, csbiInfo.dwCursorPosition, &numwritten)) - S_error1("expeditor", "error setting attributes in section of screen buffer: ~a", - S_LastErrorString()); -} - -static void s_ee_clear_eos(void) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - DWORD ntowrite, numwritten; - - fflush(stdout); - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - ntowrite = (csbiInfo.dwSize.X - csbiInfo.dwCursorPosition.X) + - (csbiInfo.dwSize.X * - (csbiInfo.dwSize.Y - csbiInfo.dwCursorPosition.Y - 1)); - - if (!FillConsoleOutputCharacter(hStdout, (TCHAR)' ', - ntowrite, csbiInfo.dwCursorPosition, &numwritten)) - S_error1("expeditor", "error clearing section of screen buffer: ~a", - S_LastErrorString()); - - if (!FillConsoleOutputAttribute(hStdout, csbiInfo.wAttributes, - ntowrite, csbiInfo.dwCursorPosition, &numwritten)) - S_error1("expeditor", "error setting attributes in section of screen buffer: ~a", - S_LastErrorString()); -} - -static void s_ee_clear_screen(void) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - COORD cursor_pos; - DWORD ntowrite, numwritten; - - fflush(stdout); - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - cursor_pos.X = 0; - cursor_pos.Y = csbiInfo.srWindow.Top; - SetConsoleCursorPosition(hStdout, cursor_pos); - - ntowrite = csbiInfo.dwSize.X * (csbiInfo.dwSize.Y - cursor_pos.Y); - - if (!FillConsoleOutputCharacter(hStdout, (TCHAR)' ', - ntowrite, cursor_pos, &numwritten)) - S_error1("expeditor", "error clearing section of screen buffer: ~a", - S_LastErrorString()); - - if (!FillConsoleOutputAttribute(hStdout, csbiInfo.wAttributes, - ntowrite, cursor_pos, &numwritten)) - S_error1("expeditor", "error setting attributes in section of screen buffer: ~a", - S_LastErrorString()); -} - -static void s_ee_scroll_reverse(I32 n) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - - fflush(stdout); - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - if (csbiInfo.dwCursorPosition.Y - n < 0) { - SMALL_RECT rect; - COORD dest; - CHAR_INFO fill; - - /* set fill to blank so new top lines will be cleared */ - fill.Attributes = csbiInfo.wAttributes; - fill.Char.AsciiChar = (char)' '; - - /* move lines 0 through N-n-1 down to lines n through N-1 */ - rect.Top = 0; - rect.Bottom = csbiInfo.dwSize.Y - n - 1; - rect.Left = 0; - rect.Right = csbiInfo.dwSize.X - 1; - dest.X = 0; - dest.Y = n; - if (!ScrollConsoleScreenBuffer(hStdout, &rect, (SMALL_RECT *)0, dest, &fill)) - S_error1("expeditor", "error scrolling screen buffer: ~a", - S_LastErrorString()); - } else { - COORD cursor_pos; DWORD numwritten; - - cursor_pos.X = csbiInfo.dwCursorPosition.X; - cursor_pos.Y = csbiInfo.dwCursorPosition.Y - n; - SetConsoleCursorPosition(hStdout, cursor_pos); - - if (!FillConsoleOutputCharacter(hStdout, (TCHAR)' ', - csbiInfo.dwSize.X * n, cursor_pos, &numwritten)) - S_error1("expeditor", "error clearing section of screen buffer: ~a", - S_LastErrorString()); - - if (!FillConsoleOutputAttribute(hStdout, csbiInfo.wAttributes, - csbiInfo.dwSize.X * n, cursor_pos, &numwritten)) - S_error1("expeditor", "error setting attributes in section of screen buffer: ~a", - S_LastErrorString()); - } -} - -static void s_ee_bell(void) { - MessageBeep(MB_OK); -} - -static void s_ee_carriage_return(void) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - COORD cursor_pos; - - fflush(stdout); - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - cursor_pos.X = 0; - cursor_pos.Y = csbiInfo.dwCursorPosition.Y; - - SetConsoleCursorPosition(hStdout, cursor_pos); -} - -static void s_ee_line_feed(void) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - - fflush(stdout); - - if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) - S_error1("expeditor", "error getting console info: ~a", - S_LastErrorString()); - - if (csbiInfo.dwCursorPosition.Y == (csbiInfo.dwSize.Y - 1)) { - SMALL_RECT rect; - COORD dest; - CHAR_INFO fill; - - /* set fill to blank so new bottom line will be cleared */ - fill.Attributes = csbiInfo.wAttributes; - fill.Char.AsciiChar = (char)' '; - - /* move lines 1 through N-1 up to lines 0 through N-2 */ - rect.Top = 1; - rect.Bottom = csbiInfo.dwSize.Y - 1; - rect.Left = 0; - rect.Right = csbiInfo.dwSize.X - 1; - dest.X = 0; - dest.Y = 0; - if (!ScrollConsoleScreenBuffer(hStdout, &rect, (SMALL_RECT *)0, dest, &fill)) - S_error1("expeditor", "error scrolling screen buffer: ~a", - S_LastErrorString()); - } else { - COORD cursor_pos; - - cursor_pos.X = csbiInfo.dwCursorPosition.X; - cursor_pos.Y = csbiInfo.dwCursorPosition.Y + 1; - SetConsoleCursorPosition(hStdout, cursor_pos); - } -} - -static ptr s_ee_get_clipboard(void) { - ptr x = S_G.null_string; - - if (OpenClipboard((HWND)0)) { - HANDLE h = GetClipboardData(CF_UNICODETEXT); - if (h != NULL) { - wchar_t *w = (wchar_t*)GlobalLock(h); - if (w != NULL) { - char *s = Swide_to_utf8(w); - x = Sstring_utf8(s, -1); - free(s); - GlobalUnlock(h); - } - } - CloseClipboard(); - } - - return x; -} - -static void s_ee_write_char(wchar_t c) { - DWORD n; - WriteConsoleW(hStdout, &c, 1, &n, NULL); -} - -#else /* WIN32 */ -#include -#ifdef DISABLE_CURSES -#include "nocurses.h" -#elif defined(SOLARIS) -#define NCURSES_CONST -#define CHTYPE int -#include -#include -#elif defined(NETBSD) -#include -#include -#else /* NETBSD */ -#include -#include -#endif /* SOLARIS */ -#include -#include -#include -#include -#include -#include -#if !defined(__linux__) && !defined(__OpenBSD__) && !defined(__NetBSD__) -#include -#endif - -#if defined(TIOCGWINSZ) && defined(SIGWINCH) && defined(EINTR) -#define HANDLE_SIGWINCH -#endif - -#ifdef USE_MBRTOWC_L -static locale_t the_locale; -static locale_t uselocale_alt(locale_t l) { - locale_t old = the_locale; - the_locale = l; - return old; -} -# define uselocale(v) uselocale_alt(v) -# define mbrtowc(pwc, s, n, ps) mbrtowc_l(pwc, s, n, ps, the_locale) -#endif - -/* locally defined functions */ -static int eeputc(tputsputcchar c); -#ifdef HANDLE_SIGWINCH -static void handle_sigwinch(int sig); -#endif - -#ifdef HANDLE_SIGWINCH -static IBOOL winched = 0; -static void handle_sigwinch(UNUSED int sig) { - winched = 1; -} -#endif - -#define STDIN_FD 0 -#define STDOUT_FD 1 - -static IBOOL disable_auto_margin = 0, avoid_last_column = 0; -static locale_t term_locale; -static mbstate_t term_in_mbs; -static mbstate_t term_out_mbs; - -static IBOOL s_ee_init_term(void) { - int errret; - - if (init_status != -1) return init_status; - - if (isatty(STDIN_FD) - && isatty(STDOUT_FD) - && setupterm(NULL, STDOUT_FD, &errret) != ERR -/* assuming here and in our optproc definitions later that the names of - missing capabilities are set to NULL, although this does not appear - to be documented */ - && cursor_up - && cursor_down - && cursor_left - && cursor_right - && clr_eol - && clr_eos - && clear_screen - && scroll_reverse - && carriage_return) { - if (auto_right_margin) { - /* terminal automatically wraps. safest to disable if possible */ - if (exit_am_mode && enter_am_mode) { - disable_auto_margin = 1; - avoid_last_column = 0; - /* can't disable automatic margins, but eat_newline_glitch is set. - may still be okay, since we never write past the last column, - and the automatic newline should be emitted only if we do. but - see hack in s_ee_enter_am_mode */ - } else if (eat_newline_glitch) { - disable_auto_margin = 0; - avoid_last_column = 0; - } else { - disable_auto_margin = 0; - avoid_last_column = 1; - } - } else { - disable_auto_margin = 0; - avoid_last_column = 0; - } - -#ifdef HANDLE_SIGWINCH - struct sigaction act; - - sigemptyset(&act.sa_mask); - - act.sa_flags = 0; - act.sa_handler = handle_sigwinch; - sigaction(SIGWINCH, &act, (struct sigaction *)0); -#endif - - term_locale = newlocale(LC_ALL_MASK, "", NULL); - memset(&term_out_mbs, 0, sizeof(term_out_mbs)); - memset(&term_in_mbs, 0, sizeof(term_in_mbs)); - - init_status = 1; - } else { - init_status = 0; - } - - return init_status; -} - -/* returns char, eof, #t (winched), or #f (nothing ready), the latter - only if blockp is false */ -static ptr s_ee_read_char(IBOOL blockp) { - ptr msg; int fd = STDIN_FD; int n; char buf[1]; wchar_t wch; size_t sz; - locale_t old_locale; -#ifdef PTHREADS - ptr tc = get_thread_context(); -#endif - - do { -#ifdef HANDLE_SIGWINCH - if (winched) { winched = 0; return Strue; } -#endif -#ifdef PTHREADS - if (!blockp || DISABLECOUNT(tc) == FIX(0)) { - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | NOBLOCK); - n = READ(fd, buf, 1); - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~NOBLOCK); - if (n < 0 && errno == EWOULDBLOCK) { - if (!blockp) return Sfalse; - deactivate_thread(tc); - n = READ(fd, buf, 1); - reactivate_thread(tc); - } - } else { - n = READ(fd, buf, 1); - } -#else /* PTHREADS */ - if (!blockp) { - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | NOBLOCK); - n = READ(fd, buf, 1); - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~NOBLOCK); - if (n < 0 && errno == EWOULDBLOCK) return Sfalse; - } else { - n = READ(fd, buf, 1); - } -#endif /* PTHREADS */ - - if (n == 1) { - if (buf[0] == '\0') { - return Schar('\0'); - } else { - old_locale = uselocale(term_locale); - sz = mbrtowc(&wch, buf, 1, &term_out_mbs); - uselocale(old_locale); - if (sz == 1) { - return Schar(wch); - } - } - } - - } while ((n < 0 && errno == EINTR) || (n == 1 && sz == (size_t)-2)); - - if (n == 0) return Seof_object; - - msg = S_strerror(errno); - S_error1("expeditor", "error reading from console: ~a", msg); - - memset(&term_out_mbs, 0, sizeof(term_out_mbs)); - return Svoid; -} - -/* returns a pair of positive integers */ -static ptr s_ee_get_screen_size(void) { - static INT ee_rows = 0; - static INT ee_cols = 0; - -#ifdef TIOCGWINSZ - struct winsize ws; - if (ioctl(STDOUT_FD, TIOCGWINSZ, &ws) == 0) { - if (ws.ws_row > 0) ee_rows = ws.ws_row; - if (ws.ws_col > 0) ee_cols = ws.ws_col; - } -#ifdef MACOSX - static IBOOL tried_resize = 0; - /* attempt to work around 10.6 tty driver / xterm bug */ - if (ee_rows == 0 && ee_cols == 0 && !tried_resize) { - system("exec /usr/X11/bin/resize >& /dev/null"); - tried_resize = 1; - return s_ee_get_screen_size(); - } -#endif /* MACOSX */ -#endif /* TIOCGWINSZ */ - - if (ee_rows == 0) { - char *s, *endp; - if ((s = getenv("LINES")) != NULL) { - INT n = (int)strtol(s, &endp, 10); - if (n > 0 && *endp == '\0') ee_rows = n; - } - if (ee_rows == 0) ee_rows = lines > 0 ? lines : 24; - } - - if (ee_cols == 0) { - char *s, *endp; - if ((s = getenv("COLUMNS")) != NULL) { - INT n = (int)strtol(s, &endp, 10); - if (n > 0 && *endp == '\0') ee_cols = n; - } - if (ee_cols == 0) ee_cols = columns > 0 ? columns : 80; - } - - return Scons(Sinteger(ee_rows), Sinteger(ee_cols > 1 && avoid_last_column ? ee_cols - 1 : ee_cols)); -} - -static int eeputc(tputsputcchar c) { - return putchar(c); -} - -static struct termios orig_termios; - -static void s_ee_raw(void) { - struct termios new_termios; - while (tcgetattr(STDIN_FD, &orig_termios) != 0) { - if (errno != EINTR) { - ptr msg = S_strerror(errno); - if (msg != Sfalse) - S_error1("expeditor", "error entering raw mode: ~a", msg); - else - S_error("expeditor", "error entering raw mode"); - } - } - new_termios = orig_termios; - - /* essentially want "stty raw -echo". the appropriate flags to accomplish - this were determined by studying the gnu/linux stty and termios man - pages, with particular attention to the cfmakeraw function. */ - new_termios.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|INPCK|ISTRIP - |INLCR|IGNCR|ICRNL|IXON); - new_termios.c_oflag &= ~(OPOST); - new_termios.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN); - new_termios.c_cflag &= ~(CSIZE|PARENB); - new_termios.c_cflag |= CS8; - new_termios.c_cc[VMIN] = 1; - new_termios.c_cc[VTIME] = 0; - - while (tcsetattr(STDIN_FD, TCSADRAIN, &new_termios) != 0) { - if (errno != EINTR) { - ptr msg = S_strerror(errno); - if (msg != Sfalse) - S_error1("expeditor", "error entering raw mode: ~a", msg); - else - S_error("expeditor", "error entering raw mode"); - } - } -} - -static void s_ee_noraw(void) { - while (tcsetattr(STDIN_FD, TCSADRAIN, &orig_termios) != 0) { - if (errno != EINTR) { - ptr msg = S_strerror(errno); - if (msg != Sfalse) - S_error1("expeditor", "error leaving raw mode: ~a", msg); - else - S_error("expeditor", "error leaving raw mode"); - } - } -} - -static void s_ee_enter_am_mode(void) { - if (disable_auto_margin) { - tputs(enter_am_mode, 1, eeputc); - /* flush to minimize time span when automatic margins are disabled */ - fflush(stdout); - } else if (eat_newline_glitch) { - /* hack: try to prevent terminal from eating subsequent cr or lf. - assumes we've just written to last column. probably works only - for vt100 interpretation of eat_newline_glitch/xn/xenl flag. */ - tputs(cursor_left, 1, eeputc); - tputs(cursor_right, 1, eeputc); - } -} - -static void s_ee_exit_am_mode(void) { - if (disable_auto_margin) { - tputs(exit_am_mode, 1, eeputc); - } -} - -static void s_ee_pause(void) { /* used to handle ^Z */ - fflush(stdout); - kill(0, SIGTSTP); -} - -static void s_ee_nanosleep(U32 secs, U32 nanosecs) { - struct timespec ts; - ts.tv_sec = secs; - ts.tv_nsec = nanosecs; - nanosleep(&ts, (struct timespec *)0); -} - -static void s_ee_up(I32 n) { - while (n--) tputs(cursor_up, 1, eeputc); -} - -static void s_ee_down(I32 n) { - while (n--) tputs(cursor_down, 1, eeputc); -} - -static void s_ee_left(I32 n) { - while (n--) tputs(cursor_left, 1, eeputc); -} - -static void s_ee_right(I32 n) { - while (n--) tputs(cursor_right, 1, eeputc); -} - -static void s_ee_clear_eol(void) { - tputs(clr_eol, 1, eeputc); -} - -static void s_ee_clear_eos(void) { - tputs(clr_eos, 1, eeputc); -} - -static void s_ee_clear_screen(void) { - tputs(clear_screen, 1, eeputc); -} - -static void s_ee_scroll_reverse(I32 n) { - /* moving up from an entry that was only partially displayed, - scroll-reverse may be called when cursor isn't at the top line of - the screen, in which case we hope it will move up by one line. - in this case, which we have no way of distinguishing from the normal - case, scroll-reverse needs to clear the line explicitly */ - while (n--) { - tputs(scroll_reverse, 1, eeputc); - tputs(clr_eol, 1, eeputc); - } -} - -static void s_ee_bell(void) { - tputs(bell, 1, eeputc); -} - -static void s_ee_carriage_return(void) { - tputs(carriage_return, 1, eeputc); -} - -/* move-line-down doesn't scroll the screen when performed on the last - line on the freebsd and openbsd consoles. the official way to scroll - the screen is to use scroll-forward (ind), but ind is defined only - at the bottom left corner of the screen, and we don't always know - where the bottom of the screen actually is. so we write a line-feed - (newline) character and hope that will do the job. */ -static void s_ee_line_feed(void) { - putchar(0x0a); -} - -#ifdef LIBX11 -#include -#include -#include -#include -#endif /* LIBX11 */ - -static ptr s_ee_get_clipboard(void) { -#ifdef LIBX11 - static enum {UNINITIALIZED, INITIALIZED, FAILED} status = UNINITIALIZED; - static int (*pXConvertSelection)(Display *, Atom, Atom, Atom, Window, Time); - static int (*pXPending)(Display *display); - static int (*pXNextEvent)(Display *, XEvent *); - static int (*pXGetWindowProperty)(Display *, Window, Atom, long, long, Bool, Atom, Atom *, int *, unsigned long *, unsigned long *, unsigned char **); - static int (*pXFree)(void *); - - static Display *D; - static Window R, W; -#endif /* LIBX11 */ - - ptr p = S_G.null_string; - -#ifdef LIBX11 - if (status == UNINITIALIZED) { - char *display_name; - void *handle; - Display *(*pXOpenDisplay)(char *); - Window (*pXDefaultRootWindow)(Display *); - Window (*pXCreateSimpleWindow)(Display *, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long); - - status = (display_name = getenv("DISPLAY")) - && (handle = dlopen(LIBX11, RTLD_NOW)) - && (pXOpenDisplay = (Display *(*)(char *display_name))dlsym(handle, "XOpenDisplay")) - && (pXDefaultRootWindow = (Window (*)(Display *))dlsym(handle, "XDefaultRootWindow")) - && (pXCreateSimpleWindow = (Window (*)(Display *, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long))dlsym(handle, "XCreateSimpleWindow")) - && (pXConvertSelection = (int (*)(Display *, Atom, Atom, Atom, Window, Time))dlsym(handle, "XConvertSelection")) - && (pXPending = (int (*)(Display *display))dlsym(handle, "XPending")) - && (pXNextEvent = (int (*)(Display *, XEvent *))dlsym(handle, "XNextEvent")) - && (pXGetWindowProperty = (int (*)(Display *, Window, Atom, long, long, Bool, Atom, Atom *, int *, unsigned long *, unsigned long *, unsigned char **))dlsym(handle, "XGetWindowProperty")) - && (pXFree = (int (*)(void *))dlsym(handle, "XFree")) - && (D = pXOpenDisplay(display_name)) - && (R = pXDefaultRootWindow(D)) - && (W = pXCreateSimpleWindow(D, R, 0, 0, 1, 1, 0, 0, 0)) - ? INITIALIZED : FAILED; - } - - if (status == INITIALIZED) { - XEvent XE; - Window W2; Atom P; - Atom type; - int format; - unsigned long items, bytes, ignore_bytes; - unsigned char *buf; - int timeout; - - /* flush late arrivals from previous requests, if any */ - while (pXPending(D)) pXNextEvent(D, &XE); - - pXConvertSelection(D, XA_PRIMARY, XA_STRING, XA_STRING, W, CurrentTime); - - /* mini event loop to catch response, if any */ - timeout = 20; /* wait two seconds, 100ms at a time */ - for (;;) { - if (pXPending(D)) { - pXNextEvent(D, &XE); - if (XE.type == SelectionNotify) { - if (XE.xselection.property == None) { - W2 = R; - P = XA_CUT_BUFFER0; - } else { - W2 = XE.xselection.requestor; - P = XE.xselection.property; - } - - if (pXGetWindowProperty(D, W2, P, 0, 0, 0, AnyPropertyType, - &type, &format, &items, &bytes, &buf) == Success - && type == XA_STRING - && format == 8) { - pXFree(buf); - if (pXGetWindowProperty(D, W2, P, 0, bytes, 0, AnyPropertyType, - &type, &format, &items, &ignore_bytes, &buf) == Success - && type == XA_STRING - && format == 8) { - p = S_string((char *)buf, (iptr)bytes); - } - } - - pXFree(buf); - - break; - } - } else { - int xfd; - fd_set rfds; - struct timeval tv; - - if (timeout == 0) break; - xfd = ConnectionNumber(D); - FD_ZERO(&rfds); - FD_SET(xfd, &rfds); - tv.tv_sec = 0; - tv.tv_usec = 100*1000; - select(xfd+1, &rfds, NULL, NULL, &tv); - timeout -= 1; - } - } - } -#endif /* LIBX11 */ - -#ifdef MACOSX -#define PBPASTEBUFSIZE 1024 - if (p == S_G.null_string) { - char buf[PBPASTEBUFSIZE]; - FILE *f = popen("/usr/bin/pbpaste", "r"); - iptr i, n, m; - char *s; - - for (;;) { - ptr newp; - n = fread(buf, 1, PBPASTEBUFSIZE, f); - if (n == 0) break; - n += (m = Sstring_length(p)); - newp = S_string(NULL, n); - for (i = 0; i != m; i += 1) Sstring_set(newp, i, Sstring_ref(p, i)); - for (s = buf; i != n; i += 1, s += 1) - Sstring_set(newp, i, *s); - p = newp; - } - - fclose(f); - } -#endif /* MACOSX */ - - return p; -} - -static void s_ee_write_char(wchar_t wch) { - locale_t old; char buf[MB_LEN_MAX]; size_t n; - - old = uselocale(term_locale); - n = wcrtomb(buf, wch, &term_in_mbs); - if (n == (size_t)-1) { - putchar('?'); - } else { - fwrite(buf, 1, n, stdout); - } - uselocale(old); -} - -#endif /* WIN32 */ - -static void s_ee_flush(void) { - fflush(stdout); -} - -void S_expeditor_init(void) { - Sforeign_symbol("(cs)ee_init_term", (void *)s_ee_init_term); - Sforeign_symbol("(cs)ee_read_char", (void *)s_ee_read_char); - Sforeign_symbol("(cs)ee_write_char", (void *)s_ee_write_char); - Sforeign_symbol("(cs)ee_flush", (void *)s_ee_flush); - Sforeign_symbol("(cs)ee_get_screen_size", (void *)s_ee_get_screen_size); - Sforeign_symbol("(cs)ee_raw", (void *)s_ee_raw); - Sforeign_symbol("(cs)ee_noraw", (void *)s_ee_noraw); - Sforeign_symbol("(cs)ee_enter_am_mode", (void *)s_ee_enter_am_mode); - Sforeign_symbol("(cs)ee_exit_am_mode", (void *)s_ee_exit_am_mode); - Sforeign_symbol("(cs)ee_pause", (void *)s_ee_pause); - Sforeign_symbol("(cs)ee_nanosleep", (void *)s_ee_nanosleep); - Sforeign_symbol("(cs)ee_get_clipboard", (void *)s_ee_get_clipboard); - Sforeign_symbol("(cs)ee_up", (void *)s_ee_up); - Sforeign_symbol("(cs)ee_down", (void *)s_ee_down); - Sforeign_symbol("(cs)ee_left", (void *)s_ee_left); - Sforeign_symbol("(cs)ee_right", (void *)s_ee_right); - Sforeign_symbol("(cs)ee_clr_eol", (void *)s_ee_clear_eol); - Sforeign_symbol("(cs)ee_clr_eos", (void *)s_ee_clear_eos); - Sforeign_symbol("(cs)ee_clear_screen", (void *)s_ee_clear_screen); - Sforeign_symbol("(cs)ee_scroll_reverse", (void *)s_ee_scroll_reverse); - Sforeign_symbol("(cs)ee_bell", (void *)s_ee_bell); - Sforeign_symbol("(cs)ee_carriage_return", (void *)s_ee_carriage_return); - Sforeign_symbol("(cs)ee_line_feed", (void *)s_ee_line_feed); -} - -#endif /* FEATURE_EXPEDITOR */ diff --git a/ta6ob/c/expeditor.o b/ta6ob/c/expeditor.o deleted file mode 100644 index f99952d..0000000 Binary files a/ta6ob/c/expeditor.o and /dev/null differ diff --git a/ta6ob/c/externs.h b/ta6ob/c/externs.h deleted file mode 100644 index 773f030..0000000 --- a/ta6ob/c/externs.h +++ /dev/null @@ -1,415 +0,0 @@ -/* externs.h - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This file sets up platform-dependent includes and extern declarations - * for Scheme globals not intended for use outside of the system (prefixed - * with S_). Scheme globals intended for use outside of the system - * (prefixed with S) are declared in scheme.h - */ - -#include -#include -#include -#include - -#ifndef WIN32 -#include - -#if (machine_type == machine_type_i3qnx || machine_type == machine_type_ti3qnx) -off64_t lseek64(int,off64_t,int); -#endif - -#endif - -#ifdef SOLARIS -#include -#include -#include -#endif - -#ifdef WIN32 -#include -#include /* for _getcwd */ -#include -#endif - -#if !defined(NORETURN) -# if defined(__GNUC__) || defined(__clang__) -# define NORETURN __attribute__((noreturn)) -# elif defined(_MSC_VER) -# define NORETURN __declspec(noreturn) -# else -# define NORETURN -# endif /* defined(__GNUC__) || defined(__clang__) */ -#endif /* !defined(NORETURN) */ - -/* external procedure declarations */ -/* prototypes gen. by ProtoGen Version 0.31 (Haydn Huntley) 1/18/93 */ - -/* alloc.c */ -extern void S_alloc_init(void); -extern void S_protect(ptr *p); -extern void S_reset_scheme_stack(ptr tc, iptr n); -extern void S_reset_allocation_pointer(ptr tc); -extern ptr S_compute_bytes_allocated(ptr xg, ptr xs); -extern ptr S_find_more_room(ISPC s, IGEN g, iptr n, ptr old); -extern void S_dirty_set(ptr *loc, ptr x); -extern void S_mark_card_dirty(uptr card, IGEN to_g); -extern void S_scan_dirty(ptr **p, ptr **endp); -extern void S_scan_remembered_set(void); -extern void S_get_more_room(void); -extern ptr S_get_more_room_help(ptr tc, uptr ap, uptr type, uptr size); -extern ptr S_cons_in(ISPC s, IGEN g, ptr car, ptr cdr); -extern ptr S_symbol(ptr name); -extern ptr S_rational(ptr n, ptr d); -extern ptr S_tlc(ptr keyval, ptr tconc, ptr next); -extern ptr S_vector_in(ISPC s, IGEN g, iptr n); -extern ptr S_vector(iptr n); -extern ptr S_fxvector(iptr n); -extern ptr S_bytevector(iptr n); -extern ptr S_null_immutable_vector(void); -extern ptr S_null_immutable_fxvector(void); -extern ptr S_null_immutable_bytevector(void); -extern ptr S_null_immutable_string(void); -extern ptr S_record(iptr n); -extern ptr S_closure(ptr cod, iptr n); -extern ptr S_mkcontinuation(ISPC s, IGEN g, ptr nuate, ptr stack, - iptr length, iptr clength, ptr link, ptr ret, ptr winders); -extern ptr S_inexactnum(double rp, double ip); -extern ptr S_exactnum(ptr a, ptr b); -extern ptr S_thread(ptr tc); -extern ptr S_string(const char *s, iptr n); -extern ptr S_bignum(ptr tc, iptr n, IBOOL sign); -extern ptr S_code(ptr tc, iptr type, iptr n); -extern ptr S_relocation_table(iptr n); -extern ptr S_weak_cons(ptr car, ptr cdr); - -/* fasl.c */ -extern void S_fasl_init(void); -ptr S_fasl_read(INT fd, IFASLCODE situation, ptr path); -ptr S_bv_fasl_read(ptr bv, ptr path); -ptr S_boot_read(INT fd, const char *path); -char *S_format_scheme_version(uptr n); -char *S_lookup_machine_type(uptr n); -extern void S_set_code_obj(char *who, IFASLCODE typ, ptr p, iptr n, - ptr x, iptr o); -extern ptr S_get_code_obj(IFASLCODE typ, ptr p, iptr n, iptr o); - -/* flushcache.c */ -extern void S_record_code_mod(ptr tc, uptr addr, uptr bytes); -extern void S_flush_instruction_cache(ptr tc); -extern void S_flushcache_init(void); - -/* foreign.c */ -extern void S_foreign_init(void); -extern void S_foreign_entry(void); - -/* gcwrapper.c */ -extern void S_ptr_tell(ptr p); -extern void S_addr_tell(ptr p); -extern void S_gc_init(void); -#ifndef WIN32 -extern void S_register_child_process(INT child); -#endif /* WIN32 */ -extern void S_fixup_counts(ptr counts); -extern void S_do_gc(IGEN max_cg, IGEN min_tg, IGEN max_tg); -extern void S_gc(ptr tc, IGEN max_cg, IGEN min_tg, IGEN max_tg); -extern void S_gc_init(void); -extern void S_set_maxgen(IGEN g); -extern IGEN S_maxgen(void); -extern void S_set_minfreegen(IGEN g); -extern IGEN S_minfreegen(void); -#ifndef WIN32 -extern void S_register_child_process(INT child); -#endif /* WIN32 */ -extern IBOOL S_enable_object_counts(void); -extern void S_set_enable_object_counts(IBOOL eoc); -extern ptr S_object_counts(void); -extern ptr S_locked_objects(void); -extern ptr S_unregister_guardian(ptr tconc); -extern void S_compact_heap(void); -extern void S_check_heap(IBOOL aftergc); - -/* gc-011.c */ -extern void S_gc_011(ptr tc); - -/* gc-ocd.c */ -extern void S_gc_ocd(ptr tc, IGEN max_cg, IGEN min_tg, IGEN max_tg); - -/* gc-oce.c */ -extern void S_gc_oce(ptr tc, IGEN max_cg, IGEN min_tg, IGEN max_tg); - -/* intern.c */ -extern void S_intern_init(void); -extern void S_resize_oblist(void); -extern ptr S_intern(const unsigned char *s); -extern ptr S_intern_sc(const string_char *s, iptr n, ptr name_str); -extern ptr S_intern3(const string_char *pname, iptr plen, const string_char *uname, iptr ulen, ptr pname_str, ptr uame_str); -extern void S_intern_gensym(ptr g); -extern void S_retrofit_nonprocedure_code(void); - -/* io.c */ -extern IBOOL S_file_existsp(const char *inpath, IBOOL followp); -extern IBOOL S_file_regularp(const char *inpath, IBOOL followp); -extern IBOOL S_file_directoryp(const char *inpath, IBOOL followp); -extern IBOOL S_file_symbolic_linkp(const char *inpath); -#ifdef WIN32 -extern ptr S_find_files(const char *wildpath); -#else -extern ptr S_directory_list(const char *inpath); -#endif -extern char *S_malloc_pathname(const char *inpath); -#ifdef WIN32 -extern wchar_t *S_malloc_wide_pathname(const char *inpath); -#endif -extern IBOOL S_fixedpathp(const char *inpath); - -/* compress-io.c */ -extern INT S_zlib_compress_level(INT compress_level); -extern INT S_lz4_compress_level(INT compress_level); -extern glzFile S_glzdopen_output(INT fd, INT compress_format, INT compress_level); -extern glzFile S_glzdopen_input(INT fd); -extern glzFile S_glzopen_input(const char *path); -#ifdef WIN32 -extern glzFile S_glzopen_input_w(const wchar_t *path); -#endif -extern IBOOL S_glzdirect(glzFile file); -extern INT S_glzclose(glzFile file); - -extern INT S_glzread(glzFile file, void *buffer, UINT count); -extern INT S_glzwrite(glzFile file, void *buffer, UINT count); -extern long S_glzseek(glzFile file, long offset, INT whence); -extern INT S_glzgetc(glzFile file); -extern INT S_glzungetc(INT c, glzFile file); -extern INT S_glzrewind(glzFile file); - -extern void S_glzerror(glzFile file, INT *errnum); -extern void S_glzclearerr(glzFile fdfile); - - -/* new-io.c */ -extern INT S_gzxfile_fd(ptr x); -extern glzFile S_gzxfile_gzfile(ptr x); -extern ptr S_new_open_input_fd(const char *filename, IBOOL compressed); -extern ptr S_new_open_output_fd( - const char *filename, INT mode, - IBOOL no_create, IBOOL no_fail, IBOOL no_truncate, - IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed); -extern ptr S_new_open_input_output_fd( - const char *filename, INT mode, - IBOOL no_create, IBOOL no_fail, IBOOL no_truncate, - IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed); -extern ptr S_close_fd(ptr file, IBOOL gzflag); -extern ptr S_compress_input_fd(INT fd, I64 fp); -extern ptr S_compress_output_fd(INT fd); - -extern ptr S_bytevector_read(ptr file, ptr buffer, iptr start, iptr count, IBOOL gzflag); -extern ptr S_bytevector_read_nb(ptr file, ptr buffer, iptr start, iptr count, IBOOL gzflag); -extern ptr S_bytevector_write(ptr file, ptr buffer, iptr start, iptr count, IBOOL gzflag); -extern ptr S_put_byte(ptr file, INT byte, IBOOL gzflag); - -extern ptr S_get_fd_pos(ptr file, IBOOL gzflag); -extern ptr S_set_fd_pos(ptr file, ptr pos, IBOOL gzflag); -extern ptr S_get_fd_non_blocking(ptr file, IBOOL gzflag); -extern ptr S_set_fd_non_blocking(ptr file, IBOOL x, IBOOL gzflag); -extern ptr S_get_fd_length(ptr file, IBOOL gzflag); -extern ptr S_set_fd_length(ptr file, ptr length, IBOOL gzflag); -extern void S_new_io_init(void); - -extern uptr S_bytevector_compress_size(iptr s_count, INT compress_format); -extern ptr S_bytevector_compress(ptr dest_bv, iptr d_start, iptr d_count, - ptr src_bv, iptr s_start, iptr s_count, - INT compress_format); -extern ptr S_bytevector_uncompress(ptr dest_bv, iptr d_start, iptr d_count, - ptr src_bv, iptr s_start, iptr s_count, - INT compress_format); - -/* thread.c */ -extern void S_thread_init(void); -extern ptr S_create_thread_object(const char *who, ptr p_tc); -#ifdef PTHREADS -extern ptr S_fork_thread(ptr thunk); -extern scheme_mutex_t *S_make_mutex(void); -extern void S_mutex_free(scheme_mutex_t *m); -extern void S_mutex_acquire(scheme_mutex_t *m); -extern INT S_mutex_tryacquire(scheme_mutex_t *m); -extern void S_mutex_release(scheme_mutex_t *m); -extern s_thread_cond_t *S_make_condition(void); -extern void S_condition_free(s_thread_cond_t *c); -extern IBOOL S_condition_wait(s_thread_cond_t *c, scheme_mutex_t *m, ptr t); -extern INT S_activate_thread(void); -extern void S_unactivate_thread(int mode); -#endif - -/* scheme.c */ -extern void S_generic_invoke(ptr tc, ptr code); - -/* number.c */ -extern void S_number_init(void); -extern ptr S_normalize_bignum(ptr x); -extern IBOOL S_integer_valuep(ptr x); -extern iptr S_integer_value(const char *who, ptr x); -extern I64 S_int64_value(char *who, ptr x); -extern IBOOL S_big_eq(ptr x, ptr y); -extern IBOOL S_big_lt(ptr x, ptr y); -extern ptr S_big_negate(ptr x); -extern ptr S_add(ptr x, ptr y); -extern ptr S_sub(ptr x, ptr y); -extern ptr S_mul(ptr x, ptr y); -extern ptr S_div(ptr x, ptr y); -extern ptr S_rem(ptr x, ptr y); -extern ptr S_trunc(ptr x, ptr y); -extern void S_trunc_rem(ptr tc, ptr x, ptr y, ptr *q, ptr *r); -extern ptr S_gcd(ptr x, ptr y); -extern ptr S_ash(ptr x, ptr n); -extern ptr S_big_positive_bit_field(ptr x, ptr fxstart, ptr fxend); -extern ptr S_integer_length(ptr x); -extern ptr S_big_first_bit_set(ptr x); -extern double S_random_double(U32 m1, U32 m2, - U32 m3, U32 m4, double scale); -extern double S_floatify(ptr x); -extern ptr S_decode_float(double d); -extern ptr S_logand(ptr x, ptr y); -extern ptr S_logbitp(ptr k, ptr x); -extern ptr S_logbit0(ptr k, ptr x); -extern ptr S_logbit1(ptr k, ptr x); -extern ptr S_logtest(ptr x, ptr y); -extern ptr S_logor(ptr x, ptr y); -extern ptr S_logxor(ptr x, ptr y); -extern ptr S_lognot(ptr x); - -/* prim.c */ -extern ptr S_lookup_library_entry(iptr n, IBOOL errorp); -extern ptr S_lookup_c_entry(iptr i); -extern void S_prim_init(void); - -/* prim5.c */ -extern ptr S_strerror(INT errnum); -extern void S_prim5_init(void); -extern void S_dump_tc(ptr tc); - -/* print.c */ -extern void S_print_init(void); -extern void S_prin1(ptr x); - -/* schsig.c */ -extern ptr S_get_scheme_arg(ptr tc, iptr n); -extern void S_put_scheme_arg(ptr tc, iptr n, ptr x); -extern iptr S_continuation_depth(ptr k); -extern ptr S_single_continuation(ptr k, iptr n); -extern void S_split_and_resize(void); -extern void S_handle_overflow(void); -extern void S_handle_overflood(void); -extern void S_handle_apply_overflood(void); -extern void S_overflow(ptr tc, iptr frame_request); -extern NORETURN void S_error_reset(const char *s); -extern NORETURN void S_error_abort(const char *s); -extern NORETURN void S_abnormal_exit(void); -extern NORETURN void S_error(const char *who, const char *s); -extern NORETURN void S_error1(const char *who, const char *s, ptr x); -extern NORETURN void S_error2(const char *who, const char *s, ptr x, ptr y); -extern NORETURN void S_error3(const char *who, const char *s, ptr x, ptr y, ptr z); -extern NORETURN void S_boot_error(const ptr who, ptr s, ptr args); -extern void S_handle_docall_error(void); -extern void S_handle_arg_error(void); -extern void S_handle_nonprocedure_symbol(void); -extern void S_handle_values_error(void); -extern void S_handle_mvlet_error(void); -extern ptr S_allocate_scheme_signal_queue(void); -extern ptr S_dequeue_scheme_signals(ptr tc); -extern void S_register_scheme_signal(iptr sig); -extern void S_fire_collector(void); -extern NORETURN void S_noncontinuable_interrupt(void); -extern void S_schsig_init(void); -#ifdef DEFINE_MATHERR -#include -extern INT matherr(struct exception *x); -#endif /* DEFINE_MATHERR */ - -/* segment.c */ -extern void S_segment_init(void); -extern void *S_getmem(iptr bytes, IBOOL zerofill); -extern void S_freemem(void *addr, iptr bytes); -extern iptr S_find_segments(ISPC s, IGEN g, iptr n); -extern void S_free_chunk(chunkinfo *chunk); -extern void S_free_chunks(void); -extern uptr S_curmembytes(void); -extern uptr S_maxmembytes(void); -extern void S_resetmaxmembytes(void); -extern void S_move_to_chunk_list(chunkinfo *chunk, chunkinfo **pchunk_list); - -/* stats.c */ -extern void S_stats_init(void); -extern ptr S_cputime(void); -extern ptr S_realtime(void); -extern ptr S_clock_gettime(I32 typeno); -extern ptr S_gmtime(ptr tzoff, ptr tspair); -extern ptr S_asctime(ptr dtvec); -extern ptr S_mktime(ptr dtvec); -extern ptr S_unique_id(void); -extern void S_gettime(INT typeno, struct timespec *tp); - -/* symbol.c */ -extern ptr S_symbol_value(ptr sym); -extern void S_set_symbol_value(ptr sym, ptr val); - -/* machine-dependent .c files, e.g., x88k.c */ -#ifdef FLUSHCACHE -extern INT S_flushcache_max_gap(void); -extern void S_doflush(uptr start, uptr end); -#endif -extern void S_machine_init(void); - -/* schlib.c */ -extern void S_initframe(ptr tc, iptr n); -extern void S_put_arg(ptr tc, iptr i, ptr x); -extern void S_return(void); -extern void S_call_help(ptr tc, IBOOL singlep, IBOOL lock_ts); -extern void S_call_one_result(void); -extern void S_call_any_results(void); - -#ifdef WIN32 -/* windows.c */ -extern INT S_getpagesize(void); -extern ptr S_LastErrorString(void); -extern void *S_ntdlopen(const char *path); -extern void *S_ntdlsym(void *h, const char *s); -extern ptr S_ntdlerror(void); -extern int S_windows_flock(int fd, int operation); -extern int S_windows_chdir(const char *pathname); -extern int S_windows_chmod(const char *pathname, int mode); -extern int S_windows_mkdir(const char *pathname); -extern int S_windows_open(const char *pathname, int flags, int mode); -extern int S_windows_rename(const char *oldpathname, const char *newpathname); -extern int S_windows_rmdir(const char *pathname); -extern int S_windows_stat64(const char *pathname, struct STATBUF *buffer); -extern int S_windows_system(const char *command); -extern int S_windows_unlink(const char *pathname); -extern char *S_windows_getcwd(char *buffer, int maxlen); -#endif /* WIN32 */ - -#ifdef _WIN64 -extern int S_setjmp(void* jb); -extern void S_longjmp(void* jb, int value); -#endif /* _WIN64 */ - -#ifdef FEATURE_EXPEDITOR -/* expeditor.c */ -extern void S_expeditor_init(void); -#endif /* FEATURE_EXPEDITOR */ - -/* statics.c */ -extern void scheme_statics(void); diff --git a/ta6ob/c/fasl.c b/ta6ob/c/fasl.c deleted file mode 100644 index b0f51fa..0000000 --- a/ta6ob/c/fasl.c +++ /dev/null @@ -1,1662 +0,0 @@ -/* fasl.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* fasl representation: - * - * -> * - * - * -> * - * - * -> {header}\0\0\0chez( ...) - * - * -> * - * - * -> # size is the size in bytes of - * - * -> {visit} | {revisit} | {visit-revisit} - * - * -> | {uncompressed} - * - * -> {gzip} | {lz4} - * - * -> {pair}... - * - * -> {weak-pair} - * - * -> {box} - * - * -> {symbol} - * - * -> {gensym} - * - * -> {string} - * - * -> {vector}... - * - * -> {fxvector}... - * - * -> {bytevector}... - * - * -> {immediate} - * - * -> {small-integer} - * - * -> {large-integer}... - * - * -> {ratum} - * - * -> {inexactnum} - * - * -> {exactnum} - * - * -> {flonum} - * - * -> {entry} - * - * -> {library} - * - * -> {library-code} - * - * -> {graph} - * - * -> {graph-def} - * - * -> {graph-ref} - * - * -> {base-rtd} - * - * -> {rtd} - * - * -> {record} - * - * -> {eq-hashtable} - * - * - * - * - * ... - * -> - * - * -> {symbol-hashtable} - * - * ; 0: eq?, 1: eqv?, 2: equal?, 3: symbol=? - * - * - * ... - * -> - * - * -> {closure} - * - * -> {code} - * # number of free variables - * # length in bytes of code - * - * # two's complement encoding of accepted argument counts - * # inspector info - * # profiling info - * ... - * # length in uptrs of relocation table - * # first relocation entry - * ... - * # last relocation entry - * - * -> # bit 0: extended entry, bit 1: expect item offset, bit 2+: type - * - * # omitted if bit 1 of type-etc is 0 - * - * - * -> ... - * - * -> # size in bytes, not necessarily ptr-aligned - * # number of flds - * - * - * ... - * - * -> - * - * - * - * - * # 32-bit target - * # 64-bit target - * # 32-bit target - * # 64-bit target - * # 32-bit target - * # 64-bit target - * # 32-bit target - * # 64-bit target - * - * - * -> - * - * -> * - * -> k << 1 | 1, 0 <= k <= 127 - * -> k << 1 | 0, 0 <= k <= 127 - * each ubyte represents 7 bits of the uptr, least-significant first - * low-order bit is continuation bit: 1 iff more bytes are present - * - * -> | * - * -> sign << 7 | k << 1 | 1, 0 <= k <= 63 - * -> sign << 7 | k << 1 | 0, 0 <= k <= 63 - * leading ibyte represents least-significant 6 bits and sign - * each ubyte represents 7 of the remaining bits of the iptr, - * least-significant first - * - * Notes: - * * a list of length n will appear to be shorter in the fasl - * representation when the tail of the list is shared, since the - * shared tail will be a {graph-def} or {graph-ref}. - * - * * the length of a relocation table is the number of uptrs in the - * table, not the number of relocation entries. - * - * * closure offset is the amount added to the code object before - * storing it in the code field of the closure. - * - * * {graph} defines the size of the graph used to commonize shared - * structure, including cycles. It must appear before {graph-def} - * or {graph-ref}. A {graph-def} at index i must appear before - * a {graph-ref} at index i. - * - * * after an rtd is read: if its uname is unbound, the rtd is placed - * into the symbol value slot of the uname; otherwise, the rtd is - * discarded and the existing symbol value of uname is returned - * instead. Note that when many records appear within the same - * aggregrate structure, the full rtd will appear only in the - * first occurrence; the remainder will simply be graph references. - * - * * at present, the fasl representation supports only records - * containing only scheme-object fields. - */ - -#include "system.h" -#include "zlib.h" - -#ifdef WIN32 -#include -#endif /* WIN32 */ - -#ifdef NAN_INCLUDE -#include NAN_INCLUDE -#endif - -#define UFFO_TYPE_FD 2 -#define UFFO_TYPE_BV 3 - -#define PREPARE_BYTEVECTOR(bv,n) {if (bv == Sfalse || Sbytevector_length(bv) < (n)) bv = S_bytevector(n);} - -typedef struct unbufFaslFileObj { - ptr path; - INT type; - INT fd; -} *unbufFaslFile; - -typedef struct faslFileObj { - unbufFaslFile uf; - iptr size; - octet *next; - octet *end; - octet *buf; -} *faslFile; - -/* locally defined functions */ -static INT uf_read(unbufFaslFile uf, octet *s, iptr n); -static octet uf_bytein(unbufFaslFile uf); -static uptr uf_uptrin(unbufFaslFile uf, INT *bytes_consumed); -static ptr fasl_entry(ptr tc, IFASLCODE situation, unbufFaslFile uf); -static ptr bv_fasl_entry(ptr tc, ptr bv, unbufFaslFile uf); -static void fillFaslFile(faslFile f); -static void bytesin(octet *s, iptr n, faslFile f); -static void toolarge(ptr path); -static iptr iptrin(faslFile f); -static uptr uptrin(faslFile f); -static float singlein(faslFile f); -static double doublein(faslFile f); -static iptr stringin(ptr *pstrbuf, iptr start, faslFile f); -static void faslin(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f); -static void fasl_record(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f); -static IBOOL rtd_equiv(ptr x, ptr y); -static IBOOL equalp(ptr x, ptr y); -#ifdef ARMV6 -static void arm32_set_abs(void *address, uptr item); -static uptr arm32_get_abs(void *address); -static void arm32_set_jump(void *address, uptr item, IBOOL callp); -static uptr arm32_get_jump(void *address); -#endif /* ARMV6 */ -#ifdef PPC32 -static void ppc32_set_abs(void *address, uptr item); -static uptr ppc32_get_abs(void *address); -static void ppc32_set_jump(void *address, uptr item, IBOOL callp); -static uptr ppc32_get_jump(void *address); -#endif /* PPC32 */ -#ifdef X86_64 -static void x86_64_set_jump(void *address, uptr item, IBOOL callp); -static uptr x86_64_get_jump(void *address); -#endif /* X86_64 */ -#ifdef SPARC64 -static INT extract_reg_from_sethi(void *address); -static void emit_sethi_lo(U32 item, INT destreg, void *address); -static uptr sparc64_get_literal(void *address); -static void sparc64_set_call(void *address, U32 *call_addr, uptr item); -static U32 adjust_delay_inst(U32 delay_inst, U32 *old_call_addr, U32 *new_call_addr); -static INT sparc64_set_lit_only(void *address, uptr item, I32 destreg); -static void sparc64_set_literal(void *address, uptr item); -#endif /* SPARC64 */ - -static double s_nan; - -void S_fasl_init(void) { - if (S_boot_time) { - S_protect(&S_G.base_rtd); - S_G.base_rtd = Sfalse; - S_protect(&S_G.rtd_key); - S_G.rtd_key = S_intern((const unsigned char *)"*rtd*"); - S_protect(&S_G.eq_symbol); - S_G.eq_symbol = S_intern((const unsigned char *)"eq"); - S_protect(&S_G.eq_ht_rtd); - S_G.eq_ht_rtd = Sfalse; - S_protect(&S_G.symbol_symbol); - S_G.symbol_symbol = S_intern((const unsigned char *)"symbol"); - S_protect(&S_G.symbol_ht_rtd); - S_G.symbol_ht_rtd = Sfalse; - S_protect(&S_G.eqp); - S_G.eqp = Sfalse; - S_protect(&S_G.eqvp); - S_G.eqvp = Sfalse; - S_protect(&S_G.equalp); - S_G.equalp = Sfalse; - S_protect(&S_G.symboleqp); - S_G.symboleqp = Sfalse; - } - - MAKE_NAN(s_nan) -#ifndef WIN32 /* msvc returns true for s_nan==s_nan! */ - if (s_nan == s_nan) { - fprintf(stderr, "s_nan == s_nan\n"); - S_abnormal_exit(); - } -#endif -} - -ptr S_fasl_read(INT fd, IFASLCODE situation, ptr path) { - ptr tc = get_thread_context(); - ptr x; struct unbufFaslFileObj uffo; - - /* acquire mutex in case we modify code pages */ - tc_mutex_acquire() - uffo.path = path; - uffo.type = UFFO_TYPE_FD; - uffo.fd = fd; - x = fasl_entry(tc, situation, &uffo); - tc_mutex_release() - return x; -} - -ptr S_bv_fasl_read(ptr bv, ptr path) { - ptr tc = get_thread_context(); - ptr x; struct unbufFaslFileObj uffo; - - /* acquire mutex in case we modify code pages */ - tc_mutex_acquire() - uffo.path = path; - uffo.type = UFFO_TYPE_BV; - x = bv_fasl_entry(tc, bv, &uffo); - tc_mutex_release() - return x; -} - -ptr S_boot_read(INT fd, const char *path) { - ptr tc = get_thread_context(); - struct unbufFaslFileObj uffo; - - uffo.path = Sstring_utf8(path, -1); - uffo.type = UFFO_TYPE_FD; - uffo.fd = fd; - return fasl_entry(tc, fasl_type_visit_revisit, &uffo); -} - -#ifdef WIN32 -#define IO_SIZE_T unsigned int -#else /* WIN32 */ -#define IO_SIZE_T size_t -#endif /* WIN32 */ - -static INT uf_read(unbufFaslFile uf, octet *s, iptr n) { - iptr k; - while (n > 0) { - uptr nx = n; - -#if (iptr_bits > 32) - if (WIN32 && (unsigned int)nx != nx) nx = 0xffffffff; -#endif - - switch (uf->type) { - case UFFO_TYPE_FD: - k = READ(uf->fd, s, (IO_SIZE_T)nx); - if (k > 0) - n -= k; - else if (k == 0) - return -1; - else if (errno != EINTR) - S_error1("", "error reading from ~a", uf->path); - break; - default: - return -1; - } - - s += k; - } - return 0; -} - -static void uf_skipbytes(unbufFaslFile uf, iptr n) { - switch (uf->type) { - case UFFO_TYPE_FD: - if (LSEEK(uf->fd, n, SEEK_CUR) == -1) { - S_error1("", "error seeking ~a", uf->path); - } - break; - } -} - -static octet uf_bytein(unbufFaslFile uf) { - octet buf[1]; - if (uf_read(uf, buf, 1) < 0) - S_error1("", "unexpected eof in fasl file ~a", uf->path); - return buf[0]; -} - -static uptr uf_uptrin(unbufFaslFile uf, INT *bytes_consumed) { - uptr n, m; octet k; - - if (bytes_consumed) *bytes_consumed = 1; - k = uf_bytein(uf); - n = k >> 1; - while (k & 1) { - if (bytes_consumed) *bytes_consumed += 1; - k = uf_bytein(uf); - m = n << 7; - if (m >> 7 != n) toolarge(uf->path); - n = m | (k >> 1); - } - - return n; -} - -char *S_format_scheme_version(uptr n) { - static char buf[16]; INT len; - if ((n >> 16) != ((n >> 16) & 0xffff)) return "unknown"; - if ((n & 0xff) == 0) - len = snprintf(buf, 16, "%d.%d", (int) n >> 16, (int) (n >> 8) & 0xff); - else - len = snprintf(buf, 16, "%d.%d.%d", (int) n >> 16, (int) (n >> 8) & 0xff, - (int) n & 0xff); - return len > 0 ? buf : "unknown"; -} - -char *S_lookup_machine_type(uptr n) { - static char *machine_type_table[] = machine_type_names; - if (n < machine_type_limit) - return machine_type_table[n]; - else - return "unknown"; -} - -static ptr fasl_entry(ptr tc, IFASLCODE situation, unbufFaslFile uf) { - ptr x; ptr strbuf = S_G.null_string; - octet tybuf[1]; IFASLCODE ty; iptr size; - /* gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28) co-locates buf and x if we put the declaration of buf down where we use it */ - octet buf[SBUFSIZ]; - - for (;;) { - if (uf_read(uf, tybuf, 1) < 0) return Seof_object; - ty = tybuf[0]; - - while (ty == fasl_type_header) { - uptr n; ICHAR c; - - /* check for remainder of magic number */ - if (uf_bytein(uf) != 0 || - uf_bytein(uf) != 0 || - uf_bytein(uf) != 0 || - uf_bytein(uf) != 'c' || - uf_bytein(uf) != 'h' || - uf_bytein(uf) != 'e' || - uf_bytein(uf) != 'z') - S_error1("", "malformed fasl-object header (missing magic word) found in ~a", uf->path); - - if ((n = uf_uptrin(uf, (INT *)0)) != scheme_version) - S_error2("", "incompatible fasl-object version ~a found in ~a", S_string(S_format_scheme_version(n), -1), uf->path); - - if ((n = uf_uptrin(uf, (INT *)0)) != machine_type_any && n != machine_type) - S_error2("", "incompatible fasl-object machine-type ~a found in ~a", S_string(S_lookup_machine_type(n), -1), uf->path); - - if (uf_bytein(uf) != '(') - S_error1("", "malformed fasl-object header (missing open paren) found in ~a", uf->path); - - while ((c = uf_bytein(uf)) != ')') - if (c < 0) S_error1("", "malformed fasl-object header (missing close paren) found in ~a", uf->path); - - ty = uf_bytein(uf); - } - - switch (ty) { - case fasl_type_visit: - case fasl_type_revisit: - case fasl_type_visit_revisit: - break; - default: - S_error2("", "malformed fasl-object header (missing situation, got ~s) found in ~a", FIX(ty), uf->path); - return (ptr)0; - } - - size = uf_uptrin(uf, (INT *)0); - - if (ty == situation || situation == fasl_type_visit_revisit || ty == fasl_type_visit_revisit) { - struct faslFileObj ffo; - - ty = uf_bytein(uf); - switch (ty) { - case fasl_type_gzip: - case fasl_type_lz4: { - ptr result; INT bytes_consumed; - iptr dest_size = uf_uptrin(uf, &bytes_consumed); - iptr src_size = size - (1 + bytes_consumed); /* adjust for u8 compression type and uptr dest_size */ - - PREPARE_BYTEVECTOR(SRCBV(tc), src_size); - PREPARE_BYTEVECTOR(DSTBV(tc), dest_size); - if (uf_read(uf, &BVIT(SRCBV(tc),0), src_size) < 0) - S_error1("", "unexpected eof in fasl file ~a", uf->path); - result = S_bytevector_uncompress(DSTBV(tc), 0, dest_size, SRCBV(tc), 0, src_size, - (ty == fasl_type_gzip ? COMPRESS_GZIP : COMPRESS_LZ4)); - if (result != FIX(dest_size)) { - if (Sstringp(result)) S_error2("fasl-read", "~@?", result, SRCBV(tc)); - S_error3("fasl-read", "uncompressed size ~s for ~s is smaller than expected size ~s", result, SRCBV(tc), FIX(dest_size)); - } - ffo.size = dest_size; - ffo.next = ffo.buf = &BVIT(DSTBV(tc),0); - ffo.end = &BVIT(DSTBV(tc),dest_size); - ffo.uf = uf; - break; - } - case fasl_type_uncompressed: { - ffo.size = size - 1; /* adjust for u8 compression type */ - ffo.next = ffo.end = ffo.buf = buf; - ffo.uf = uf; - break; - } - default: - S_error2("", "malformed fasl-object header (missing possibly-compressed, got ~s) found in ~a", FIX(ty), uf->path); - return (ptr)0; - } - faslin(tc, &x, S_G.null_vector, &strbuf, &ffo); - S_flush_instruction_cache(tc); - return x; - } else { - uf_skipbytes(uf, size); - } - } -} - -static ptr bv_fasl_entry(ptr tc, ptr bv, unbufFaslFile uf) { - ptr x; ptr strbuf = S_G.null_string; - struct faslFileObj ffo; - - ffo.size = Sbytevector_length(bv); - ffo.next = ffo.buf = &BVIT(bv, 0); - ffo.end = &BVIT(bv, ffo.size); - ffo.uf = uf; - - faslin(tc, &x, S_G.null_vector, &strbuf, &ffo); - S_flush_instruction_cache(tc); - return x; -} - -static void fillFaslFile(faslFile f) { - iptr n = f->size < SBUFSIZ ? f->size : SBUFSIZ; - if (uf_read(f->uf, f->buf, n) < 0) - S_error1("", "unexpected eof in fasl file ~a", f->uf->path); - f->end = (f->next = f->buf) + n; - f->size -= n; -} - -#define bytein(f) ((((f)->next == (f)->end) ? fillFaslFile(f) : (void)0), *((f)->next++)) - -static void bytesin(octet *s, iptr n, faslFile f) { - iptr avail = f->end - f->next; - if (avail < n) { - if (avail != 0) { - memcpy(s, f->next, avail); - f->next = f->end; - n -= avail; - s += avail; - } - if (uf_read(f->uf, s, n) < 0) - S_error1("", "unexpected eof in fasl file ~a", f->uf->path); - f->size -= n; - } else { - memcpy(s, f->next, n); - f->next += n; - } -} - -static void toolarge(ptr path) { - S_error1("", "fasl value too large for this machine type in ~a", path); -} - -static iptr iptrin(faslFile f) { - uptr n, m; octet k, k0; - - k0 = k = bytein(f); - n = (k & 0x7f) >> 1; - while (k & 1) { - k = bytein(f); - m = n << 7; - if (m >> 7 != n) toolarge(f->uf->path); - n = m | (k >> 1); - } - - if (k0 & 0x80) { - if (n < ((uptr)1 << (ptr_bits - 1))) { - return -(iptr)n; - } else if (n > ((uptr)1 << (ptr_bits - 1))) { - toolarge(f->uf->path); - } -#if (fixnum_bits > 32) - return (iptr)0x8000000000000000; -#else - return (iptr)0x80000000; -#endif - } else { - if (n >= ((uptr)1 << (ptr_bits - 1))) toolarge(f->uf->path); - return (iptr)n; - } -} - -static uptr uptrin(faslFile f) { - uptr n, m; octet k; - - k = bytein(f); - n = k >> 1; - while (k & 1) { - k = bytein(f); - m = n << 7; - if (m >> 7 != n) toolarge(f->uf->path); - n = m | (k >> 1); - } - - return n; -} - -static float singlein(faslFile f) { - union { float f; U32 u; } val; - - val.u = (U32)uptrin(f); - - return val.f; -} - -static double doublein(faslFile f) { -#ifdef LITTLE_ENDIAN_IEEE_DOUBLE - union { double d; struct { U32 l; U32 h; } u; } val; -#else - union { double d; struct { U32 h; U32 l; } u; } val; -#endif - - val.u.h = (U32)uptrin(f); - val.u.l = (U32)uptrin(f); - - return val.d; -} - -static iptr stringin(ptr *pstrbuf, iptr start, faslFile f) { - iptr end, n, i; ptr p = *pstrbuf; - - end = start + (n = uptrin(f)); - if (Sstring_length(*pstrbuf) < end) { - ptr newp = S_string((char *)0, end); - for (i = 0; i != start; i += 1) Sstring_set(newp, i, Sstring_ref(p, i)); - *pstrbuf = p = newp; - } - for (i = start; i != end; i += 1) Sstring_set(p, i, uptrin(f)); - return n; -} - -static void faslin(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f) { - IFASLCODE ty = bytein(f); - switch (ty) { - case fasl_type_pair: { - iptr n; ptr p; - n = uptrin(f); - *x = p = Scons(FIX(0), FIX(0)); - faslin(tc, &INITCAR(p), t, pstrbuf, f); - while (--n) { - INITCDR(p) = Scons(FIX(0), FIX(0)); - p = INITCDR(p); - faslin(tc, &INITCAR(p), t, pstrbuf, f); - } - faslin(tc, &INITCDR(p), t, pstrbuf, f); - return; - } - case fasl_type_box: - case fasl_type_immutable_box: - *x = Sbox(FIX(0)); - faslin(tc, &INITBOXREF(*x), t, pstrbuf, f); - if (ty == fasl_type_immutable_box) - BOXTYPE(*x) = type_immutable_box; - return; - case fasl_type_symbol: { - iptr n; - n = stringin(pstrbuf, 0, f); - *x = S_intern_sc(&STRIT(*pstrbuf, 0), n, Sfalse); - return; - } - case fasl_type_gensym: { - iptr pn, un; - pn = stringin(pstrbuf, 0, f); - un = stringin(pstrbuf, pn, f); - *x = S_intern3(&STRIT(*pstrbuf, 0), pn, &STRIT(*pstrbuf, pn), un, Sfalse, Sfalse); - return; - } - case fasl_type_ratnum: - *x = S_rational(FIX(0), FIX(0)); - faslin(tc, &RATNUM(*x), t, pstrbuf, f); - faslin(tc, &RATDEN(*x), t, pstrbuf, f); - return; - case fasl_type_exactnum: - *x = S_exactnum(FIX(0), FIX(0)); - faslin(tc, &EXACTNUM_REAL_PART(*x), t, pstrbuf, f); - faslin(tc, &EXACTNUM_IMAG_PART(*x), t, pstrbuf, f); - return; - case fasl_type_vector: - case fasl_type_immutable_vector: { - iptr n; ptr *p; - n = uptrin(f); - *x = S_vector(n); - p = &INITVECTIT(*x, 0); - while (n--) faslin(tc, p++, t, pstrbuf, f); - if (ty == fasl_type_immutable_vector) { - if (Svector_length(*x) == 0) - *x = NULLIMMUTABLEVECTOR(tc); - else - VECTTYPE(*x) |= vector_immutable_flag; - } - return; - } - case fasl_type_fxvector: - case fasl_type_immutable_fxvector: { - iptr n; ptr *p; - n = uptrin(f); - *x = S_fxvector(n); - p = &FXVECTIT(*x, 0); - while (n--) { - iptr t = iptrin(f); - if (!FIXRANGE(t)) toolarge(f->uf->path); - *p++ = FIX(t); - } - if (ty == fasl_type_immutable_fxvector) { - if (Sfxvector_length(*x) == 0) - *x = NULLIMMUTABLEFXVECTOR(tc); - else - FXVECTOR_TYPE(*x) |= fxvector_immutable_flag; - } - return; - } - case fasl_type_bytevector: - case fasl_type_immutable_bytevector: { - iptr n; - n = uptrin(f); - *x = S_bytevector(n); - bytesin(&BVIT(*x,0), n, f); - if (ty == fasl_type_immutable_bytevector) { - if (Sbytevector_length(*x) == 0) - *x = NULLIMMUTABLEBYTEVECTOR(tc); - else - BYTEVECTOR_TYPE(*x) |= bytevector_immutable_flag; - } - return; - } - case fasl_type_base_rtd: { - ptr rtd; - if ((rtd = S_G.base_rtd) == Sfalse) { - if (!Srecordp(rtd)) S_error_abort("S_G.base-rtd has not been set"); - } - *x = rtd; - return; - } case fasl_type_rtd: { - ptr rtd, rtd_uid, plist, ls; - - faslin(tc, &rtd_uid, t, pstrbuf, f); - - /* look for rtd on uid's property list */ - plist = SYMSPLIST(rtd_uid); - for (ls = plist; ls != Snil; ls = Scdr(Scdr(ls))) { - if (Scar(ls) == S_G.rtd_key) { - ptr tmp; - *x = rtd = Scar(Scdr(ls)); - fasl_record(tc, &tmp, t, pstrbuf, f); - if (!rtd_equiv(tmp, rtd)) - S_error2("", "incompatible record type ~s in ~a", RECORDDESCNAME(tmp), f->uf->path); - return; - } - } - - fasl_record(tc, x, t, pstrbuf, f); - rtd = *x; - - /* register rtd on uid's property list */ - SETSYMSPLIST(rtd_uid, Scons(S_G.rtd_key, Scons(rtd, plist))); - return; - } - case fasl_type_record: { - fasl_record(tc, x, t, pstrbuf, f); - return; - } - case fasl_type_eq_hashtable: { - ptr rtd, ht, v; uptr subtype; uptr veclen, i, n; - if ((rtd = S_G.eq_ht_rtd) == Sfalse) { - S_G.eq_ht_rtd = rtd = SYMVAL(S_intern((const unsigned char *)"$eq-ht-rtd")); - if (!Srecordp(rtd)) S_error_abort("$eq-ht-rtd has not been set"); - } - *x = ht = S_record(size_record_inst(UNFIX(RECORDDESCSIZE(rtd)))); - RECORDINSTTYPE(ht) = rtd; - INITPTRFIELD(ht,eq_hashtable_type_disp) = S_G.eq_symbol; - INITPTRFIELD(ht,eq_hashtable_mutablep_disp) = bytein(f) ? Strue : Sfalse; - switch ((subtype = bytein(f))) { - case eq_hashtable_subtype_normal: - case eq_hashtable_subtype_weak: - case eq_hashtable_subtype_ephemeron: - INITPTRFIELD(ht,eq_hashtable_subtype_disp) = FIX(subtype); - break; - default: - S_error2("", "invalid eq-hashtable subtype code", FIX(subtype), f->uf->path); - } - INITPTRFIELD(ht,eq_hashtable_minlen_disp) = FIX(uptrin(f)); - veclen = uptrin(f); - INITPTRFIELD(ht,eq_hashtable_vec_disp) = v = S_vector(veclen); - n = uptrin(f); - INITPTRFIELD(ht,eq_hashtable_size_disp) = FIX(n); - for (i = 0; i < veclen ; i += 1) { INITVECTIT(v, i) = FIX(i); } - while (n > 0) { - ptr keyval; - switch (subtype) { - case eq_hashtable_subtype_normal: - keyval = Scons(FIX(0), FIX(0)); - break; - case eq_hashtable_subtype_weak: - keyval = S_cons_in(space_weakpair, 0, FIX(0), FIX(0)); - break; - case eq_hashtable_subtype_ephemeron: - default: - keyval = S_cons_in(space_ephemeron, 0, FIX(0), FIX(0)); - break; - } - faslin(tc, &INITCAR(keyval), t, pstrbuf, f); - faslin(tc, &INITCDR(keyval), t, pstrbuf, f); - i = ((uptr)Scar(keyval) >> primary_type_bits) & (veclen - 1); - INITVECTIT(v, i) = S_tlc(keyval, ht, Svector_ref(v, i)); - n -= 1; - } - return; - } - case fasl_type_symbol_hashtable: { - ptr rtd, ht, equiv, v; uptr equiv_code, veclen, i, n; - if ((rtd = S_G.symbol_ht_rtd) == Sfalse) { - S_G.symbol_ht_rtd = rtd = SYMVAL(S_intern((const unsigned char *)"$symbol-ht-rtd")); - if (!Srecordp(rtd)) S_error_abort("$symbol-ht-rtd has not been set"); - } - *x = ht = S_record(size_record_inst(UNFIX(RECORDDESCSIZE(rtd)))); - RECORDINSTTYPE(ht) = rtd; - INITPTRFIELD(ht,symbol_hashtable_type_disp) = S_G.symbol_symbol; - INITPTRFIELD(ht,symbol_hashtable_mutablep_disp) = bytein(f) ? Strue : Sfalse; - INITPTRFIELD(ht,symbol_hashtable_minlen_disp) = FIX(uptrin(f)); - equiv_code = bytein(f); - switch (equiv_code) { - case 0: - if ((equiv = S_G.eqp) == Sfalse) { - S_G.eqp = equiv = SYMVAL(S_intern((const unsigned char *)"eq?")); - if (!Sprocedurep(equiv)) S_error_abort("fasl: eq? has not been set"); - } - break; - case 1: - if ((equiv = S_G.eqvp) == Sfalse) { - S_G.eqvp = equiv = SYMVAL(S_intern((const unsigned char *)"eqv?")); - if (!Sprocedurep(equiv)) S_error_abort("fasl: eqv? has not been set"); - } - break; - case 2: - if ((equiv = S_G.equalp) == Sfalse) { - S_G.equalp = equiv = SYMVAL(S_intern((const unsigned char *)"equal?")); - if (!Sprocedurep(equiv)) S_error_abort("fasl: equal? has not been set"); - } - break; - case 3: - if ((equiv = S_G.symboleqp) == Sfalse) { - S_G.symboleqp = equiv = SYMVAL(S_intern((const unsigned char *)"symbol=?")); - if (!Sprocedurep(equiv)) S_error_abort("fasl: symbol=? has not been set"); - } - break; - default: - S_error2("", "invalid symbol-hashtable equiv code", FIX(equiv_code), f->uf->path); - /* make compiler happy */ - equiv = Sfalse; - } - INITPTRFIELD(ht,symbol_hashtable_equivp_disp) = equiv; - veclen = uptrin(f); - INITPTRFIELD(ht,symbol_hashtable_vec_disp) = v = S_vector(veclen); - n = uptrin(f); - INITPTRFIELD(ht,symbol_hashtable_size_disp) = FIX(n); - for (i = 0; i < veclen ; i += 1) { INITVECTIT(v, i) = Snil; } - while (n > 0) { - ptr keyval; - keyval = Scons(FIX(0), FIX(0)); - faslin(tc, &INITCAR(keyval), t, pstrbuf, f); - faslin(tc, &INITCDR(keyval), t, pstrbuf, f); - i = UNFIX(SYMHASH(Scar(keyval))) & (veclen - 1); - INITVECTIT(v, i) = Scons(keyval, Svector_ref(v, i)); - n -= 1; - } - return; - } - case fasl_type_closure: { - ptr cod; iptr offset; - offset = uptrin(f); - *x = S_closure((ptr)0, 0); - faslin(tc, &cod, t, pstrbuf, f); - CLOSENTRY(*x) = (ptr)((uptr)cod + offset); - return; - } - case fasl_type_flonum: { - *x = Sflonum(doublein(f)); - return; - } - case fasl_type_inexactnum: { - ptr rp, ip; - faslin(tc, &rp, t, pstrbuf, f); - faslin(tc, &ip, t, pstrbuf, f); - *x = S_inexactnum(FLODAT(rp), FLODAT(ip)); - return; - } - case fasl_type_string: - case fasl_type_immutable_string: { - iptr i, n; ptr str; - n = uptrin(f); - str = S_string((char *)0, n); - for (i = 0; i != n; i += 1) Sstring_set(str, i, uptrin(f)); - if (ty == fasl_type_immutable_string) { - if (n == 0) - str = NULLIMMUTABLESTRING(tc); - else - STRTYPE(str) |= string_immutable_flag; - } - *x = str; - return; - } - case fasl_type_small_integer: - *x = Sinteger(iptrin(f)); - return; - case fasl_type_large_integer: { - IBOOL sign; iptr n; ptr t; bigit *p; - sign = bytein(f); - n = uptrin(f); - t = S_bignum(tc, n, sign); - p = &BIGIT(t, 0); - while (n--) *p++ = (bigit)uptrin(f); - *x = S_normalize_bignum(t); - return; - } - case fasl_type_weak_pair: - *x = S_cons_in(space_weakpair, 0, FIX(0), FIX(0)); - faslin(tc, &INITCAR(*x), t, pstrbuf, f); - faslin(tc, &INITCDR(*x), t, pstrbuf, f); - return; - case fasl_type_ephemeron: - *x = S_cons_in(space_ephemeron, 0, FIX(0), FIX(0)); - faslin(tc, &INITCAR(*x), t, pstrbuf, f); - faslin(tc, &INITCDR(*x), t, pstrbuf, f); - return; - case fasl_type_code: { - iptr n, m, a; INT flags; iptr free; - ptr co, reloc, name, pinfos; - flags = bytein(f); - free = uptrin(f); - n = uptrin(f) /* length in bytes of code */; - *x = co = S_code(tc, type_code | (flags << code_flags_offset), n); - CODEFREE(co) = free; - faslin(tc, &name, t, pstrbuf, f); - if (Sstringp(name)) name = SYMNAME(S_intern_sc(&STRIT(name, 0), Sstring_length(name), name)); - CODENAME(co) = name; - faslin(tc, &CODEARITYMASK(co), t, pstrbuf, f); - faslin(tc, &CODEINFO(co), t, pstrbuf, f); - faslin(tc, &pinfos, t, pstrbuf, f); - CODEPINFOS(co) = pinfos; - if (pinfos != Snil) { - S_G.profile_counters = Scons(S_weak_cons(co, pinfos), S_G.profile_counters); - } - bytesin((octet *)&CODEIT(co, 0), n, f); - m = uptrin(f); - CODERELOC(co) = reloc = S_relocation_table(m); - RELOCCODE(reloc) = co; - a = 0; - n = 0; - while (n < m) { - INT type_etc, type; uptr item_off, code_off; - ptr obj; - type_etc = bytein(f); - type = type_etc >> 2; - code_off = uptrin(f); - item_off = (type_etc & 2) ? uptrin(f) : 0; - if (type_etc & 1) { - RELOCIT(reloc,n) = (type << reloc_type_offset)|reloc_extended_format ; n += 1; - RELOCIT(reloc,n) = item_off; n += 1; - RELOCIT(reloc,n) = code_off; n += 1; - } else { - RELOCIT(reloc,n) = MAKE_SHORT_RELOC(type,code_off,item_off); n += 1; - } - a += code_off; - faslin(tc, &obj, t, pstrbuf, f); - S_set_code_obj("read", type, co, a, obj, item_off); - } - return; - } - case fasl_type_immediate: - *x = (ptr)uptrin(f); - return; - case fasl_type_entry: - *x = (ptr)S_lookup_c_entry(uptrin(f)); - return; - case fasl_type_library: - *x = S_lookup_library_entry(uptrin(f), 1); - return; - case fasl_type_library_code: - *x = CLOSCODE(S_lookup_library_entry(uptrin(f), 1)); - return; - case fasl_type_graph: - faslin(tc, x, S_vector(uptrin(f)), pstrbuf, f); - return; - case fasl_type_graph_def: { - ptr *p; - p = &INITVECTIT(t, uptrin(f)); - faslin(tc, p, t, pstrbuf, f); - *x = *p; - return; - } - case fasl_type_graph_ref: - *x = Svector_ref(t, uptrin(f)); - return; - default: - S_error2("", "invalid object type ~d in fasl file ~a", FIX(ty), f->uf->path); - } -} - -#define big 0 -#define little 1 -static void fasl_record(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f) { - uptr size, n, addr; ptr p; UINT padty; - - size = uptrin(f); - n = uptrin(f); - *x = p = S_record(size_record_inst(size)); - faslin(tc, &RECORDINSTTYPE(p), t, pstrbuf, f); - addr = (uptr)&RECORDINSTIT(p, 0); - for (; n != 0; n -= 1) { - padty = bytein(f); - addr += padty >> 4; - switch (padty & 0xf) { - case fasl_fld_ptr: - faslin(tc, (ptr *)addr, t, pstrbuf, f); - addr += sizeof(ptr); - break; - case fasl_fld_u8: - *(U8 *)addr = (U8)bytein(f); - addr += 1; - break; - case fasl_fld_i16: - *(I16 *)addr = (I16)iptrin(f); - addr += 2; - break; - case fasl_fld_i24: { - iptr q = iptrin(f); -#if (native_endianness == little) - *(U16 *)addr = (U16)q; - *(U8 *)(addr + 2) = (U8)(q >> 16); -#elif (native_endianness == big) - *(U16 *)addr = (U16)(q >> 8); - *(U8 *)(addr + 2) = (U8)q; -#else - unexpected_endianness(); -#endif - addr += 3; - break; - } - case fasl_fld_i32: - *(I32 *)addr = (I32)iptrin(f); - addr += 4; - break; - case fasl_fld_i40: { - I64 q; -#if (ptr_bits == 32) - q = (I64)iptrin(f) << 32; - q |= (U32)uptrin(f); -#elif (ptr_bits == 64) - q = (I64)iptrin(f); -#else - unexpected_ptr_bits(); -#endif -#if (native_endianness == little) - *(U32 *)addr = (U32)q; - *(U8 *)(addr + 4) = (U8)(q >> 32); -#elif (native_endianness == big) - *(U32 *)addr = (U32)(q >> 8); - *(U8 *)(addr + 4) = (U8)q; -#else - unexpected_endianness(); -#endif - addr += 5; - break; - } - case fasl_fld_i48: { - I64 q; -#if (ptr_bits == 32) - q = (I64)iptrin(f) << 32; - q |= (U32)uptrin(f); -#elif (ptr_bits == 64) - q = (I64)iptrin(f); -#else - unexpected_ptr_bits(); -#endif -#if (native_endianness == little) - *(U32 *)addr = (U32)q; - *(U16 *)(addr + 4) = (U16)(q >> 32); -#elif (native_endianness == big) - *(U32 *)addr = (U32)(q >> 16); - *(U16 *)(addr + 4) = (U16)q; -#else - unexpected_endianness(); -#endif - addr += 6; - break; - } - case fasl_fld_i56: { - I64 q; -#if (ptr_bits == 32) - q = (I64)iptrin(f) << 32; - q |= (U32)uptrin(f); -#elif (ptr_bits == 64) - q = (I64)iptrin(f); -#else - unexpected_ptr_bits(); -#endif -#if (native_endianness == little) - *(U32 *)addr = (U32)q; - *(U16 *)(addr + 4) = (U16)(q >> 32); - *(U8 *)(addr + 6) = (U8)(q >> 48); -#elif (native_endianness == big) - *(U32 *)addr = (U32)(q >> 24); - *(U32 *)(addr + 3) = (U32)q; -#else - unexpected_endianness(); -#endif - addr += 7; - break; - } - case fasl_fld_i64: { - I64 q; -#if (ptr_bits == 32) - q = (I64)iptrin(f) << 32; - q |= (U32)uptrin(f); -#elif (ptr_bits == 64) - q = (I64)iptrin(f); -#else - unexpected_ptr_bits(); -#endif - *(I64 *)addr = q; - addr += 8; - break; - } - case fasl_fld_single: - *(float *)addr = (float)singlein(f); - addr += sizeof(float); - break; - case fasl_fld_double: - *(double *)addr = (double)doublein(f); - addr += sizeof(double); - break; - default: - S_error1("", "unrecognized record fld type ~d", FIX(padty & 0xf)); - break; - } - } -} - -/* limited version for checking rtd fields */ -static IBOOL equalp(ptr x, ptr y) { - if (x == y) return 1; - if (Spairp(x)) return Spairp(y) && equalp(Scar(x), Scar(y)) && equalp(Scdr(x), Scdr(y)); - if (Svectorp(x)) { - iptr n; - if (!Svectorp(y)) return 0; - if ((n = Svector_length(x)) != Svector_length(y)) return 0; - while (--n >= 0) if (!equalp(Svector_ref(x, n), Svector_ref(y, n))) return 0; - return 1; - } - return Sbignump(x) && Sbignump(y) && S_big_eq(x, y); -} - -static IBOOL rtd_equiv(ptr x, ptr y) { - return RECORDINSTTYPE(x) == RECORDINSTTYPE(y) && - RECORDDESCPARENT(x) == RECORDDESCPARENT(y) && - equalp(RECORDDESCPM(x), RECORDDESCPM(y)) && - equalp(RECORDDESCMPM(x), RECORDDESCMPM(y)) && - equalp(RECORDDESCFLDS(x), RECORDDESCFLDS(y)) && - RECORDDESCSIZE(x) == RECORDDESCSIZE(y) && - RECORDDESCFLAGS(x) == RECORDDESCFLAGS(y); -} - -#ifdef HPUX -INT pax_decode21(INT x) -{ - INT x0_4, x5_6, x7_8, x9_19, x20; - - x20 = x & 0x1; x >>= 1; - x9_19 = x & 0x7ff; x >>= 11; - x7_8 = x & 0x3; x >>= 2; - x5_6 = x & 0x3; - x0_4 = x >> 2; - - return (((x20<<11 | x9_19)<<2 | x5_6)<<5 | x0_4)<<2 | x7_8; -} - -INT pax_encode21(INT n) -{ - INT x0_4, x5_6, x7_8, x9_19, x20; - - x7_8 = n & 0x3; n >>= 2; - x0_4 = n & 0x1f; n >>= 5; - x5_6 = n & 0x3; n >>= 2; - x9_19 = n & 0x7ff; - x20 = n >> 11; - - return (((x0_4<<2 | x5_6)<<2 | x7_8)<<11 | x9_19)<<1 | x20; -} -#endif /* HPUX */ - -/* used here, in S_gc(), and in compile.ss */ -void S_set_code_obj(char *who, IFASLCODE typ, ptr p, iptr n, ptr x, iptr o) { - void *address; uptr item; - - address = (void *)((uptr)p + n); - item = (uptr)x + o; - switch (typ) { - case reloc_abs: - *(uptr *)address = item; - break; -#ifdef ARMV6 - case reloc_arm32_abs: - arm32_set_abs(address, item); - break; - case reloc_arm32_jump: - arm32_set_jump(address, item, 0); - break; - case reloc_arm32_call: - arm32_set_jump(address, item, 1); - break; -#endif /* ARMV6 */ -#ifdef PPC32 - case reloc_ppc32_abs: - ppc32_set_abs(address, item); - break; - case reloc_ppc32_jump: - ppc32_set_jump(address, item, 0); - break; - case reloc_ppc32_call: - ppc32_set_jump(address, item, 1); - break; -#endif /* PPC32 */ -#ifdef I386 - case reloc_rel: - item = item - ((uptr)address + sizeof(uptr)); - *(uptr *)address = item; - break; -#endif /* I386 */ -#ifdef X86_64 - case reloc_x86_64_jump: - x86_64_set_jump(address, item, 0); - break; - case reloc_x86_64_call: - x86_64_set_jump(address, item, 1); - break; -#endif /* X86_64 */ -#ifdef SPARC64 - case reloc_sparc64abs: - sparc64_set_literal(address, item); - break; - /* we don't use this presently since it can't handle out-of-range - relocations */ - case reloc_sparc64rel: - /* later: make the damn thing local by copying it an - every other code object we can reach into a single - close area of memory */ - item = item - (uptr)address; - if ((iptr)item < -0x20000000 || (iptr)item > 0x1FFFFFFF) - S_error1("", "sparc64rel address out of range ~x", - Sunsigned((uptr)address)); - *(U32 *)address = *(U32 *)address & ~0x3fffffff | item >> 2 & 0x3fffffff; - break; -#endif /* SPARC64 */ -#ifdef SPARC - case reloc_sparcabs: - *(U32 *)address = *(U32 *)address & ~0x3fffff | item >> 10 & 0x3fffff; - *((U32 *)address + 1) = *((U32 *)address + 1) & ~0x3ff | item & 0x3ff; - break; - case reloc_sparcrel: - item = item - (uptr)address; - *(U32 *)address = *(U32 *)address & ~0x3fffffff | item >> 2 & 0x3fffffff; - break; -#endif /* SPARC */ - default: - S_error1(who, "invalid relocation type ~s", FIX(typ)); - } -} - -/* used in S_gc() */ -ptr S_get_code_obj(IFASLCODE typ, ptr p, iptr n, iptr o) { - void *address; uptr item; - - address = (void *)((uptr)p + n); - switch (typ) { - case reloc_abs: - item = *(uptr *)address; - break; -#ifdef ARMV6 - case reloc_arm32_abs: - item = arm32_get_abs(address); - break; - case reloc_arm32_jump: - case reloc_arm32_call: - item = arm32_get_jump(address); - break; -#endif /* ARMV6 */ -#ifdef PPC32 - case reloc_ppc32_abs: - item = ppc32_get_abs(address); - break; - case reloc_ppc32_jump: - case reloc_ppc32_call: - item = ppc32_get_jump(address); - break; -#endif /* PPC32 */ -#ifdef I386 - case reloc_rel: - item = *(uptr *)address; - item = item + ((uptr)address + sizeof(uptr)); - break; -#endif /* I386 */ -#ifdef X86_64 - case reloc_x86_64_jump: - case reloc_x86_64_call: - item = x86_64_get_jump(address); - break; -#endif /* X86_64 */ -#ifdef SPARC64 - case reloc_sparc64abs: - item = sparc64_get_literal(address); - break; - case reloc_sparc64rel: - item = (*(U32 *)address & 0x3fffffff) << 2; - if (item & 0x80000000) /* sign bit set */ - item = item | 0xffffffff00000000; - item = (uptr)address + (iptr)item; - break; -#endif /* SPARC64 */ -#ifdef SPARC - case reloc_sparcabs: - item = (*(U32 *)address & 0x3fffff) << 10 | *((U32 *)address + 1) & 0x3ff; - break; - case reloc_sparcrel: - item = (*(U32 *)address & 0x3fffffff) << 2; - item += (uptr)address; - break; -#endif /* SPARC */ - default: - S_error1("", "invalid relocation type ~s", FIX(typ)); - return (ptr)0 /* not reached */; - } - return (ptr)(item - o); -} - - -#ifdef ARMV6 -static void arm32_set_abs(void *address, uptr item) { - /* code generator produces ldrlit destreg, 0; brai 0; long 0 */ - /* we change long 0 => long item */ - *((U32 *)address + 2) = item; -} - -static uptr arm32_get_abs(void *address) { - return *((U32 *)address + 2); -} - -#define MAKE_B(n) (0xEA000000 | (n)) -#define MAKE_BL(n) (0xEB000000 | (n)) -#define B_OR_BL_DISP(x) ((x) & 0xFFFFFF) -#define MAKE_BX(reg) (0xE12FFF10 | (reg)) -#define MAKE_BLX(reg) (0xE12FFF30 | (reg)) -#define MAKE_LDRLIT(dst,n) (0xE59F0000 | ((dst) << 12) | (n)) -#define LDRLITP(x) (((x) & 0xFFFF0000) == 0xE59F0000) -#define LDRLIT_DST(x) (((x) >> 12) & 0xf) -#define MAKE_MOV(dst,src) (0xE1A00000 | ((dst) << 12) | (src)) -#define MOV_SRC(x) ((x) & 0xf) -/* nop instruction is not supported by all ARMv6 chips, so use recommended mov r0, r0 */ -#define NOP MAKE_MOV(0,0) - -static void arm32_set_jump(void *address, uptr item, IBOOL callp) { - /* code generator produces ldrlit %ip, 0; brai 0; long 0; bx or blx %ip */ - U32 inst = *((U32 *)address + 0); - INT reg = LDRLITP(inst) ? LDRLIT_DST(inst) : MOV_SRC(*((U32 *)address + 1)); - I32 worddisp = (U32 *)item - ((U32 *)address + 2); - if (worddisp >= -0x800000 && worddisp <= 0x7FFFFF) { - worddisp &= 0xFFFFFF; - *((U32 *)address + 0) = (callp ? MAKE_BL(worddisp) : MAKE_B(worddisp)); - *((U32 *)address + 1) = MAKE_MOV(reg,reg); /* effective NOP recording tmp reg for later use */ - *((U32 *)address + 2) = NOP; - *((U32 *)address + 3) = NOP; - } else { - *((U32 *)address + 0) = MAKE_LDRLIT(reg,0); - *((U32 *)address + 1) = MAKE_B(0); - *((U32 *)address + 2) = item; - *((U32 *)address + 3) = (callp ? MAKE_BLX(reg) : MAKE_BX(reg)); - } -} - -static uptr arm32_get_jump(void *address) { - U32 inst = *((U32 *)address + 0); - if (LDRLITP(inst)) { - return *((U32 *)address + 2); - } else { - I32 worddisp = B_OR_BL_DISP(inst); - if (worddisp >= 0x800000) worddisp -= 0x1000000; - return (uptr)(((U32 *)address + 2) + worddisp); - } -} -#endif /* ARMV6 */ - -#ifdef PPC32 - -#define UPDATE_ADDIS(item, instr) (((instr) & ~0xFFFF) | (((item) >> 16) & 0xFFFF)) -#define UPDATE_ADDI(item, instr) (((instr) & ~0xFFFF) | ((item) & 0xFFFF)) - -#define MAKE_B(disp, callp) ((18 << 26) | (((disp) & 0xFFFFFF) << 2) | (callp)) -#define MAKE_ADDIS(item) ((15 << 26) | (((item) >> 16) & 0xFFFF)) -#define MAKE_ORI(item) ((24 << 26) | ((item) & 0xFFFF)) -#define MAKE_NOP ((24 << 26)) -#define MAKE_MTCTR ((31 << 26) | (9 << 16) | (467 << 1)) -#define MAKE_BCTR(callp) ((19 << 26) | (20 << 21) | (528 << 1) | (callp)) - -static void ppc32_set_abs(void *address, uptr item) { - /* code generator produces addis destreg, %r0, 0 (hi) ; addi destreg, destreg, 0 (lo) */ - /* we change 0 (hi) => upper 16 bits of address */ - /* we change 0 (lo) => lower 16 bits of address */ - /* low part is signed: if negative, increment high part */ - item = item + (item << 1 & 0x10000); - *((U32 *)address + 0) = UPDATE_ADDIS(item, *((U32 *)address + 0)); - *((U32 *)address + 1) = UPDATE_ADDI(item, *((U32 *)address + 1)); -} - -static uptr ppc32_get_abs(void *address) { - uptr item = ((*((U32 *)address + 0) & 0xFFFF) << 16) | (*((U32 *)address + 1) & 0xFFFF); - return item - (item << 1 & 0x10000); -} - -static void ppc32_set_jump(void *address, uptr item, IBOOL callp) { - iptr disp = (iptr *)item - (iptr *)address; - if (-0x800000 <= disp && disp <= 0x7FFFFF) { - *((U32 *)address + 0) = MAKE_B(disp, callp); - *((U32 *)address + 1) = MAKE_NOP; - *((U32 *)address + 2) = MAKE_NOP; - *((U32 *)address + 3) = MAKE_NOP; - } else { - *((U32 *)address + 0) = MAKE_ADDIS(item); - *((U32 *)address + 1) = MAKE_ORI(item); - *((U32 *)address + 2) = MAKE_MTCTR; - *((U32 *)address + 3) = MAKE_BCTR(callp); - } -} - -static uptr ppc32_get_jump(void *address) { - uptr item, instr = *(U32 *)address; - - if ((instr >> 26) == 18) { - /* bl disp */ - iptr disp = (instr >> 2) & 0xFFFFFF; - if (disp & 0x800000) disp -= 0x1000000; - item = (uptr)address + (disp << 2); - } else { - /* lis r0, high - ori r0, r0, low */ - item = ((instr & 0xFFFF) << 16) | (*((U32 *)address + 1) & 0xFFFF); - } - - return item; -} -#endif /* PPC32 */ - -#ifdef X86_64 -static void x86_64_set_jump(void *address, uptr item, IBOOL callp) { - I64 disp = (I64)item - ((I64)address + 5); /* 5 = size of call instruction */ - if ((I32)disp == disp) { - *(octet *)address = callp ? 0xE8 : 0xE9; /* call or jmp disp32 opcode */ - *(I32 *)((uptr)address + 1) = (I32)disp; - /* 7-byte long NOP */ - *((octet *)address + 5) = 0x0f; - *((octet *)address + 6) = 0x1f; - *((octet *)address + 7) = 0x80; - *((octet *)address + 8) = 0x00; - *((octet *)address + 9) = 0x00; - *((octet *)address + 10) = 0x00; - *((octet *)address + 11) = 0x00; - } else { - *(octet *)address = 0x48; /* REX w/REX.w set */ - *((octet *)address + 1)= 0xB8; /* MOV imm64 to RAX */ - *(uptr *)((uptr)address + 2) = item; - *((octet *)address + 10) = 0xFF; /* call/jmp reg/mem opcode */ - *((octet *)address + 11) = callp ? 0xD0 : 0xE0; /* mod=11, ttt=010 (call) or 100 (jmp), r/m = 0 (RAX) */ - } -} - -static uptr x86_64_get_jump(void *address) { - if (*(octet *)address == 0x48) /* REX w/REX.w set */ - /* must be long form: move followed by call/jmp */ - return *(uptr *)((uptr)address + 2); - else - /* must be short form: call/jmp */ - return ((uptr)address + 5) + *(I32 *)((uptr)address + 1); -} -#endif /* X86_64 */ - -#ifdef SPARC64 -#define ASMREG0 1 -/* TMPREG is asm-literal-tmp in sparc64macros.ss */ -#define TMPREG 5 -/* CRETREG is retreg in sparc64macros.ss */ -#define CRETREG 15 -/* SRETREG is ret in sparc64macros.ss */ -#define SRETREG 26 - -#define OP_ADDI 0x80002000 -#define OP_CALL 0x40000000 -#define OP_JSR 0x81C00000 -#define OP_OR 0x80100000 -#define OP_ORI 0x80102000 -#define OP_SETHI 0x1000000 -/* SLLXI is the 64-bit version */ -#define OP_SLLXI 0x81283000 -#define OP_XORI 0x80182000 -/* NOP is sethi %g0,0 */ -#define NOP 0x1000000 -#define IMMMASK (U32)0x1fff -#define IMMRANGE(x) ((U32)(x) + (U32)0x1000 <= IMMMASK) -#define ADDI(src,imm,dst) (OP_ADDI | (dst) << 25 | (src) << 14 | (imm) & IMMMASK) -#define JSR(src) (OP_JSR | CRETREG << 25 | (src) << 14) -#define ORI(src,imm,dst) (OP_ORI | (dst) << 25 | (src) << 14 | (imm) & IMMMASK) -#define SETHI(dst,high) (OP_SETHI | (dst) << 25 | (high) & 0x3fffff) -#define CALL(disp) (OP_CALL | (disp) >> 2 & 0x3fffffff) - - -static INT extract_reg_from_sethi(void* address) { - return *(U32 *)address >> 25; -} - -static void emit_sethi_lo(U32 item, INT destreg, void *address) { - U32 high = item >> 10; - U32 low = item & 0x3ff; - - /* sethi destreg, high */ - *(U32 *)address = SETHI(destreg,high); - /* setlo destreg, low */ - *((U32 *)address + 1) = ORI(destreg,low,destreg); -} - -static uptr sparc64_get_literal(void *address) { - uptr item; - - /* we may have "call disp" followed by delay instruction */ - item = *(U32 *)address; - if (item >> 30 == OP_CALL >> 30) { - item = (item & 0x3fffffff) << 2; - if (item & 0x80000000) /* sign bit set */ - item = item | 0xffffffff00000000; - item = (uptr)address + (iptr)item; - return item; - } - - item = (item & 0x3fffff) << 10 | *((U32 *)address + 1) & 0x3ff; - if (*((U32 *)address + 2) != NOP) { - item = item << 32 | - (*((U32 *)address + 3) & 0x3fffff) << 10 | - *((U32 *)address + 4) & 0x3ff; - } - return item; -} - -static U32 adjust_delay_inst(delay_inst, old_call_addr, new_call_addr) - U32 delay_inst; U32 *old_call_addr, *new_call_addr; { - INT offset; - - offset = sizeof(U32) * (old_call_addr - new_call_addr); - if (offset == 0) return delay_inst; - - if ((delay_inst & ~IMMMASK) == ADDI(CRETREG,0,SRETREG)) { - INT k = delay_inst & IMMMASK; - k = k - ((k << 1) & (IMMMASK+1)); - offset = k + offset; - if (IMMRANGE(offset)) return ADDI(CRETREG,offset,SRETREG); - } else if ((delay_inst & ~IMMMASK) == ADDI(CRETREG,0,CRETREG)) { - INT k = delay_inst & IMMMASK; - k = k - ((k << 1) & (IMMMASK+1)); - offset = k + offset; - if (offset == 0) return NOP; - if (IMMRANGE(offset)) return ADDI(CRETREG,offset,CRETREG); - } else if (IMMRANGE(offset)) - return ADDI(CRETREG,offset,CRETREG); - - return 0; /* fortunately, not a valid instruction here */ -} - -static void sparc64_set_call(void *address, U32 *call_addr, uptr item) { - U32 delay_inst = *(call_addr + 1), new_delay_inst; iptr disp; - - /* later: make item local if it refers to Scheme code, i.e., is in the - Scheme heap, by copying it and every other code object we can reach - into a single close area of memory. Or generate a close stub. */ - disp = item - (uptr)address; - if (disp >= -0x20000000 && disp <= 0x1FFFFFFF && - (new_delay_inst = adjust_delay_inst(delay_inst, call_addr, - (U32 *)address))) { - *(U32 *)address = CALL(disp); - *((U32 *)address + 1) = new_delay_inst; - } else { - INT n = sparc64_set_lit_only(address, item, ASMREG0); - new_delay_inst = adjust_delay_inst(delay_inst, call_addr, (U32 *)address + n); - *((U32 *)address + n) = JSR(ASMREG0); - *((U32 *)address + n + 1) = new_delay_inst; - } -} - -static INT sparc64_set_lit_only(void *address, uptr item, I32 destreg) { - - if ((iptr)item >= -0xffffffff && item <= 0xffffffff) { - uptr x, high, low; - - if ((iptr)item < 0) { - x = 0x100000000 - item; - high = x >> 10; - low = x - (high << 10); - /* sethi destreg, ~high */ - *(U32 *)address = OP_SETHI | destreg << 25 | ~high & 0x3fffff; - /* xor.i destreg, low|0x1c00, destreg */ - *((U32 *)address + 1) = OP_XORI | destreg << 25 | destreg << 14 | - low | 0x1c00; - } else { - emit_sethi_lo(item, destreg, address); - } - *((U32 *)address + 2) = NOP; - *((U32 *)address + 3) = NOP; - *((U32 *)address + 4) = NOP; - *((U32 *)address + 5) = NOP; - return 2; - } else { - emit_sethi_lo(item >> 32, destreg, address); - /* sll destreg, 32, destreg */ - *((U32 *)address + 2) = OP_SLLXI | destreg << 25 | destreg << 14 | 32; - emit_sethi_lo(item & 0xffffffff, TMPREG, (void *)((U32 *)address+3)); - /* or destreg, tmpreg, destreg */ - *((U32 *)address + 5) = OP_OR | destreg << 25 | destreg << 14 | TMPREG; - return 6; - } -} - -static void sparc64_set_literal(void* address, uptr item) { - I32 destreg; - - /* case 1: we have call followed by delay inst */ - if (*(U32 *)address >> 30 == OP_CALL >> 30) { - sparc64_set_call(address, (U32 *)address, item); - return; - } - - destreg = extract_reg_from_sethi(address); - - /* case 2: we have two-instr load-literal followed by jsr and delay inst */ - if (*((U32 *)address + 2) == JSR(destreg)) { - sparc64_set_call(address, (U32 *)address + 2, item); - return; - } - - /* case 3: we have six-instr load-literal followed by jsr and a delay - instruction we're willing to try to deal with */ - if (*((U32 *)address + 6) == JSR(destreg) && - (*((U32 *)address + 7) & ~IMMMASK == ADDI(CRETREG,0,SRETREG) || - *((U32 *)address + 7) == NOP)) { - sparc64_set_call(address, (U32 *)address + 6, item); - return; - } - - /* case 4: we have a plain load-literal */ - sparc64_set_lit_only(address, item, destreg); -} -#endif /* SPARC64 */ diff --git a/ta6ob/c/fasl.o b/ta6ob/c/fasl.o deleted file mode 100644 index b1c7d97..0000000 Binary files a/ta6ob/c/fasl.o and /dev/null differ diff --git a/ta6ob/c/flushcache.c b/ta6ob/c/flushcache.c deleted file mode 100644 index e2520f9..0000000 --- a/ta6ob/c/flushcache.c +++ /dev/null @@ -1,87 +0,0 @@ -/* flushcache.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" - -#ifdef FLUSHCACHE -typedef struct { - uptr start; - uptr end; -} mod_range; - -#define mod_range_start(x) (((mod_range *)&BVIT(x,0))->start) -#define mod_range_end(x) (((mod_range *)&BVIT(x,0))->end) - -static uptr max_gap; - -static ptr make_mod_range(uptr start, uptr end) { - ptr bv = S_bytevector(sizeof(mod_range)); - mod_range_start(bv) = start; - mod_range_end(bv) = end; - return bv; -} - -/* we record info per thread so flush in one prematurely for another doesn't prevent - the other from doing its own flush...and also since it's not clear that flushing in one - actually syncs caches across cores & processors */ - -void S_record_code_mod(ptr tc, uptr addr, uptr bytes) { - uptr end = addr + bytes; - ptr ls = CODERANGESTOFLUSH(tc); - - if (ls != Snil) { - ptr last_mod = Scar(ls); - uptr last_end = mod_range_end(last_mod); - if (addr > last_end && addr - last_end < max_gap) { -#ifdef DEBUG - printf(" record_code_mod merging %x %x and %x %x\n", mod_range_start(last_mod), last_end, addr, end); fflush(stdout); -#endif - mod_range_end(last_mod) = end; - return; - } - } - -#ifdef DEBUG - printf(" record_code_mod new range %x to %x\n", addr, end); fflush(stdout); -#endif - CODERANGESTOFLUSH(tc) = S_cons_in(space_new, 0, make_mod_range(addr, end), ls); - return; -} - -extern void S_flush_instruction_cache(ptr tc) { - ptr ls; - - for (ls = CODERANGESTOFLUSH(tc); ls != Snil; ls = Scdr(ls)) { - S_doflush(mod_range_start(Scar(ls)), mod_range_end(Scar(ls))); - } - CODERANGESTOFLUSH(tc) = Snil; -} - -extern void S_flushcache_init(void) { - if (S_boot_time) { - max_gap = S_flushcache_max_gap(); - if (max_gap < (uptr)(code_data_disp + byte_alignment)) { - max_gap = (uptr)(code_data_disp + byte_alignment); - } - } -} -#else /* FLUSHCACHE */ - -extern void S_record_code_mod(UNUSED ptr tc, UNUSED uptr addr, UNUSED uptr bytes) {} -extern void S_flush_instruction_cache(UNUSED ptr tc) {} -extern void S_flushcache_init(void) { return; } - -#endif /* FLUSHCACHE */ diff --git a/ta6ob/c/flushcache.o b/ta6ob/c/flushcache.o deleted file mode 100644 index 19d08f1..0000000 Binary files a/ta6ob/c/flushcache.o and /dev/null differ diff --git a/ta6ob/c/foreign.c b/ta6ob/c/foreign.c deleted file mode 100644 index fbe9a12..0000000 --- a/ta6ob/c/foreign.c +++ /dev/null @@ -1,334 +0,0 @@ -/* foreign.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define debug(y) /* (void)printf(y) *//* uncomment printf for debug */ -/* #define UNLINK(x) 0 *//* uncomment #define to preserve temp files */ - - -#include "system.h" - -/* we can now return arbitrary values (aligned or not) - * since the garbage collector ignores addresses outside of the heap - * or within foreign segments */ -#define ptr_to_addr(p) ((void *)p) -#define addr_to_ptr(a) ((ptr)a) - -/* buckets should be prime */ -#define buckets 457 -#define multiplier 3 - -#define ptrhash(x) ((uptr)x % buckets) - -#ifdef LOAD_SHARED_OBJECT -#if defined(HPUX) -#include -#define dlopen(path,flags) (void *)shl_load(path, BIND_IMMEDIATE, 0L) -#define s_dlerror() Sstring_utf8(strerror(errno), -1) -#elif defined(WIN32) -#define dlopen(path,flags) S_ntdlopen(path) -#define dlsym(h,s) S_ntdlsym(h,s) -#define s_dlerror() S_ntdlerror() -#else -#include -#define s_dlerror() Sstring_utf8(dlerror(), -1) -#ifndef RTLD_NOW -#define RTLD_NOW 2 -#endif /* RTLD_NOW */ -#endif /* machine types */ -#endif /* LOAD_SHARED_OBJECT */ - -/* locally defined functions */ -static uptr symhash(const char *s); -static ptr lookup_static(const char *s); -static ptr lookup_dynamic(const char *s, ptr tbl); -static ptr lookup(const char *s); -static ptr remove_foreign_entry(const char *s); -static void *lookup_foreign_entry(const char *s); -static ptr foreign_entries(void); -static ptr foreign_static_table(void); -static ptr foreign_dynamic_table(void); -static ptr bvstring(const char *s); - -#ifdef LOAD_SHARED_OBJECT -static void load_shared_object(const char *path); -#endif /* LOAD_SHARED_OBJECT */ - -#ifdef HPUX -void *proc2entry(void *f, ptr name) { - if (((uptr)f & 2) == 0) - if (name == NULL) - S_error("Sforeign_symbol", "invalid entry"); - else - S_error1("Sforeign_symbol", "invalid entry for ~s", name); - return (void *)((uptr)f & ~0x3); -} -#endif /* HPUX */ - -static ptr bvstring(const char *s) { - iptr n = strlen(s) + 1; - ptr x = S_bytevector(n); - memcpy(&BVIT(x, 0), s, n); - return x; -} - -/* multiplier weights each character, h = n factors in the length */ -static uptr symhash(const char *s) { - uptr n, h; - - h = n = strlen(s); - while (n--) h = h * multiplier + (unsigned char)*s++; - return h % buckets; -} - -static ptr lookup_static(const char *s) { - uptr b; ptr p; - - b = symhash(s); - for (p = Svector_ref(S_G.foreign_static, b); p != Snil; p = Scdr(p)) - if (strcmp(s, (char *)&BVIT(Scar(Scar(p)),0)) == 0) - return Scdr(Scar(p)); - - return addr_to_ptr(0); -} - -#ifdef LOAD_SHARED_OBJECT -#define LOOKUP_DYNAMIC -static ptr lookup_dynamic(const char *s, ptr tbl) { - ptr p; - - for (p = tbl; p != Snil; p = Scdr(p)) { -#ifdef HPUX - (void *)value = (void *)0; /* assignment to prevent compiler warning */ - shl_t handle = (shl_t)ptr_to_addr(Scar(p)); - - if (shl_findsym(&handle, s, TYPE_PROCEDURE, (void *)&value) == 0) - return addr_to_ptr(proc2entry(value, NULL)); -#else /* HPUX */ - void *value; - - value = dlsym(ptr_to_addr(Scar(p)), s); - if (value != (void *)0) return addr_to_ptr(value); -#endif /* HPUX */ - } - - return addr_to_ptr(0); -} -#endif /* LOAD_SHARED_OBJECT */ - -static ptr lookup(const char *s) { - iptr b; ptr p; - -#ifdef LOOKUP_DYNAMIC - ptr x; - - x = lookup_dynamic(s, S_foreign_dynamic); - if (x == addr_to_ptr(0)) -#endif /* LOOKUP_DYNAMIC */ - - x = lookup_static(s); - if (x == addr_to_ptr(0)) return x; - - tc_mutex_acquire() - - b = ptrhash(x); - for (p = Svector_ref(S_G.foreign_names, b); p != Snil; p = Scdr(p)) { - if (Scar(Scar(p)) == x) { - SETCDR(Scar(p),bvstring(s)); - goto quit; - } - } - SETVECTIT(S_G.foreign_names, b, Scons(Scons(addr_to_ptr(x),bvstring(s)), - Svector_ref(S_G.foreign_names, b))); - -quit: - tc_mutex_release() - return x; -} - -void Sforeign_symbol(const char *s, void *v) { - iptr b; ptr x; - - tc_mutex_acquire() - -#ifdef HPUX - v = proc2entry(v,name); -#endif - - if ((x = lookup(s)) == addr_to_ptr(0)) { - b = symhash(s); - SETVECTIT(S_G.foreign_static, b, Scons(Scons(bvstring(s), addr_to_ptr(v)), - Svector_ref(S_G.foreign_static, b))); - } else if (ptr_to_addr(x) != v) - S_error1("Sforeign_symbol", "duplicate symbol entry for ~s", Sstring_utf8(s, -1)); - - tc_mutex_release() -} - -/* like Sforeign_symbol except it silently redefines the symbol - if it's already in S_G.foreign_static */ -void Sregister_symbol(const char *s, void *v) { - uptr b; ptr p; - - tc_mutex_acquire() - - b = symhash(s); - for (p = Svector_ref(S_G.foreign_static, b); p != Snil; p = Scdr(p)) - if (strcmp(s, (char *)&BVIT(Scar(Scar(p)),0)) == 0) { - INITCDR(Scar(p)) = addr_to_ptr(v); - goto quit; - } - SETVECTIT(S_G.foreign_static, b, Scons(Scons(bvstring(s), addr_to_ptr(v)), - Svector_ref(S_G.foreign_static, b))); - - quit: - tc_mutex_release() -} - -static ptr remove_foreign_entry(const char *s) { - uptr b; - ptr tbl, p1, p2; - - tc_mutex_acquire() - - b = symhash(s); - tbl = S_G.foreign_static; - p1 = Snil; - p2 = Svector_ref(tbl, b); - for (; p2 != Snil; p1 = p2, p2 = Scdr(p2)) { - if (strcmp(s, (char *)&BVIT(Scar(Scar(p2)), 0)) == 0) { - if (p1 == Snil) { - SETVECTIT(tbl, b, Scdr(p2)) - } else { - SETCDR(p1, Scdr(p2)) - } - tc_mutex_release() - return Strue; - } - } - tc_mutex_release() - return Sfalse; -} - -#ifdef LOAD_SHARED_OBJECT -static void load_shared_object(const char *path) { - void *handle; - - tc_mutex_acquire() - - handle = dlopen(path, RTLD_NOW); - if (handle == (void *)NULL) - S_error2("", "(while loading ~a) ~a", Sstring_utf8(path, -1), s_dlerror()); - S_foreign_dynamic = Scons(addr_to_ptr(handle), S_foreign_dynamic); - - tc_mutex_release() - - return; -} -#endif /* LOAD_SHARED_OBJECT */ - -void S_foreign_entry(void) { - ptr tc = get_thread_context(); - ptr name, x, bvname; - iptr i, n; - - name = AC0(tc); - if (Sfixnump(name) || Sbignump(name)) { - AC0(tc) = (ptr)Sinteger_value(name); - return; - } - - if (!(Sstringp(name))) { - S_error1("foreign-procedure", "invalid foreign procedure handle ~s", name); - } - - n = Sstring_length(name); - bvname = S_bytevector(n + 1); - for (i = 0; i != n; i += 1) { - int k = Sstring_ref(name, i); - if (k >= 256) k = '?'; - BVIT(bvname, i) = k; - } - BVIT(bvname, n) = 0; - - if ((x = lookup((char *)&BVIT(bvname, 0))) == addr_to_ptr(0)) { - S_error1("foreign-procedure", "no entry for ~s", name); - } - - AC0(tc) = x; -} - -static void *lookup_foreign_entry(s) const char *s; { - return ptr_to_addr(lookup(s)); -} - -static ptr foreign_entries(void) { - iptr b; ptr p, entries; - - entries = Snil; - - for (b = 0; b < buckets; b++) - for (p = Svector_ref(S_G.foreign_static, b); p != Snil; p = Scdr(p)) - entries = Scons(Sstring_utf8((char *)&BVIT(Scar(Scar(p)), 0), -1), entries); - - return entries; -} - -static ptr foreign_static_table(void) { return S_G.foreign_static; } -#ifdef LOAD_SHARED_OBJECT -static ptr foreign_dynamic_table(void) { return S_foreign_dynamic; } -#else -static ptr foreign_dynamic_table(void) { return Sfalse; } -#endif /* LOAD_SHARED_OBJECT */ - -static octet *foreign_address_name(ptr addr) { - iptr b; ptr p; - - b = ptrhash(addr); - for (p = Svector_ref(S_G.foreign_names, b); p != Snil; p = Scdr(p)) - if (Scar(Scar(p)) == (ptr)addr) - return &BVIT(Scdr(Scar(p)),0); - - return NULL; -} - -void S_foreign_init(void) { - if (S_boot_time) { - S_protect(&S_G.foreign_static); - S_G.foreign_static = S_vector(buckets); - {iptr i; for (i = 0; i < buckets; i++) INITVECTIT(S_G.foreign_static,i) = Snil;} - - S_protect(&S_G.foreign_names); - S_G.foreign_names = S_vector(buckets); - {iptr i; for (i = 0; i < buckets; i++) INITVECTIT(S_G.foreign_names,i) = Snil;} - -#ifdef LOAD_SHARED_OBJECT - S_protect(&S_foreign_dynamic); - S_foreign_dynamic = Snil; - Sforeign_symbol("(cs)load_shared_object", (void *)load_shared_object); -#endif /* LOAD_SHARED_OBJECT */ - - Sforeign_symbol("(cs)lookup_foreign_entry", (void *)lookup_foreign_entry); - Sforeign_symbol("(cs)remove_foreign_entry", (void *)remove_foreign_entry); - Sforeign_symbol("(cs)foreign_entries", (void *)foreign_entries); - Sforeign_symbol("(cs)foreign_static_table", (void *)foreign_static_table); - Sforeign_symbol("(cs)foreign_dynamic_table", (void *)foreign_dynamic_table); - Sforeign_symbol("(cs)foreign_address_name", (void *)foreign_address_name); - } - -#ifdef LOAD_SHARED_OBJECT - S_foreign_dynamic = Snil; -#endif /* LOAD_SHARED_OBJECT */ -} diff --git a/ta6ob/c/foreign.o b/ta6ob/c/foreign.o deleted file mode 100644 index b95ce74..0000000 Binary files a/ta6ob/c/foreign.o and /dev/null differ diff --git a/ta6ob/c/gc-011.c b/ta6ob/c/gc-011.c deleted file mode 100644 index 5fbbbef..0000000 --- a/ta6ob/c/gc-011.c +++ /dev/null @@ -1,23 +0,0 @@ -/* gc-011.c - * Copyright 1984-2020 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define GCENTRY S_gc_011 -#define MAX_CG 0 -#define MIN_TG 1 -#define MAX_TG 1 -#define compute_target_generation(g) 1 -#define NO_LOCKED_OLDSPACE_OBJECTS -#include "gc.c" diff --git a/ta6ob/c/gc-011.o b/ta6ob/c/gc-011.o deleted file mode 100644 index 25995cc..0000000 Binary files a/ta6ob/c/gc-011.o and /dev/null differ diff --git a/ta6ob/c/gc-ocd.c b/ta6ob/c/gc-ocd.c deleted file mode 100644 index 614d4fa..0000000 --- a/ta6ob/c/gc-ocd.c +++ /dev/null @@ -1,18 +0,0 @@ -/* gc-ocd.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define GCENTRY S_gc_ocd -#include "gc.c" diff --git a/ta6ob/c/gc-ocd.o b/ta6ob/c/gc-ocd.o deleted file mode 100644 index 7a55b73..0000000 Binary files a/ta6ob/c/gc-ocd.o and /dev/null differ diff --git a/ta6ob/c/gc-oce.c b/ta6ob/c/gc-oce.c deleted file mode 100644 index ab910e7..0000000 --- a/ta6ob/c/gc-oce.c +++ /dev/null @@ -1,19 +0,0 @@ -/* gc-oce.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define GCENTRY S_gc_oce -#define ENABLE_OBJECT_COUNTS -#include "gc.c" diff --git a/ta6ob/c/gc-oce.o b/ta6ob/c/gc-oce.o deleted file mode 100644 index e447b2f..0000000 Binary files a/ta6ob/c/gc-oce.o and /dev/null differ diff --git a/ta6ob/c/gc.c b/ta6ob/c/gc.c deleted file mode 100644 index 425d92f..0000000 --- a/ta6ob/c/gc.c +++ /dev/null @@ -1,2324 +0,0 @@ -/* gc.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" -#include "sort.h" -#ifndef WIN32 -#include -#endif /* WIN32 */ - -#define enable_object_counts do_not_use_enable_object_counts_in_this_file_use_ifdef_ENABLE_OBJECT_COUNTS_instead - -#if defined(MIN_TG) && defined(MAX_TG) -#if MIN_TG == MAX_TG -#define NO_DIRTY_NEWSPACE_POINTERS -#endif -#endif - -#if defined(MAX_CG) && defined(MIN_TG) && defined(MAX_TG) -#define FORMAL_CTGS -#define ONLY_FORMAL_CTGS void -#define ACTUAL_CTGS -#define ONLY_ACTUAL_CTGS -#define DECLARE_CTGS(max_cg, min_tg, max_tg) IGEN max_cg = MAX_CG, min_tg = MIN_TG, max_tg = MAX_TG -#define GCENTRY_PROTO(tcdecl, max_cgdecl, min_tgdecl, max_tgdecl) (tcdecl) -#else -#define FORMAL_CTGS , UINT _ctgs -#define ONLY_FORMAL_CTGS UINT _ctgs -#define ACTUAL_CTGS , _ctgs -#define ONLY_ACTUAL_CTGS _ctgs -#define DECLARE_CTGS(max_cg, min_tg, max_tg) UINT _ctgs = (((UINT)min_tg << 16) | ((UINT)max_cg << 8) | (UINT)max_tg) -#define MAX_CG ((INT)((_ctgs >> 8) & 0xff)) -#define MIN_TG ((INT)(_ctgs >> 16)) -#define MAX_TG ((INT)(_ctgs & 0xff)) -#define GCENTRY_PROTO(tcdecl, max_cgdecl, min_tgdecl, max_tgdecl) (tcdecl, max_cgdecl, min_tgdecl, max_tgdecl) -#endif - -/* locally defined functions */ -#ifndef NO_DIRTY_NEWSPACE_POINTERS -static void record_new_dirty_card(ptr *ppp, IGEN to_g); -#endif /* !NO_DIRTY_NEWSPACE_POINTERS */ -#ifndef NO_LOCKED_OLDSPACE_OBJECTS -static ptr append_bang(ptr ls1, ptr ls2); -static uptr count_unique(ptr ls); -static uptr list_length(ptr ls); -static ptr dosort(ptr ls, uptr n); -static ptr domerge(ptr l1, ptr l2); -static IBOOL search_locked(ptr p); -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ -static IGEN copy(ptr pp, seginfo *si, ptr *ppp FORMAL_CTGS); -static void sweep_locked_ptrs(ptr *p, iptr n FORMAL_CTGS); -static void sweep_locked(ptr tc, ptr p, IBOOL sweep_pure FORMAL_CTGS); -static ptr copy_stack(ptr old, iptr *length, iptr clength FORMAL_CTGS); -static void resweep_weak_pairs(ONLY_FORMAL_CTGS); -static void forward_or_bwp(ptr *pp, ptr p); -static void sweep_generation(ptr tc FORMAL_CTGS); -#ifndef NO_LOCKED_OLDSPACE_OBJECTS -static iptr size_object(ptr p); -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ -static iptr sweep_typed_object(ptr p, IGEN from_g FORMAL_CTGS); -static void sweep_symbol(ptr p, IGEN from_g FORMAL_CTGS); -static void sweep_port(ptr p, IGEN from_g FORMAL_CTGS); -static void sweep_thread(ptr p FORMAL_CTGS); -static void sweep_continuation(ptr p FORMAL_CTGS); -static void sweep_stack(uptr base, uptr size, uptr ret FORMAL_CTGS); -static void sweep_record(ptr x, IGEN from_g FORMAL_CTGS); -static IGEN sweep_dirty_record(ptr x, IGEN youngest FORMAL_CTGS); -static void sweep_code_object(ptr tc, ptr co FORMAL_CTGS); -static void record_dirty_segment(IGEN from_g, IGEN to_g, seginfo *si); -static void sweep_dirty(ONLY_FORMAL_CTGS); -static void resweep_dirty_weak_pairs(ONLY_FORMAL_CTGS); -static void add_ephemeron_to_pending(ptr p); -static void add_trigger_ephemerons_to_repending(ptr p); -static void check_trigger_ephemerons(seginfo *si); -static void check_ephemeron(ptr pe, IBOOL add_to_trigger FORMAL_CTGS); -static void check_pending_ephemerons(ONLY_FORMAL_CTGS); -static IGEN check_dirty_ephemeron(ptr pe, IGEN youngest FORMAL_CTGS); -static void clear_trigger_ephemerons(); - -#define OLDSPACE(x) (SPACE(x) & space_old) - -/* #define DEBUG */ - -/* initialized and used each gc cycle. any others should be defined in globals.h */ -static IBOOL change; -static ptr sweep_loc[static_generation+1][max_real_space+1]; -static ptr orig_next_loc[static_generation+1][max_real_space+1]; -#ifndef NO_LOCKED_OLDSPACE_OBJECTS -static ptr sorted_locked_objects; -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ -static ptr tlcs_to_rehash; - -#ifndef compute_target_generation -FORCEINLINE IGEN compute_target_generation(IGEN g FORMAL_CTGS) { - return g == MAX_TG ? g : g < MIN_TG ? MIN_TG : g + 1; -} -#endif /* !compute_target_generation */ - -/* rkd 2020/06/16: had the relocate routines more nicely coded with FORCEINLINE. - unfortunately, the llvm-compiled gc ran much (10-20%) slower on my mac. */ -#define relocate_return_addr(PCP) do {\ - ptr *_pcp = PCP;\ - seginfo *_si;\ - ptr _cp = *_pcp;\ - if ((_si = SegInfo(ptr_get_segment(_cp)))->space & space_old) {\ - iptr _co = ENTRYOFFSET(_cp) + ((uptr)_cp - (uptr)&ENTRYOFFSET(_cp));\ - ptr _pp = (ptr)((uptr)_cp - _co);\ - if (FWDMARKER(_pp) == forward_marker)\ - _pp = FWDADDRESS(_pp);\ - else\ - (void) copy(_pp, _si, &_pp ACTUAL_CTGS);\ - *_pcp = (ptr)((uptr)_pp + _co);\ - }\ -} while (0) - -/* use relocate_dirty for oldspace fields that might hold pointers to younger objects */ -#define relocate_dirty(PPP, YOUNGEST) do {\ - seginfo *_si; ptr *_ppp = PPP, _pp = *_ppp; IGEN _pg;\ - if (!IMMEDIATE(_pp) && (_si = MaybeSegInfo(ptr_get_segment(_pp))) != NULL) {\ - if (!(_si->space & space_old)) {\ - _pg = _si->generation;\ - } else if (FWDMARKER(_pp) == forward_marker && TYPEBITS(_pp) != type_flonum) {\ - *_ppp = FWDADDRESS(_pp);\ - _pg = compute_target_generation(_si->generation ACTUAL_CTGS);\ - } else {\ - _pg = copy(_pp, _si, _ppp ACTUAL_CTGS);\ - }\ - if (_pg < YOUNGEST) YOUNGEST = _pg;\ - }\ -} while (0) - -/* use relocate_pure for newspace fields that can't point to younger objects */ -#define relocate_pure_help(PPP, PP) do {\ - ptr *__ppp = PPP, __pp = PP; seginfo *__si;\ - if (!IMMEDIATE(__pp) && (__si = MaybeSegInfo(ptr_get_segment(__pp))) != NULL && (__si->space & space_old)) {\ - if (FWDMARKER(__pp) == forward_marker && TYPEBITS(__pp) != type_flonum) {\ - *__ppp = FWDADDRESS(__pp);\ - } else {\ - (void) copy(__pp, __si, __ppp ACTUAL_CTGS);\ - }\ - }\ -} while (0) - -#define relocate_pure(PPP) do {\ - ptr *_ppp = PPP; relocate_pure_help(_ppp, *_ppp);\ -} while (0) - -/* use relocate_impure for newspace fields that can point to younger objects */ -#ifdef NO_DIRTY_NEWSPACE_POINTERS -#define relocate_impure_help(PPP, PP, FROM_G) do {(void)FROM_G; relocate_pure_help(PPP, PP);} while (0) -#define relocate_impure(PPP, FROM_G) do {(void)FROM_G; relocate_pure(PPP);} while (0) -#else /* !NO_DIRTY_NEWSPACE_POINTERS */ -/* the initialization of __to_g to 0 below shouldn't be necessary, but gcc 7.5.0 complains without it */ -#define relocate_impure_help(PPP, PP, FROM_G) do {\ - ptr *__ppp = PPP, __pp = PP; IGEN __from_g = FROM_G;\ - seginfo *__si; IGEN __to_g = 0;\ - if (!IMMEDIATE(__pp) && (__si = MaybeSegInfo(ptr_get_segment(__pp))) != NULL && (__si->space & space_old)) {\ - if (FWDMARKER(__pp) == forward_marker && TYPEBITS(__pp) != type_flonum ?\ - (*__ppp = FWDADDRESS(__pp), (__from_g > 1 && (__to_g = compute_target_generation(__si->generation ACTUAL_CTGS)) < __from_g)) :\ - ((__to_g = copy(__pp, __si, __ppp ACTUAL_CTGS)) < __from_g)) {\ - record_new_dirty_card(__ppp, __to_g);\ - }\ - }\ -} while (0) - -#define relocate_impure(PPP, FROM_G) do {\ - ptr *_ppp = PPP; relocate_impure_help(_ppp, *_ppp, FROM_G);\ -} while (0) -#endif /* !NO_DIRTY_NEWSPACE_POINTERS */ - -#ifndef NO_DIRTY_NEWSPACE_POINTERS -typedef struct _dirtycardinfo { - uptr card; - IGEN youngest; - struct _dirtycardinfo *next; -} dirtycardinfo; - -static dirtycardinfo *new_dirty_cards; - -static void record_new_dirty_card(ptr *ppp, IGEN to_g) { - uptr card = (uptr)ppp >> card_offset_bits; - - dirtycardinfo *ndc = new_dirty_cards; - if (ndc != NULL && ndc->card == card) { - if (to_g < ndc->youngest) ndc->youngest = to_g; - } else { - dirtycardinfo *next = ndc; - find_room(space_new, 0, typemod, ptr_align(sizeof(dirtycardinfo)), ndc); - ndc->card = card; - ndc->youngest = to_g; - ndc->next = next; - new_dirty_cards = ndc; - } -} -#endif - -/* rkd 2015/06/05: tried to use sse instructions. abandoned the code - because the collector ran slower */ -#define copy_ptrs(ty, p1, p2, n) {\ - ptr *Q1, *Q2, *Q1END;\ - Q1 = (ptr *)UNTYPE((p1),ty);\ - Q2 = (ptr *)UNTYPE((p2),ty);\ - Q1END = (ptr *)((uptr)Q1 + n);\ - while (Q1 != Q1END) *Q1++ = *Q2++;} - -#ifdef NO_LOCKED_OLDSPACE_OBJECTS -#define locked(p) 0 -#else /* !NO_LOCKED_OLDSPACE_OBJECTS */ -/* MAXPTR is used to pad the sorted_locked_object vector. The pad value must be greater than any heap address */ -#define MAXPTR ((ptr)-1) - -static ptr append_bang(ptr ls1, ptr ls2) { /* assumes ls2 pairs are older than ls1 pairs, or that we don't care */ - if (ls2 == Snil) { - return ls1; - } else if (ls1 == Snil) { - return ls2; - } else { - ptr this = ls1, next; - while ((next = Scdr(this)) != Snil) this = next; - INITCDR(this) = ls2; - return ls1; - } -} - -static uptr count_unique(ptr ls) { /* assumes ls is sorted and nonempty */ - uptr i = 1; ptr x = Scar(ls), y; - while ((ls = Scdr(ls)) != Snil) { - if ((y = Scar(ls)) != x) { - i += 1; - x = y; - } - } - return i; -} - -#define CARLT(x, y) (Scar(x) < Scar(y)) -mkmergesort(dosort, domerge, ptr, Snil, CARLT, INITCDR) - -uptr list_length(ptr ls) { - uptr i = 0; - while (ls != Snil) { ls = Scdr(ls); i += 1; } - return i; -} - -static IBOOL search_locked(ptr p) { - uptr k; ptr v, *vp, x; - v = sorted_locked_objects; - k = Svector_length(v); - vp = &INITVECTIT(v, 0); - for (;;) { - k >>= 1; - if ((x = vp[k]) == p) return 1; - if (k == 0) return 0; - if (x < p) vp += k + 1; - } -} - -#define locked(p) (sorted_locked_objects != FIX(0) && search_locked(p)) -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ - -FORCEINLINE void check_trigger_ephemerons(seginfo *si) { - /* Registering ephemerons to recheck at the granularity of a segment - means that the worst-case complexity of GC is quadratic in the - number of objects that fit into a segment (but that only happens - if the objects are ephemeron keys that are reachable just through - a chain via the value field of the same ephemerons). */ - if (si->trigger_ephemerons) { - add_trigger_ephemerons_to_repending(si->trigger_ephemerons); - si->trigger_ephemerons = NULL; - } -} - -static IGEN copy(ptr pp, seginfo *si, ptr *ppp FORMAL_CTGS) { - ptr p, tf; ITYPE t; - IGEN newg = compute_target_generation(si->generation ACTUAL_CTGS); - -#ifndef NO_LOCKED_OLDSPACE_OBJECTS - if (locked(pp)) { *ppp = pp; return newg; } -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ - - change = 1; - - check_trigger_ephemerons(si); - - if ((t = TYPEBITS(pp)) == type_typed_object) { - tf = TYPEFIELD(pp); - if (TYPEP(tf, mask_record, type_record)) { - ptr rtd; iptr n; ISPC s; - - /* relocate to make sure we aren't using an oldspace descriptor - that has been overwritten by a forwarding marker, but don't loop - on tag-reflexive base descriptor */ - if ((rtd = tf) != pp) relocate_pure(&rtd); - - n = size_record_inst(UNFIX(RECORDDESCSIZE(rtd))); - -#ifdef ENABLE_OBJECT_COUNTS - { ptr counts; IGEN g; - counts = RECORDDESCCOUNTS(rtd); - if (counts == Sfalse) { - IGEN grtd = rtd == pp ? newg : GENERATION(rtd); - S_G.countof[grtd][countof_rtd_counts] += 1; - /* allocate counts struct in same generation as rtd. initialize timestamp & counts */ - find_room(space_data, grtd, type_typed_object, size_rtd_counts, counts); - RTDCOUNTSTYPE(counts) = type_rtd_counts; - RTDCOUNTSTIMESTAMP(counts) = S_G.gctimestamp[0]; - for (g = 0; g <= static_generation; g += 1) RTDCOUNTSIT(counts, g) = 0; - RECORDDESCCOUNTS(rtd) = counts; - S_G.rtds_with_counts[grtd] = S_cons_in((grtd == 0 ? space_new : space_impure), grtd, rtd, S_G.rtds_with_counts[grtd]); - S_G.countof[grtd][countof_pair] += 1; - } else { - relocate_pure(&counts); - RECORDDESCCOUNTS(rtd) = counts; - if (RTDCOUNTSTIMESTAMP(counts) != S_G.gctimestamp[0]) S_fixup_counts(counts); - } - RTDCOUNTSIT(counts, newg) += 1; - } -#endif /* ENABLE_OBJECT_COUNTS */ - - /* if the rtd is the only pointer and is immutable, put the record - into space data. if the record contains only pointers, put it - into space_pure or space_impure. otherwise put it into - space_pure_typed_object or space_impure_record. we could put all - records into space_{pure,impure}_record or even into - space_impure_record, but by picking the target space more - carefully we may reduce fragmentation and sweeping cost */ - s = RECORDDESCPM(rtd) == FIX(1) && RECORDDESCMPM(rtd) == FIX(0) ? - space_data : - RECORDDESCPM(rtd) == FIX(-1) ? - RECORDDESCMPM(rtd) == FIX(0) ? - space_pure : - space_impure : - RECORDDESCMPM(rtd) == FIX(0) ? - space_pure_typed_object : - space_impure_record; - - find_room(s, newg, type_typed_object, n, p); - copy_ptrs(type_typed_object, p, pp, n); - - /* overwrite type field with forwarded descriptor */ - RECORDINSTTYPE(p) = rtd == pp ? p : rtd; - - /* pad if necessary */ - if (s == space_pure || s == space_impure) { - iptr m = unaligned_size_record_inst(UNFIX(RECORDDESCSIZE(rtd))); - if (m != n) - *((ptr *)((uptr)UNTYPE(p,type_typed_object) + m)) = FIX(0); - } - } else if (TYPEP(tf, mask_vector, type_vector)) { - iptr len, n; - len = Svector_length(pp); - n = size_vector(len); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_vector] += 1; - S_G.bytesof[newg][countof_vector] += n; -#endif /* ENABLE_OBJECT_COUNTS */ - /* assumes vector lengths look like fixnums; if not, vectors will need their own space */ - if ((uptr)tf & vector_immutable_flag) { - find_room(space_pure, newg, type_typed_object, n, p); - } else { - find_room(space_impure, newg, type_typed_object, n, p); - } - copy_ptrs(type_typed_object, p, pp, n); - /* pad if necessary */ - if ((len & 1) == 0) INITVECTIT(p, len) = FIX(0); - } else if (TYPEP(tf, mask_string, type_string)) { - iptr n; - n = size_string(Sstring_length(pp)); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_string] += 1; - S_G.bytesof[newg][countof_string] += n; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, type_typed_object, n, p); - copy_ptrs(type_typed_object, p, pp, n); - } else if (TYPEP(tf, mask_bytevector, type_bytevector)) { - iptr n; - n = size_bytevector(Sbytevector_length(pp)); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_bytevector] += 1; - S_G.bytesof[newg][countof_bytevector] += n; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, type_typed_object, n, p); - copy_ptrs(type_typed_object, p, pp, n); - } else if ((iptr)tf == type_tlc) { - ptr keyval, next; - -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_tlc] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_impure, newg, type_typed_object, size_tlc, p); - TLCTYPE(p) = type_tlc; - INITTLCKEYVAL(p) = keyval = TLCKEYVAL(pp); - INITTLCHT(p) = TLCHT(pp); - INITTLCNEXT(p) = next = TLCNEXT(pp); - - /* if next isn't false and keyval is old, add tlc to a list of tlcs - * to process later. determining if keyval is old is a (conservative) - * approximation to determining if key is old. we can't easily - * determine if key is old, since keyval might or might not have been - * swept already. NB: assuming keyvals are always pairs. */ - if (next != Sfalse && SPACE(keyval) & space_old) - tlcs_to_rehash = S_cons_in(space_new, 0, p, tlcs_to_rehash); - } else if (TYPEP(tf, mask_box, type_box)) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_box] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - if ((uptr)tf == type_immutable_box) { - find_room(space_pure, newg, type_typed_object, size_box, p); - } else { - find_room(space_impure, newg, type_typed_object, size_box, p); - } - BOXTYPE(p) = (iptr)tf; - INITBOXREF(p) = Sunbox(pp); - } else if (TYPEP(tf, mask_fxvector, type_fxvector)) { - iptr n; - n = size_fxvector(Sfxvector_length(pp)); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_fxvector] += 1; - S_G.bytesof[newg][countof_fxvector] += n; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, type_typed_object, n, p); - copy_ptrs(type_typed_object, p, pp, n); - } else if ((iptr)tf == type_ratnum) { - /* not recursive: place in space_data and relocate fields immediately */ -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_ratnum] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, - type_typed_object, size_ratnum, p); - RATTYPE(p) = type_ratnum; - RATNUM(p) = RATNUM(pp); - RATDEN(p) = RATDEN(pp); - relocate_pure(&RATNUM(p)); - relocate_pure(&RATDEN(p)); - } else if ((iptr)tf == type_exactnum) { - /* not recursive: place in space_data and relocate fields immediately */ -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_exactnum] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, - type_typed_object, size_exactnum, p); - EXACTNUM_TYPE(p) = type_exactnum; - EXACTNUM_REAL_PART(p) = EXACTNUM_REAL_PART(pp); - EXACTNUM_IMAG_PART(p) = EXACTNUM_IMAG_PART(pp); - relocate_pure(&EXACTNUM_REAL_PART(p)); - relocate_pure(&EXACTNUM_IMAG_PART(p)); - } else if ((iptr)tf == type_inexactnum) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_inexactnum] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, - type_typed_object, size_inexactnum, p); - INEXACTNUM_TYPE(p) = type_inexactnum; - INEXACTNUM_REAL_PART(p) = INEXACTNUM_REAL_PART(pp); - INEXACTNUM_IMAG_PART(p) = INEXACTNUM_IMAG_PART(pp); - } else if (TYPEP(tf, mask_bignum, type_bignum)) { - iptr n; - n = size_bignum(BIGLEN(pp)); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_bignum] += 1; - S_G.bytesof[newg][countof_bignum] += n; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, type_typed_object, n, p); - copy_ptrs(type_typed_object, p, pp, n); - } else if (TYPEP(tf, mask_port, type_port)) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_port] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_port, newg, type_typed_object, size_port, p); - PORTTYPE(p) = PORTTYPE(pp); - PORTHANDLER(p) = PORTHANDLER(pp); - PORTNAME(p) = PORTNAME(pp); - PORTINFO(p) = PORTINFO(pp); - PORTOCNT(p) = PORTOCNT(pp); - PORTICNT(p) = PORTICNT(pp); - PORTOBUF(p) = PORTOBUF(pp); - PORTOLAST(p) = PORTOLAST(pp); - PORTIBUF(p) = PORTIBUF(pp); - PORTILAST(p) = PORTILAST(pp); - } else if (TYPEP(tf, mask_code, type_code)) { - iptr n; - n = size_code(CODELEN(pp)); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_code] += 1; - S_G.bytesof[newg][countof_code] += n; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_code, newg, type_typed_object, n, p); - copy_ptrs(type_typed_object, p, pp, n); - } else if ((iptr)tf == type_thread) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_thread] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_pure_typed_object, newg, - type_typed_object, size_thread, p); - TYPEFIELD(p) = (ptr)type_thread; - THREADTC(p) = THREADTC(pp); /* static */ - } else if ((iptr)tf == type_rtd_counts) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_rtd_counts] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, type_typed_object, size_rtd_counts, p); - copy_ptrs(type_typed_object, p, pp, size_rtd_counts); - } else { - S_error_abort("copy(gc): illegal type"); - return newg /* not reached */; - } - } else if (t == type_pair) { - if (si->space == (space_ephemeron | space_old)) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_ephemeron] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_ephemeron, newg, type_pair, size_ephemeron, p); - INITCAR(p) = Scar(pp); - INITCDR(p) = Scdr(pp); - } else { - ptr qq = Scdr(pp); ptr q; - if (qq != pp && TYPEBITS(qq) == type_pair && ptr_get_segment(qq) == ptr_get_segment(pp) && FWDMARKER(qq) != forward_marker && !locked(qq)) { - if (si->space == (space_weakpair | space_old)) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_weakpair] += 2; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_weakpair, newg, type_pair, 2 * size_pair, p); - } else { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_pair] += 2; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_impure, newg, type_pair, 2 * size_pair, p); - } - q = (ptr)((uptr)p + size_pair); - INITCAR(p) = Scar(pp); - INITCDR(p) = q; - INITCAR(q) = Scar(qq); - INITCDR(q) = Scdr(qq); - FWDMARKER(qq) = forward_marker; - FWDADDRESS(qq) = q; - } else { - if (si->space == (space_weakpair | space_old)) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_weakpair] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_weakpair, newg, type_pair, size_pair, p); - } else { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_pair] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_impure, newg, type_pair, size_pair, p); - } - INITCAR(p) = Scar(pp); - INITCDR(p) = qq; - } - } - } else if (t == type_closure) { - ptr code; - - /* relocate before accessing code type field, which otherwise might - be a forwarding marker */ - code = CLOSCODE(pp); - relocate_pure(&code); - if (CODETYPE(code) & (code_flag_continuation << code_flags_offset)) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_continuation] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_continuation, newg, - type_closure, size_continuation, p); - SETCLOSCODE(p,code); - /* don't promote one-shots */ - CONTLENGTH(p) = CONTLENGTH(pp); - CONTCLENGTH(p) = CONTCLENGTH(pp); - CONTWINDERS(p) = CONTWINDERS(pp); - if (CONTLENGTH(p) != scaled_shot_1_shot_flag) { - CONTLINK(p) = CONTLINK(pp); - CONTRET(p) = CONTRET(pp); - CONTSTACK(p) = CONTSTACK(pp); - } - } else { - iptr len, n; - len = CLOSLEN(pp); - n = size_closure(len); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_closure] += 1; - S_G.bytesof[newg][countof_closure] += n; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_pure, newg, type_closure, n, p); - copy_ptrs(type_closure, p, pp, n); - SETCLOSCODE(p,code); - /* pad if necessary */ - if ((len & 1) == 0) CLOSIT(p, len) = FIX(0); - } - } else if (t == type_symbol) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_symbol] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_symbol, newg, type_symbol, size_symbol, p); - INITSYMVAL(p) = SYMVAL(pp); - INITSYMPVAL(p) = SYMPVAL(pp); - INITSYMPLIST(p) = SYMPLIST(pp); - INITSYMSPLIST(p) = SYMSPLIST(pp); - INITSYMNAME(p) = SYMNAME(pp); - INITSYMHASH(p) = SYMHASH(pp); - } else if (t == type_flonum) { -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_flonum] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, type_flonum, size_flonum, p); - FLODAT(p) = FLODAT(pp); - /* no room for forwarding address, so let 'em be duplicated */ - *ppp = p; - return newg; - } else { - S_error_abort("copy(gc): illegal type"); - return newg /* not reached */; - } - - FWDMARKER(pp) = forward_marker; - FWDADDRESS(pp) = p; - - *ppp = p; - return newg; -} - -static void sweep_locked_ptrs(ptr *pp, iptr n FORMAL_CTGS) { - ptr *end = pp + n; - - while (pp != end) { - relocate_pure(pp); - pp += 1; - } -} - -static void sweep_locked(ptr tc, ptr p, IBOOL sweep_pure FORMAL_CTGS) { - ptr tf; ITYPE t; - - if ((t = TYPEBITS(p)) == type_pair) { - ISPC s = SPACE(p) & ~(space_locked | space_old); - if (s == space_ephemeron) - add_ephemeron_to_pending(p); - else { - if (s != space_weakpair) { - relocate_pure(&INITCAR(p)); - } - relocate_pure(&INITCDR(p)); - } - } else if (t == type_closure) { - if (sweep_pure) { - ptr code; - - code = CLOSCODE(p); - relocate_pure(&code); - SETCLOSCODE(p,code); - if (CODETYPE(code) & (code_flag_continuation << code_flags_offset)) - sweep_continuation(p ACTUAL_CTGS); - else - sweep_locked_ptrs(&CLOSIT(p, 0), CLOSLEN(p) ACTUAL_CTGS); - } - } else if (t == type_symbol) { - sweep_symbol(p, 0 ACTUAL_CTGS); - } else if (t == type_flonum) { - /* nothing to sweep */; - /* typed objects */ - } else if (tf = TYPEFIELD(p), TYPEP(tf, mask_vector, type_vector)) { - sweep_locked_ptrs(&INITVECTIT(p, 0), Svector_length(p) ACTUAL_CTGS); - } else if (TYPEP(tf, mask_string, type_string) || TYPEP(tf, mask_bytevector, type_bytevector) || TYPEP(tf, mask_fxvector, type_fxvector)) { - /* nothing to sweep */; - } else if (TYPEP(tf, mask_record, type_record)) { - relocate_pure(&RECORDINSTTYPE(p)); - if (sweep_pure || RECORDDESCMPM(RECORDINSTTYPE(p)) != FIX(0)) { - sweep_record(p, 0 ACTUAL_CTGS); - } - } else if (TYPEP(tf, mask_box, type_box)) { - relocate_pure(&INITBOXREF(p)); - } else if ((iptr)tf == type_ratnum) { - if (sweep_pure) { - relocate_pure(&RATNUM(p)); - relocate_pure(&RATDEN(p)); - } - } else if ((iptr)tf == type_exactnum) { - if (sweep_pure) { - relocate_pure(&EXACTNUM_REAL_PART(p)); - relocate_pure(&EXACTNUM_IMAG_PART(p)); - } - } else if ((iptr)tf == type_inexactnum) { - /* nothing to sweep */; - } else if (TYPEP(tf, mask_bignum, type_bignum)) { - /* nothing to sweep */; - } else if (TYPEP(tf, mask_port, type_port)) { - sweep_port(p, 0 ACTUAL_CTGS); - } else if (TYPEP(tf, mask_code, type_code)) { - if (sweep_pure) { - sweep_code_object(tc, p ACTUAL_CTGS); - } - } else if ((iptr)tf == type_thread) { - sweep_thread(p ACTUAL_CTGS); - } else if ((iptr)tf == type_rtd_counts) { - /* nothing to sweep */; - } else { - S_error_abort("sweep_locked(gc): illegal type"); - } -} - -static ptr copy_stack(ptr old, iptr *length, iptr clength FORMAL_CTGS) { - iptr n, m; ptr new; IGEN newg; - - /* Don't copy non-oldspace stacks, since we may be sweeping a locked - continuation. Doing so would be a waste of work anyway. */ - if (!OLDSPACE(old)) return old; - - newg = compute_target_generation(GENERATION(old) ACTUAL_CTGS); - - /* reduce headroom created for excessively large frames (typically resulting from apply with long lists) */ - if ((n = *length) != clength && n > default_stack_size && n > (m = clength + one_shot_headroom)) { - *length = n = m; - } - - n = ptr_align(n); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_stack] += 1; - S_G.bytesof[newg][countof_stack] += n; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, typemod, n, new); - n = ptr_align(clength); - /* warning: stack may have been left non-double-aligned by split_and_resize */ - copy_ptrs(typemod, new, old, n); - - /* also returning possibly updated value in *length */ - return new; -} - -#define NONSTATICINHEAP(si, x) (!IMMEDIATE(x) && (si = MaybeSegInfo(ptr_get_segment(x))) != NULL && si->generation != static_generation) -#define ALWAYSTRUE(si, x) (si = SegInfo(ptr_get_segment(x)), 1) -#define partition_guardians(LS, FILTER) { \ - ptr ls; seginfo *si;\ - for (ls = LS; ls != Snil; ls = next) { \ - obj = GUARDIANOBJ(ls); \ - next = GUARDIANNEXT(ls); \ - \ - if (FILTER(si, obj)) { \ - if (!(si->space & space_old) || locked(obj) || ((FWDMARKER(obj) == forward_marker && TYPEBITS(obj) != type_flonum) && (INITGUARDIANOBJ(ls) = FWDADDRESS(obj), 1))) { \ - INITGUARDIANNEXT(ls) = pend_hold_ls; \ - pend_hold_ls = ls; \ - } else { \ - tconc = GUARDIANTCONC(ls); \ - if (!OLDSPACE(tconc) || locked(tconc) || ((FWDMARKER(tconc) == forward_marker) && (INITGUARDIANTCONC(ls) = FWDADDRESS(tconc), 1))) { \ - INITGUARDIANNEXT(ls) = final_ls; \ - final_ls = ls; \ - } else { \ - INITGUARDIANNEXT(ls) = pend_final_ls; \ - pend_final_ls = ls; \ - } \ - } \ - } \ - } \ -} - -/* tc: thread context - * max_cg: maximum copied generation, i.e., maximum generation subject to collection. max_cg >= 0 && max_cg <= 255. - * min_tg: minimum target generation. max_tg == 0 ? min_tg == 0 : min_tg > 0 && min_tg <= max_tg; - * max_tg: maximum target generation. max_tg == max_cg || max_tg == max_cg + 1. - * Objects in generation g are collected into generation MIN(max_tg, MAX(min_tg, g+1)). - */ -void GCENTRY GCENTRY_PROTO(ptr tc, IGEN max_cg, IGEN min_tg, IGEN max_tg) { - IGEN g; ISPC s; - seginfo *oldspacesegments, *si, *nextsi; - ptr ls; - bucket_pointer_list *buckets_to_rebuild; -#ifndef NO_LOCKED_OLDSPACE_OBJECTS - ptr locked_oldspace_objects; -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ - DECLARE_CTGS(max_cg, min_tg, max_tg); - - /* flush instruction cache: effectively clear_code_mod but safer */ - for (ls = S_threads; ls != Snil; ls = Scdr(ls)) { - ptr tc = (ptr)THREADTC(Scar(ls)); - S_flush_instruction_cache(tc); - } - - tlcs_to_rehash = Snil; -#ifndef NO_DIRTY_NEWSPACE_POINTERS - new_dirty_cards = NULL; -#endif /* !NO_DIRTY_NEWSPACE_POINTERS */ - - for (ls = S_threads; ls != Snil; ls = Scdr(ls)) { - ptr tc = (ptr)THREADTC(Scar(ls)); - S_scan_dirty((ptr **)EAP(tc), (ptr **)REAL_EAP(tc)); - EAP(tc) = REAL_EAP(tc) = AP(tc) = (ptr)0; - } - - /* perform after ScanDirty */ - if (S_checkheap) S_check_heap(0); - -#ifdef DEBUG -(void)printf("max_cg = %x; go? ", max_cg); (void)fflush(stdout); (void)getc(stdin); -#endif - - /* set up generations to be copied */ - for (g = 0; g <= max_cg; g++) { - S_G.bytes_of_generation[g] = 0; - for (s = 0; s <= max_real_space; s++) { - S_G.base_loc[g][s] = FIX(0); - S_G.first_loc[g][s] = FIX(0); - S_G.next_loc[g][s] = FIX(0); - S_G.bytes_left[g][s] = 0; - S_G.bytes_of_space[g][s] = 0; - } - } - - /* set up target generation sweep_loc and orig_next_loc pointers */ - for (g = min_tg; g <= max_tg; g += 1) { - for (s = 0; s <= max_real_space; s++) { - /* for all but max_tg (and max_tg as well, if max_tg == max_cg), this - will set orig_net_loc and sweep_loc to 0 */ - orig_next_loc[g][s] = sweep_loc[g][s] = S_G.next_loc[g][s]; - } - } - - /* mark segments from which objects are to be copied */ - oldspacesegments = (seginfo *)NULL; - for (g = 0; g <= max_cg; g += 1) { - for (s = 0; s <= max_real_space; s += 1) { - for (si = S_G.occupied_segments[g][s]; si != NULL; si = nextsi) { - nextsi = si->next; - si->next = oldspacesegments; - oldspacesegments = si; - si->space = s | space_old; /* NB: implicitly clearing space_locked */ - } - S_G.occupied_segments[g][s] = NULL; - } - } - -#ifdef ENABLE_OBJECT_COUNTS - /* clear object counts & bytes for copied generations; bump timestamp */ - {INT i; - for (g = 0; g <= max_cg; g += 1) { - for (i = 0; i < countof_types; i += 1) { - S_G.countof[g][i] = 0; - S_G.bytesof[g][i] = 0; - } - if (g == 0) { - S_G.gctimestamp[g] += 1; - } else { - S_G.gctimestamp[g] = S_G.gctimestamp[0]; - } - } - } -#endif /* ENABLE_OBJECT_COUNTS */ - - /* pre-collection handling of locked objects. */ - -#ifndef NO_LOCKED_OLDSPACE_OBJECTS - /* create a single sorted_locked_object vector for all copied generations - * to accelerate the search for locked objects in copy(). copy wants - * a vector of some size n=2^k-1 so it doesn't have to check bounds */ - ls = Snil; - /* note: append_bang and dosort reuse pairs, which can result in older - * objects pointing to newer ones...but we don't care since they are all - * oldspace and going away after this collection. */ - for (g = 0; g <= max_cg; g += 1) { - ls = append_bang(S_G.locked_objects[g], ls); - S_G.locked_objects[g] = Snil; - S_G.unlocked_objects[g] = Snil; - } - if (ls == Snil) { - sorted_locked_objects = FIX(0); - locked_oldspace_objects = Snil; - } else { - ptr v, x, y; uptr i, n; - - /* dosort is destructive, so have to store the result back */ - locked_oldspace_objects = ls = dosort(ls, list_length(ls)); - - /* create vector of smallest size n=2^k-1 that will fit all of - the list's unique elements */ - i = count_unique(ls); - for (n = 1; n < i; n = (n << 1) | 1); - sorted_locked_objects = v = S_vector_in(space_new, 0, n); - - /* copy list elements in, skipping duplicates */ - INITVECTIT(v,0) = x = Scar(ls); - i = 1; - while ((ls = Scdr(ls)) != Snil) { - if ((y = Scar(ls)) != x) { - INITVECTIT(v, i) = x = y; - i += 1; - } - } - - /* fill remaining slots with largest ptr value */ - while (i < n) { INITVECTIT(v, i) = MAXPTR; i += 1; } - } -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ - - /* sweep older locked and unlocked objects */ - for (g = max_cg + 1; g <= static_generation; INCRGEN(g)) { - for (ls = S_G.locked_objects[g]; ls != Snil; ls = Scdr(ls)) - sweep_locked(tc, Scar(ls), 0 ACTUAL_CTGS); - for (ls = S_G.unlocked_objects[g]; ls != Snil; ls = Scdr(ls)) - sweep_locked(tc, Scar(ls), 0 ACTUAL_CTGS); - } - -#ifndef NO_LOCKED_OLDSPACE_OBJECTS - /* sweep younger locked objects, working from sorted vector to avoid redundant sweeping of duplicates */ - if (sorted_locked_objects != FIX(0)) { - uptr i; ptr x, v, *vp; - v = sorted_locked_objects; - i = Svector_length(v); - x = *(vp = &INITVECTIT(v, 0)); - do sweep_locked(tc, x, 1 ACTUAL_CTGS); while (--i != 0 && (x = *++vp) != MAXPTR); - } -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ - - /* sweep non-oldspace threads, since any thread may have an active stack */ - for (ls = S_threads; ls != Snil; ls = Scdr(ls)) { - ptr thread; - - /* someone may have their paws on the list */ - if (FWDMARKER(ls) == forward_marker) ls = FWDADDRESS(ls); - - thread = Scar(ls); - if (!OLDSPACE(thread)) sweep_thread(thread ACTUAL_CTGS); - } - relocate_pure(&S_threads); - - /* relocate nonempty oldspace symbols and set up list of buckets to rebuild later */ - buckets_to_rebuild = NULL; - for (g = 0; g <= max_cg; g += 1) { - bucket_list *bl, *blnext; bucket *b; bucket_pointer_list *bpl; bucket **oblist_cell; ptr sym; iptr idx; - for (bl = S_G.buckets_of_generation[g]; bl != NULL; bl = blnext) { - blnext = bl->cdr; - b = bl->car; - /* mark this bucket old for the rebuilding loop */ - b->next = (bucket *)((uptr)b->next | 1); - sym = b->sym; - idx = UNFIX(SYMHASH(sym)) % S_G.oblist_length; - oblist_cell = &S_G.oblist[idx]; - if (!((uptr)*oblist_cell & 1)) { - /* mark this bucket in the set */ - *oblist_cell = (bucket *)((uptr)*oblist_cell | 1); - /* repurpose the bucket list element for the list of buckets to rebuild later */ - /* idiot_checks verifies these have the same size */ - bpl = (bucket_pointer_list *)bl; - bpl->car = oblist_cell; - bpl->cdr = buckets_to_rebuild; - buckets_to_rebuild = bpl; - } - if (FWDMARKER(sym) != forward_marker && - /* coordinate with alloc.c */ - (SYMVAL(sym) != sunbound || SYMPLIST(sym) != Snil || SYMSPLIST(sym) != Snil)) { - ptr ignore; - copy(sym, SegInfo(ptr_get_segment(sym)), &ignore ACTUAL_CTGS); - } - } - S_G.buckets_of_generation[g] = NULL; - } - - /* relocate the protected C pointers */ - {uptr i; - for (i = 0; i < S_G.protect_next; i++) - relocate_pure(S_G.protected[i]); - } - - /* sweep areas marked dirty by assignments into older generations */ - sweep_dirty(ONLY_ACTUAL_CTGS); - - sweep_generation(tc ACTUAL_CTGS); - - /* handle guardians */ - { ptr pend_hold_ls, final_ls, pend_final_ls; - ptr obj, rep, tconc, next; - - /* move each entry in guardian lists into one of: - * pend_hold_ls if obj accessible - * final_ls if obj not accessible and tconc accessible - * pend_final_ls if obj not accessible and tconc not accessible */ - pend_hold_ls = final_ls = pend_final_ls = Snil; - - for (ls = S_threads; ls != Snil; ls = Scdr(ls)) { - ptr tc = (ptr)THREADTC(Scar(ls)); - partition_guardians(GUARDIANENTRIES(tc), NONSTATICINHEAP); - GUARDIANENTRIES(tc) = Snil; - } - - for (g = 0; g <= max_cg; g += 1) { - partition_guardians(S_G.guardians[g], ALWAYSTRUE); - S_G.guardians[g] = Snil; - } - - /* invariants after partition_guardians: - * for entry in pend_hold_ls, obj is !OLDSPACE or locked - * for entry in final_ls, obj is OLDSPACE and !locked - * for entry in final_ls, tconc is !OLDSPACE or locked - * for entry in pend_final_ls, obj and tconc are OLDSPACE and !locked - */ - - while (1) { - IBOOL relocate_rep = final_ls != Snil; - - /* relocate & add the final objects to their tconcs */ - for (ls = final_ls; ls != Snil; ls = GUARDIANNEXT(ls)) { - ptr old_end, new_end; - - rep = GUARDIANREP(ls); - /* ftype_guardian_rep is a marker for reference-counted ftype pointer */ - if (rep == ftype_guardian_rep) { - INT b; uptr *addr; - rep = GUARDIANOBJ(ls); - if (FWDMARKER(rep) == forward_marker) rep = FWDADDRESS(rep); - /* Caution: Building in assumption about shape of an ftype pointer */ - addr = RECORDINSTIT(rep, 0); - LOCKED_DECR(addr, b); - if (!b) continue; - } - - relocate_pure(&rep); - - /* if tconc was old it's been forwarded */ - tconc = GUARDIANTCONC(ls); - - old_end = Scdr(tconc); - new_end = S_cons_in(space_impure, 0, FIX(0), FIX(0)); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[0][countof_pair] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - - SETCAR(old_end,rep); - SETCDR(old_end,new_end); - SETCDR(tconc,new_end); - } - - /* copy each entry in pend_hold_ls into its target generation if tconc accessible */ - ls = pend_hold_ls; pend_hold_ls = Snil; - for ( ; ls != Snil; ls = next) { - ptr p; - - next = GUARDIANNEXT(ls); - - /* discard static pend_hold_ls entries */ - g = compute_target_generation(GENERATION(ls) ACTUAL_CTGS); - if (g == static_generation) continue; - - tconc = GUARDIANTCONC(ls); - - if (OLDSPACE(tconc) && !locked(tconc)) { - if (FWDMARKER(tconc) == forward_marker) - tconc = FWDADDRESS(tconc); - else { - INITGUARDIANNEXT(ls) = pend_hold_ls; - pend_hold_ls = ls; - continue; - } - } - - rep = GUARDIANREP(ls); - relocate_pure(&rep); - relocate_rep = 1; - -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[g][countof_guardian] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_pure, g, typemod, size_guardian_entry, p); - INITGUARDIANOBJ(p) = GUARDIANOBJ(ls); - INITGUARDIANREP(p) = rep; - INITGUARDIANTCONC(p) = tconc; - INITGUARDIANNEXT(p) = S_G.guardians[g]; - S_G.guardians[g] = p; - } - - if (!relocate_rep) break; - - sweep_generation(tc ACTUAL_CTGS); - - /* move each entry in pend_final_ls into one of: - * final_ls if tconc forwarded - * pend_final_ls if tconc not forwarded */ - ls = pend_final_ls; final_ls = pend_final_ls = Snil; - for ( ; ls != Snil; ls = next) { - tconc = GUARDIANTCONC(ls); next = GUARDIANNEXT(ls); - - if (FWDMARKER(tconc) == forward_marker) { - INITGUARDIANTCONC(ls) = FWDADDRESS(tconc); - INITGUARDIANNEXT(ls) = final_ls; - final_ls = ls; - } else { - INITGUARDIANNEXT(ls) = pend_final_ls; - pend_final_ls = ls; - } - } - } - } - - /* handle weak pairs */ - resweep_dirty_weak_pairs(ONLY_ACTUAL_CTGS); - resweep_weak_pairs(ONLY_ACTUAL_CTGS); - - /* still-pending ephemerons all go to bwp */ - clear_trigger_ephemerons(); - - /* forward car fields of locked and unlocked older weak pairs */ - for (g = max_cg + 1; g <= static_generation; INCRGEN(g)) { - for (ls = S_G.locked_objects[g]; ls != Snil; ls = Scdr(ls)) { - ptr x = Scar(ls); - if (Spairp(x) && (SPACE(x) & ~(space_old|space_locked)) == space_weakpair) - forward_or_bwp(&INITCAR(x), Scar(x)); - } - for (ls = S_G.unlocked_objects[g]; ls != Snil; ls = Scdr(ls)) { - ptr x = Scar(ls); - if (Spairp(x) && (SPACE(x) & ~(space_old|space_locked)) == space_weakpair) - forward_or_bwp(&INITCAR(x), Scar(x)); - } - } - -#ifndef NO_LOCKED_OLDSPACE_OBJECTS - /* forward car fields of locked oldspace weak pairs */ - if (sorted_locked_objects != FIX(0)) { - uptr i; ptr x, v, *vp; - v = sorted_locked_objects; - i = Svector_length(v); - x = *(vp = &INITVECTIT(v, 0)); - do { - if (Spairp(x) && (SPACE(x) & ~(space_old|space_locked)) == space_weakpair) { - forward_or_bwp(&INITCAR(x), Scar(x)); - } - } while (--i != 0 && (x = *++vp) != MAXPTR); - } -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ - - /* post-gc oblist handling. rebuild old buckets in the target generation, pruning unforwarded symbols */ - { bucket_list *bl; bucket *b, *bnext; bucket_pointer_list *bpl; bucket **pb; ptr sym; - for (bpl = buckets_to_rebuild; bpl != NULL; bpl = bpl->cdr) { - pb = bpl->car; - for (b = (bucket *)((uptr)*pb - 1); b != NULL && ((uptr)(b->next) & 1); b = bnext) { - bnext = (bucket *)((uptr)(b->next) - 1); - sym = b->sym; - if (locked(sym) || (FWDMARKER(sym) == forward_marker && ((sym = FWDADDRESS(sym)) || 1))) { - IGEN g = GENERATION(sym); - find_room(space_data, g, typemod, sizeof(bucket), b); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[g][countof_oblist] += 1; - S_G.bytesof[g][countof_oblist] += sizeof(bucket); -#endif /* ENABLE_OBJECT_COUNTS */ - b->sym = sym; - *pb = b; - pb = &b->next; - if (g != static_generation) { - find_room(space_data, g, typemod, sizeof(bucket_list), bl); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[g][countof_oblist] += 1; - S_G.bytesof[g][countof_oblist] += sizeof(bucket_list); -#endif /* ENABLE_OBJECT_COUNTS */ - bl->car = b; - bl->cdr = S_G.buckets_of_generation[g]; - S_G.buckets_of_generation[g] = bl; - } - } else { - S_G.oblist_count -= 1; - } - } - *pb = b; - } - } - - /* rebuild rtds_with_counts lists, dropping otherwise inaccessible rtds */ - { IGEN g, newg; ptr ls, lsls, p; - for (g = 0, lsls = Snil; g <= max_cg; g += 1) { - lsls = S_cons_in(space_new, 0, S_G.rtds_with_counts[g], lsls); - S_G.rtds_with_counts[g] = Snil; - } - for (; lsls != Snil; lsls = Scdr(lsls)) { - for (ls = Scar(lsls); ls != Snil; ls = Scdr(ls)) { - p = Scar(ls); - if (!OLDSPACE(p) || locked(p) || (FWDMARKER(p) == forward_marker && (p = FWDADDRESS(p), 1))) { - newg = GENERATION(p); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_pair] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - S_G.rtds_with_counts[newg] = S_cons_in(space_impure, newg, p, S_G.rtds_with_counts[newg]); - } - } - } - } - -#ifndef WIN32 - /* rebuild child_process list, reaping any that have died and refusing - to promote into the static generation. */ - { IGEN g, newg; ptr ls, newls; - for (g = max_cg; g >= 0; g -= 1) { - newg = compute_target_generation(g ACTUAL_CTGS); - if (newg == static_generation) newg = S_G.max_nonstatic_generation; - newls = newg == g ? Snil : S_child_processes[newg]; - for (ls = S_child_processes[g], S_child_processes[g] = Snil; ls != Snil; ls = Scdr(ls)) { - INT pid = UNFIX(Scar(ls)), status, retpid; - retpid = waitpid(pid, &status, WNOHANG); - if (retpid == 0 || (retpid == pid && !(WIFEXITED(status) || WIFSIGNALED(status)))) { - newls = S_cons_in(space_impure, newg, FIX(pid), newls); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_pair] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - } - } - S_child_processes[newg] = newls; - } - } -#endif /* WIN32 */ - -#ifndef NO_LOCKED_OLDSPACE_OBJECTS - /* post-collection handling of locked objects. This must come after - any use of relocate or any other use of sorted_locked_objects */ - if (sorted_locked_objects != FIX(0)) { - ptr ls, x, v, *vp; iptr i; uptr last_seg = 0, addr, seg, n; IGEN newg = 0; - - v = sorted_locked_objects; - - /* work from sorted vector to avoid redundant processing of duplicates */ - i = Svector_length(v); - x = *(vp = &INITVECTIT(v, 0)); - do { - /* promote the segment(s) containing x to the target generation. - reset the space_old bit to prevent the segments from being - reclaimed; set the locked bit to prevent sweeping by - sweep_dirty (since the segments may contain a mix of objects, - many of which have been discarded). */ - addr = (uptr)UNTYPE_ANY(x); - if ((seg = addr_get_segment(addr)) == last_seg) { - /* the generation has already been updated on this segment, and newg is still valid. - this isn't just an optimization. if we recompute newg based on the already updated - generation, we could get the wrong result. good thing the vector is sorted. */ - seg += 1; - } else { - newg = compute_target_generation(GENERATION(x) ACTUAL_CTGS); - } - - n = size_object(x); - -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_locked] += 1; - S_G.bytesof[newg][countof_locked] += n; -#endif /* ENABLE_OBJECT_COUNTS */ - - addr += n - 1; - last_seg = addr_get_segment(addr); - while (seg <= last_seg) { - seginfo *si = SegInfo(seg); - si->generation = newg; - si->space = (si->space & ~space_old) | space_locked; - seg += 1; - } - } while (--i != 0 && (x = *++vp) != MAXPTR); - - /* add every object, including duplicates, to target-generation list(s). we do so - even when newg == static_generation so we can keep track of static objects that need to - be swept at the start of collection. (we could weed out pure static objects.) */ - for (newg = min_tg; newg < max_tg; newg += 1) S_G.locked_objects[newg] = Snil; - if (max_tg == max_cg) S_G.locked_objects[max_cg] = Snil; - for (ls = locked_oldspace_objects; ls != Snil; ls = Scdr(ls)) { - x = Scar(ls); - newg = GENERATION(x); - S_G.locked_objects[newg] = S_cons_in(space_impure, newg, x, S_G.locked_objects[newg]); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_pair] += 1; -#endif /* ENABLE_OBJECT_COUNTS */ - } - } -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ - - /* move old space segments to empty space */ - for (si = oldspacesegments; si != NULL; si = nextsi) { - nextsi = si->next; - s = si->space; - if (s & space_locked) { - /* note: the oldspace bit is cleared above for locked objects */ - s &= ~space_locked; - g = si->generation; - if (g == static_generation) S_G.number_of_nonstatic_segments -= 1; - si->next = S_G.occupied_segments[g][s]; - S_G.occupied_segments[g][s] = si; - } else { - chunkinfo *chunk = si->chunk; - if (si->generation != static_generation) S_G.number_of_nonstatic_segments -= 1; - S_G.number_of_empty_segments += 1; - si->space = space_empty; - si->next = chunk->unused_segs; - chunk->unused_segs = si; -#ifdef WIPECLEAN - memset((void *)build_ptr(si->number,0), 0xc7, bytes_per_segment); -#endif - if ((chunk->nused_segs -= 1) == 0) { - if (chunk->bytes != (minimum_segment_request + 1) * bytes_per_segment) { - /* release oversize chunks back to the O/S immediately to avoid allocating - * small stuff into them and thereby invite fragmentation */ - S_free_chunk(chunk); - } else { - S_move_to_chunk_list(chunk, &S_chunks[PARTIAL_CHUNK_POOLS]); - } - } else { - S_move_to_chunk_list(chunk, &S_chunks[PARTIAL_CHUNK_POOLS-1]); - } - } - } - - S_G.g0_bytes_after_last_gc = S_G.bytes_of_generation[0]; - - if (max_cg >= S_G.min_free_gen) S_free_chunks(); - - S_flush_instruction_cache(tc); - -#ifndef NO_DIRTY_NEWSPACE_POINTERS - /* mark dirty those newspace cards to which we've added wrong-way pointers */ - { dirtycardinfo *ndc; - for (ndc = new_dirty_cards; ndc != NULL; ndc = ndc->next) - S_mark_card_dirty(ndc->card, ndc->youngest); - } -#endif /* !NO_DIRTY_NEWSPACE_POINTERS */ - - if (S_checkheap) S_check_heap(1); - - /* post-collection rehashing of tlcs. - must come after any use of relocate. - logically comes after gc is entirely complete */ - while (tlcs_to_rehash != Snil) { - ptr b, next; uptr old_idx, new_idx; - ptr tlc = Scar(tlcs_to_rehash); - ptr ht = TLCHT(tlc); - ptr vec = PTRFIELD(ht,eq_hashtable_vec_disp); - uptr veclen = Svector_length(vec); - ptr key = Scar(TLCKEYVAL(tlc)); - - /* scan to end of bucket to find the index */ - for (b = TLCNEXT(tlc); !Sfixnump(b); b = TLCNEXT(b)); - old_idx = UNFIX(b); - - if (key == Sbwp_object && PTRFIELD(ht,eq_hashtable_subtype_disp) != FIX(eq_hashtable_subtype_normal)) { - /* remove tlc */ - b = Svector_ref(vec, old_idx); - if (b == tlc) { - SETVECTIT(vec, old_idx, TLCNEXT(b)); - } else { - for (;;) { next = TLCNEXT(b); if (next == tlc) break; b = next; } - SETTLCNEXT(b,TLCNEXT(next)); - } - INITTLCNEXT(tlc) = Sfalse; - INITPTRFIELD(ht,eq_hashtable_size_disp) = FIX(UNFIX(PTRFIELD(ht,eq_hashtable_size_disp)) - 1); - } else if ((new_idx = ((uptr)key >> primary_type_bits) & (veclen - 1)) != old_idx) { - /* remove tlc from old bucket */ - b = Svector_ref(vec, old_idx); - if (b == tlc) { - SETVECTIT(vec, old_idx, TLCNEXT(b)); - } else { - for (;;) { next = TLCNEXT(b); if (next == tlc) break; b = next; } - SETTLCNEXT(b,TLCNEXT(next)); - } - /* and add to new bucket */ - SETTLCNEXT(tlc, Svector_ref(vec, new_idx)); - SETVECTIT(vec, new_idx, tlc); - } - tlcs_to_rehash = Scdr(tlcs_to_rehash); - } - - S_resize_oblist(); - - /* tell profile_release_counters to look for bwp'd counters at least through max_tg */ - if (S_G.prcgeneration < max_tg) S_G.prcgeneration = max_tg; -} - -#define sweep_space(s, from_g, body) {\ - slp = &sweep_loc[from_g][s];\ - nlp = &S_G.next_loc[from_g][s];\ - if (*slp == 0) *slp = S_G.first_loc[from_g][s];\ - pp = (ptr *)*slp;\ - while (pp != (nl = (ptr *)*nlp))\ - do\ - if ((p = *pp) == forward_marker)\ - pp = (ptr *)*(pp + 1);\ - else\ - body\ - while (pp != nl);\ - *slp = (ptr)pp; \ -} - -static void resweep_weak_pairs(ONLY_FORMAL_CTGS) { - IGEN from_g; ptr *slp, *nlp; ptr *pp, p, *nl; - - for (from_g = MIN_TG; from_g <= MAX_TG; from_g += 1) { - sweep_loc[from_g][space_weakpair] = orig_next_loc[from_g][space_weakpair]; - sweep_space(space_weakpair, from_g, { - forward_or_bwp(pp, p); - pp += 2; - }) - } -} - -static void forward_or_bwp(ptr *pp, ptr p) { - seginfo *si; - /* adapted from relocate */ - if (!IMMEDIATE(p) && (si = MaybeSegInfo(ptr_get_segment(p))) != NULL && si->space & space_old && !locked(p)) { - if (FWDMARKER(p) == forward_marker && TYPEBITS(p) != type_flonum) { - *pp = FWDADDRESS(p); - } else { - *pp = Sbwp_object; - } - } -} - -static void sweep_generation(ptr tc FORMAL_CTGS) { - IGEN from_g; ptr *slp, *nlp; ptr *pp, p, *nl; - - do { - change = 0; - for (from_g = MIN_TG; from_g <= MAX_TG; from_g += 1) { - sweep_space(space_impure, from_g, { - relocate_impure_help(pp, p, from_g); - p = *(pp += 1); - relocate_impure_help(pp, p, from_g); - pp += 1; - }) - - sweep_space(space_symbol, from_g, { - p = TYPE((ptr)pp, type_symbol); - sweep_symbol(p, from_g ACTUAL_CTGS); - pp += size_symbol / sizeof(ptr); - }) - - sweep_space(space_port, from_g, { - p = TYPE((ptr)pp, type_typed_object); - sweep_port(p, from_g ACTUAL_CTGS); - pp += size_port / sizeof(ptr); - }) - - sweep_space(space_weakpair, from_g, { - p = *(pp += 1); - relocate_impure_help(pp, p, from_g); - pp += 1; - }) - - sweep_space(space_ephemeron, from_g, { - p = TYPE((ptr)pp, type_pair); - add_ephemeron_to_pending(p); - pp += size_ephemeron / sizeof(ptr); - }) - - sweep_space(space_pure, from_g, { - relocate_pure_help(pp, p); - p = *(pp += 1); - relocate_pure_help(pp, p); - pp += 1; - }) - - sweep_space(space_continuation, from_g, { - p = TYPE((ptr)pp, type_closure); - sweep_continuation(p ACTUAL_CTGS); - pp += size_continuation / sizeof(ptr); - }) - - sweep_space(space_pure_typed_object, from_g, { - p = TYPE((ptr)pp, type_typed_object); - pp = (ptr *)((uptr)pp + sweep_typed_object(p, from_g ACTUAL_CTGS)); - }) - - sweep_space(space_code, from_g, { - p = TYPE((ptr)pp, type_typed_object); - sweep_code_object(tc, p ACTUAL_CTGS); - pp += size_code(CODELEN(p)) / sizeof(ptr); - }) - - sweep_space(space_impure_record, from_g, { - p = TYPE((ptr)pp, type_typed_object); - sweep_record(p, from_g ACTUAL_CTGS); - pp = (ptr *)((iptr)pp + - size_record_inst(UNFIX(RECORDDESCSIZE(RECORDINSTTYPE(p))))); - }) - } - - /* Waiting until sweeping doesn't trigger a change reduces the - chance that an ephemeron must be registered as a - segment-specific trigger or gets triggered for recheck, but - it doesn't change the worst-case complexity. */ - if (!change) - check_pending_ephemerons(ONLY_ACTUAL_CTGS); - } while (change); -} - -#ifndef NO_LOCKED_OLDSPACE_OBJECTS -static iptr size_object(ptr p) { - ITYPE t; ptr tf; - - if ((t = TYPEBITS(p)) == type_pair) { - seginfo *si; - if ((si = MaybeSegInfo(ptr_get_segment(p))) != NULL && (si->space & ~(space_locked | space_old)) == space_ephemeron) - return size_ephemeron; - else - return size_pair; - } else if (t == type_closure) { - ptr code = CLOSCODE(p); - if (CODETYPE(code) & (code_flag_continuation << code_flags_offset)) - return size_continuation; - else - return size_closure(CLOSLEN(p)); - } else if (t == type_symbol) { - return size_symbol; - } else if (t == type_flonum) { - return size_flonum; - /* typed objects */ - } else if (tf = TYPEFIELD(p), TYPEP(tf, mask_vector, type_vector)) { - return size_vector(Svector_length(p)); - } else if (TYPEP(tf, mask_string, type_string)) { - return size_string(Sstring_length(p)); - } else if (TYPEP(tf, mask_bytevector, type_bytevector)) { - return size_bytevector(Sbytevector_length(p)); - } else if (TYPEP(tf, mask_record, type_record)) { - return size_record_inst(UNFIX(RECORDDESCSIZE(tf))); - } else if (TYPEP(tf, mask_fxvector, type_fxvector)) { - return size_fxvector(Sfxvector_length(p)); - } else if (TYPEP(tf, mask_box, type_box)) { - return size_box; - } else if ((iptr)tf == type_ratnum) { - return size_ratnum; - } else if ((iptr)tf == type_exactnum) { - return size_exactnum; - } else if ((iptr)tf == type_inexactnum) { - return size_inexactnum; - } else if (TYPEP(tf, mask_bignum, type_bignum)) { - return size_bignum(BIGLEN(p)); - } else if (TYPEP(tf, mask_port, type_port)) { - return size_port; - } else if (TYPEP(tf, mask_code, type_code)) { - return size_code(CODELEN(p)); - } else if ((iptr)tf == type_thread) { - return size_thread; - } else if ((iptr)tf == type_rtd_counts) { - return size_rtd_counts; - } else { - S_error_abort("size_object(gc): illegal type"); - return 0 /* not reached */; - } -} -#endif /* !NO_LOCKED_OLDSPACE_OBJECTS */ - -static iptr sweep_typed_object(ptr p, IGEN from_g FORMAL_CTGS) { - ptr tf = TYPEFIELD(p); - - if (TYPEP(tf, mask_record, type_record)) { - sweep_record(p, from_g ACTUAL_CTGS); - return size_record_inst(UNFIX(RECORDDESCSIZE(RECORDINSTTYPE(p)))); - } else if (TYPEP(tf, mask_thread, type_thread)) { - sweep_thread(p ACTUAL_CTGS); - return size_thread; - } else { - S_error_abort("sweep_typed_object(gc): unexpected type"); - return 0 /* not reached */; - } -} - -static void sweep_symbol(ptr p, IGEN from_g FORMAL_CTGS) { - ptr val, code; - - relocate_impure(&INITSYMVAL(p), from_g); - val = SYMVAL(p); - code = Sprocedurep(val) ? CLOSCODE(val) : SYMCODE(p); - relocate_pure(&code); - INITSYMCODE(p,code); - relocate_impure(&INITSYMPLIST(p), from_g); - relocate_impure(&INITSYMSPLIST(p), from_g); - relocate_impure(&INITSYMNAME(p), from_g); - relocate_impure(&INITSYMHASH(p), from_g); -} - -static void sweep_port(ptr p, IGEN from_g FORMAL_CTGS) { - relocate_impure(&PORTHANDLER(p), from_g); - relocate_impure(&PORTINFO(p), from_g); - relocate_impure(&PORTNAME(p), from_g); - - if (PORTTYPE(p) & PORT_FLAG_OUTPUT) { - iptr n = (iptr)PORTOLAST(p) - (iptr)PORTOBUF(p); - relocate_impure(&PORTOBUF(p), from_g); - PORTOLAST(p) = (ptr)((iptr)PORTOBUF(p) + n); - } - - if (PORTTYPE(p) & PORT_FLAG_INPUT) { - iptr n = (iptr)PORTILAST(p) - (iptr)PORTIBUF(p); - relocate_impure(&PORTIBUF(p), from_g); - PORTILAST(p) = (ptr)((iptr)PORTIBUF(p) + n); - } -} - -static void sweep_thread(ptr p FORMAL_CTGS) { - ptr tc = (ptr)THREADTC(p); - INT i; - - if (tc != (ptr)0) { - ptr old_stack = SCHEMESTACK(tc); - if (OLDSPACE(old_stack)) { - iptr clength = (uptr)SFP(tc) - (uptr)old_stack; - /* include SFP[0], which contains the return address */ - SCHEMESTACK(tc) = copy_stack(old_stack, &SCHEMESTACKSIZE(tc), clength + sizeof(ptr) ACTUAL_CTGS); - SFP(tc) = (ptr)((uptr)SCHEMESTACK(tc) + clength); - ESP(tc) = (ptr)((uptr)SCHEMESTACK(tc) + SCHEMESTACKSIZE(tc) - stack_slop); - } - STACKCACHE(tc) = Snil; - relocate_pure(&CCHAIN(tc)); - /* U32 RANDOMSEED(tc) */ - /* I32 ACTIVE(tc) */ - relocate_pure(&STACKLINK(tc)); - /* iptr SCHEMESTACKSIZE */ - relocate_pure(&WINDERS(tc)); - relocate_return_addr(&FRAME(tc,0)); - sweep_stack((uptr)SCHEMESTACK(tc), (uptr)SFP(tc), (uptr)FRAME(tc,0) ACTUAL_CTGS); - U(tc) = V(tc) = W(tc) = X(tc) = Y(tc) = 0; - /* immediate SOMETHINGPENDING(tc) */ - /* immediate TIMERTICKS */ - /* immediate DISABLE_COUNT */ - /* immediate SIGNALINTERRUPTPENDING */ - /* void* SIGNALINTERRUPTQUEUE(tc) */ - /* immediate KEYBOARDINTERRUPTPENDING */ - relocate_pure(&THREADNO(tc)); - relocate_pure(&CURRENTINPUT(tc)); - relocate_pure(&CURRENTOUTPUT(tc)); - relocate_pure(&CURRENTERROR(tc)); - /* immediate BLOCKCOUNTER */ - relocate_pure(&SFD(tc)); - relocate_pure(&CURRENTMSO(tc)); - relocate_pure(&TARGETMACHINE(tc)); - relocate_pure(&FXLENGTHBV(tc)); - relocate_pure(&FXFIRSTBITSETBV(tc)); - relocate_pure(&NULLIMMUTABLEVECTOR(tc)); - relocate_pure(&NULLIMMUTABLEFXVECTOR(tc)); - relocate_pure(&NULLIMMUTABLEBYTEVECTOR(tc)); - relocate_pure(&NULLIMMUTABLESTRING(tc)); - /* immediate METALEVEL */ - relocate_pure(&COMPILEPROFILE(tc)); - /* immediate GENERATEINSPECTORINFORMATION */ - /* immediate GENERATEPROFILEFORMS */ - /* immediate OPTIMIZELEVEL */ - relocate_pure(&SUBSETMODE(tc)); - /* immediate SUPPRESSPRIMITIVEINLINING */ - relocate_pure(&DEFAULTRECORDEQUALPROCEDURE(tc)); - relocate_pure(&DEFAULTRECORDHASHPROCEDURE(tc)); - relocate_pure(&COMPRESSFORMAT(tc)); - relocate_pure(&COMPRESSLEVEL(tc)); - /* void* LZ4OUTBUFFER(tc) */ - /* U64 INSTRCOUNTER(tc) */ - /* U64 ALLOCCOUNTER(tc) */ - relocate_pure(&PARAMETERS(tc)); - for (i = 0 ; i < virtual_register_count ; i += 1) { - relocate_pure(&VIRTREG(tc, i)); - } - DSTBV(tc) = SRCBV(tc) = Sfalse; - } -} - -static void sweep_continuation(ptr p FORMAL_CTGS) { - relocate_pure(&CONTWINDERS(p)); - - /* bug out for shot 1-shot continuations */ - if (CONTLENGTH(p) == scaled_shot_1_shot_flag) return; - - if (OLDSPACE(CONTSTACK(p))) - CONTSTACK(p) = copy_stack(CONTSTACK(p), &CONTLENGTH(p), CONTCLENGTH(p) ACTUAL_CTGS); - - relocate_pure(&CONTLINK(p)); - relocate_return_addr(&CONTRET(p)); - - /* use CLENGTH to avoid sweeping unoccupied portion of one-shots */ - sweep_stack((uptr)CONTSTACK(p), (uptr)CONTSTACK(p) + CONTCLENGTH(p), (uptr)CONTRET(p) ACTUAL_CTGS); -} - -/* assumes stack has already been copied to newspace */ -static void sweep_stack(uptr base, uptr fp, uptr ret FORMAL_CTGS) { - ptr *pp; iptr oldret; - ptr num; - - while (fp != base) { - if (fp < base) - S_error_abort("sweep_stack(gc): malformed stack"); - fp = fp - ENTRYFRAMESIZE(ret); - pp = (ptr *)fp; - - oldret = ret; - ret = (iptr)(*pp); - relocate_return_addr(pp); - - num = ENTRYLIVEMASK(oldret); - if (Sfixnump(num)) { - uptr mask = UNFIX(num); - while (mask != 0) { - pp += 1; - if (mask & 0x0001) relocate_pure(pp); - mask >>= 1; - } - } else { - iptr index; - - relocate_pure(&ENTRYLIVEMASK(oldret)); - num = ENTRYLIVEMASK(oldret); - index = BIGLEN(num); - while (index-- != 0) { - INT bits = bigit_bits; - bigit mask = BIGIT(num,index); - while (bits-- > 0) { - pp += 1; - if (mask & 1) relocate_pure(pp); - mask >>= 1; - } - } - } - } -} - -static void sweep_record(ptr x, IGEN from_g FORMAL_CTGS) { - ptr *pp; ptr num; ptr rtd; - - /* record-type descriptor was forwarded in copy */ - rtd = RECORDINSTTYPE(x); - num = RECORDDESCPM(rtd); - pp = &RECORDINSTIT(x,0); - - /* sweep cells for which bit in pm is set; quit when pm == 0. */ - if (Sfixnump(num)) { - /* ignore bit for already forwarded rtd */ - uptr mask = (uptr)UNFIX(num) >> 1; - if (mask == (uptr)-1 >> 1) { - ptr *ppend = (ptr *)((uptr)pp + UNFIX(RECORDDESCSIZE(rtd))) - 1; - while (pp < ppend) { - relocate_impure(pp, from_g); - pp += 1; - } - } else { - while (mask != 0) { - if (mask & 1) { relocate_impure(pp, from_g); } - mask >>= 1; - pp += 1; - } - } - } else { - iptr index; bigit mask; INT bits; - - /* bignum pointer mask may have been forwarded */ - relocate_pure(&RECORDDESCPM(rtd)); - num = RECORDDESCPM(rtd); - index = BIGLEN(num) - 1; - /* ignore bit for already forwarded rtd */ - mask = BIGIT(num,index) >> 1; - bits = bigit_bits - 1; - for (;;) { - do { - if (mask & 1) { relocate_impure(pp, from_g); } - mask >>= 1; - pp += 1; - } while (--bits > 0); - if (index-- == 0) break; - mask = BIGIT(num,index); - bits = bigit_bits; - } - } -} - -static IGEN sweep_dirty_record(ptr x, IGEN youngest FORMAL_CTGS) { - ptr *pp; ptr num; ptr rtd; - - /* warning: assuming rtd is immutable */ - rtd = RECORDINSTTYPE(x); - - /* warning: assuming MPM field is immutable */ - num = RECORDDESCMPM(rtd); - pp = &RECORDINSTIT(x,0); - - /* sweep cells for which bit in mpm is set */ - if (Sfixnump(num)) { - /* ignore bit for assumed immutable rtd */ - uptr mask = (uptr)UNFIX(num) >> 1; - while (mask != 0) { - if (mask & 1) relocate_dirty(pp, youngest); - mask >>= 1; - pp += 1; - } - } else { - iptr index; bigit mask; INT bits; - - index = BIGLEN(num) - 1; - /* ignore bit for assumed immutable rtd */ - mask = BIGIT(num,index) >> 1; - bits = bigit_bits - 1; - for (;;) { - do { - if (mask & 1) relocate_dirty(pp, youngest); - mask >>= 1; - pp += 1; - } while (--bits > 0); - if (index-- == 0) break; - mask = BIGIT(num,index); - bits = bigit_bits; - } - } - - return youngest; -} - -static void sweep_code_object(ptr tc, ptr co FORMAL_CTGS) { - ptr t, oldco; iptr a, m, n; - -#ifdef DEBUG - if ((CODETYPE(co) & mask_code) != type_code) { - (void)printf("unexpected type %x sweeping code object %p\n", CODETYPE(co), co); - (void)fflush(stdout); - } -#endif - - relocate_pure(&CODENAME(co)); - relocate_pure(&CODEARITYMASK(co)); - relocate_pure(&CODEINFO(co)); - relocate_pure(&CODEPINFOS(co)); - - t = CODERELOC(co); - m = RELOCSIZE(t); - oldco = RELOCCODE(t); - a = 0; - n = 0; - while (n < m) { - uptr entry, item_off, code_off; ptr obj; - entry = RELOCIT(t, n); n += 1; - if (RELOC_EXTENDED_FORMAT(entry)) { - item_off = RELOCIT(t, n); n += 1; - code_off = RELOCIT(t, n); n += 1; - } else { - item_off = RELOC_ITEM_OFFSET(entry); - code_off = RELOC_CODE_OFFSET(entry); - } - a += code_off; - obj = S_get_code_obj(RELOC_TYPE(entry), oldco, a, item_off); - relocate_pure(&obj); - S_set_code_obj("gc", RELOC_TYPE(entry), co, a, obj, item_off); - } - - /* Don't copy non-oldspace relocation tables, since we may be - sweeping a locked code object that is older than max_target_generation - Doing so would be a waste of work anyway. */ - if (OLDSPACE(t)) { - IGEN newg = compute_target_generation(GENERATION(t) ACTUAL_CTGS); - if (newg == static_generation && !S_G.retain_static_relocation && (CODETYPE(co) & (code_flag_template << code_flags_offset)) == 0) { - CODERELOC(co) = (ptr)0; - } else { - ptr oldt = t; - n = size_reloc_table(RELOCSIZE(oldt)); -#ifdef ENABLE_OBJECT_COUNTS - S_G.countof[newg][countof_relocation_table] += 1; - S_G.bytesof[newg][countof_relocation_table] += n; -#endif /* ENABLE_OBJECT_COUNTS */ - find_room(space_data, newg, typemod, n, t); - copy_ptrs(typemod, t, oldt, n); - RELOCCODE(t) = co; - CODERELOC(co) = t; - } - } else { - RELOCCODE(t) = co; - } - - S_record_code_mod(tc, (uptr)&CODEIT(co,0), (uptr)CODELEN(co)); -} - -typedef struct _weakseginfo { - seginfo *si; - IGEN youngest[cards_per_segment]; - struct _weakseginfo *next; -} weakseginfo; - -static weakseginfo *weaksegments_to_resweep; - -static void record_dirty_segment(IGEN from_g, IGEN to_g, seginfo *si) { - if (si->min_dirty_byte != 0xff) { - S_error_abort("record_dirty(gc): unexpected mutation while sweeping"); - } - - if (to_g < from_g) { - seginfo *oldfirst = DirtySegments(from_g, to_g); - DirtySegments(from_g, to_g) = si; - si->dirty_prev = &DirtySegments(from_g, to_g); - si->dirty_next = oldfirst; - if (oldfirst != NULL) oldfirst->dirty_prev = &si->dirty_next; - si->min_dirty_byte = to_g; - } -} - -static void sweep_dirty(ONLY_FORMAL_CTGS) { - IGEN youngest, min_youngest; - ptr *pp, *ppend, *nl; - uptr seg, d; - ISPC s; - IGEN from_g, to_g; - seginfo *dirty_si, *nextsi; - - weaksegments_to_resweep = NULL; - - /* clear dirty segment lists for copied generations */ - for (from_g = 1; from_g <= MAX_CG; from_g += 1) { - for (to_g = 0; to_g < from_g; to_g += 1) { - DirtySegments(from_g, to_g) = NULL; - } - } - - /* NB: could have problems if a card is moved from some current or to-be-swept (from_g, to_g) to some previously - swept list due to a dirty_set while we sweep. believe this can't happen as of 6/14/2013. if it can, it - might be sufficient to process the lists in reverse order. */ - for (from_g = MAX_CG + 1; from_g <= static_generation; INCRGEN(from_g)) { - for (to_g = 0; to_g <= MAX_CG; to_g += 1) { - for (dirty_si = DirtySegments(from_g, to_g), DirtySegments(from_g, to_g) = NULL; dirty_si != NULL; dirty_si = nextsi) { - nextsi = dirty_si->dirty_next; - seg = dirty_si->number; - s = dirty_si->space; - - if (s & space_locked) continue; - - /* reset min dirty byte so we can detect if byte is set while card is swept */ - dirty_si->min_dirty_byte = 0xff; - - min_youngest = 0xff; - nl = from_g == MAX_TG ? (ptr *)orig_next_loc[from_g][s] : (ptr *)S_G.next_loc[from_g][s]; - ppend = build_ptr(seg, 0); - - if (s == space_weakpair) { - weakseginfo *next = weaksegments_to_resweep; - find_room(space_data, 0, typemod, ptr_align(sizeof(weakseginfo)), weaksegments_to_resweep); - weaksegments_to_resweep->si = dirty_si; - weaksegments_to_resweep->next = next; - } - - d = 0; - while (d < cards_per_segment) { - uptr dend = d + sizeof(iptr); - iptr *dp = (iptr *)(dirty_si->dirty_bytes + d); - /* check sizeof(iptr) bytes at a time for 0xff */ - if (*dp == -1) { - pp = ppend; - ppend += bytes_per_card; - if (pp <= nl && nl < ppend) ppend = nl; - d = dend; - } else { - while (d < dend) { - pp = ppend; - ppend += bytes_per_card / sizeof(ptr); - if (pp <= nl && nl < ppend) ppend = nl; - - if (dirty_si->dirty_bytes[d] <= MAX_CG) { - /* assume we won't find any wrong-way pointers */ - youngest = 0xff; - - if (s == space_impure) { - while (pp < ppend && *pp != forward_marker) { - /* handle two pointers at a time */ - relocate_dirty(pp, youngest); - pp += 1; - relocate_dirty(pp, youngest); - pp += 1; - } - } else if (s == space_symbol) { - /* old symbols cannot overlap segment boundaries - since any object that spans multiple - generations begins at the start of a segment, - and symbols are much smaller (we assume) - than the segment size. */ - pp = (ptr *)build_ptr(seg,0) + - ((pp - (ptr *)build_ptr(seg,0)) / - (size_symbol / sizeof(ptr))) * - (size_symbol / sizeof(ptr)); - - while (pp < ppend && *pp != forward_marker) { /* might overshoot card by part of a symbol. no harm. */ - ptr p, val, code; - - p = TYPE((ptr)pp, type_symbol); - - val = SYMVAL(p); - relocate_dirty(&val, youngest); - INITSYMVAL(p) = val; - code = Sprocedurep(val) ? CLOSCODE(val) : SYMCODE(p); - relocate_dirty(&code, youngest); - INITSYMCODE(p,code); - relocate_dirty(&INITSYMPLIST(p), youngest); - relocate_dirty(&INITSYMSPLIST(p), youngest); - relocate_dirty(&INITSYMNAME(p), youngest); - relocate_dirty(&INITSYMHASH(p), youngest); - - pp += size_symbol / sizeof(ptr); - } - } else if (s == space_port) { - /* old ports cannot overlap segment boundaries - since any object that spans multiple - generations begins at the start of a segment, - and ports are much smaller (we assume) - than the segment size. */ - pp = (ptr *)build_ptr(seg,0) + - ((pp - (ptr *)build_ptr(seg,0)) / - (size_port / sizeof(ptr))) * - (size_port / sizeof(ptr)); - - while (pp < ppend && *pp != forward_marker) { /* might overshoot card by part of a port. no harm. */ - ptr p = TYPE((ptr)pp, type_typed_object); - - relocate_dirty(&PORTHANDLER(p), youngest); - relocate_dirty(&PORTINFO(p), youngest); - relocate_dirty(&PORTNAME(p), youngest); - - if (PORTTYPE(p) & PORT_FLAG_OUTPUT) { - iptr n = (iptr)PORTOLAST(p) - (iptr)PORTOBUF(p); - relocate_dirty(&PORTOBUF(p), youngest); - PORTOLAST(p) = (ptr)((iptr)PORTOBUF(p) + n); - } - - if (PORTTYPE(p) & PORT_FLAG_INPUT) { - iptr n = (iptr)PORTILAST(p) - (iptr)PORTIBUF(p); - relocate_dirty(&PORTIBUF(p), youngest); - PORTILAST(p) = (ptr)((iptr)PORTIBUF(p) + n); - } - - pp += size_port / sizeof(ptr); - } - } else if (s == space_impure_record) { /* abandon hope all ye who enter here */ - uptr j; ptr p, pnext; seginfo *si; - - /* synchronize on first record that overlaps the dirty - area, then relocate any mutable pointers in that - record and those that follow within the dirty area. */ - - /* find first segment of group of like segments */ - j = seg - 1; - while ((si = MaybeSegInfo(j)) != NULL && - si->space == s && - si->generation == from_g) - j -= 1; - j += 1; - - /* now find first record in segment seg */ - /* we count on following fact: if an object spans two - or more segments, then he starts at the beginning - of a segment */ - for (;;) { - p = TYPE(build_ptr(j,0),type_typed_object); - pnext = (ptr)((iptr)p + - size_record_inst(UNFIX(RECORDDESCSIZE( - RECORDINSTTYPE(p))))); - if (ptr_get_segment(pnext) >= seg) break; - j = ptr_get_segment(pnext) + 1; - } - - /* now find first within dirty area */ - while ((ptr *)UNTYPE(pnext, type_typed_object) <= pp) { - p = pnext; - pnext = (ptr)((iptr)p + - size_record_inst(UNFIX(RECORDDESCSIZE( - RECORDINSTTYPE(p))))); - } - - /* now sweep */ - while ((ptr *)UNTYPE(p, type_typed_object) < ppend) { - /* quit on end of segment */ - if (FWDMARKER(p) == forward_marker) break; - - youngest = sweep_dirty_record(p, youngest ACTUAL_CTGS); - p = (ptr)((iptr)p + - size_record_inst(UNFIX(RECORDDESCSIZE( - RECORDINSTTYPE(p))))); - } - } else if (s == space_weakpair) { - while (pp < ppend && *pp != forward_marker) { - /* skip car field and handle cdr field */ - pp += 1; - relocate_dirty(pp, youngest); - pp += 1; - } - } else if (s == space_ephemeron) { - while (pp < ppend && *pp != forward_marker) { - ptr p = TYPE((ptr)pp, type_pair); - youngest = check_dirty_ephemeron(p, youngest ACTUAL_CTGS); - pp += size_ephemeron / sizeof(ptr); - } - } else { - S_error_abort("sweep_dirty(gc): unexpected space"); - } - - if (s == space_weakpair) { - weaksegments_to_resweep->youngest[d] = youngest; - } else { - dirty_si->dirty_bytes[d] = youngest < from_g ? youngest : 0xff; - } - if (youngest < min_youngest) min_youngest = youngest; - } else { - if (dirty_si->dirty_bytes[d] < min_youngest) min_youngest = dirty_si->dirty_bytes[d]; - } - d += 1; - } - } - } - if (s != space_weakpair) { - record_dirty_segment(from_g, min_youngest, dirty_si); - } - } - } - } -} - -static void resweep_dirty_weak_pairs(ONLY_FORMAL_CTGS) { - weakseginfo *ls; - ptr *pp, *ppend, *nl, p; - IGEN from_g, min_youngest, youngest, pg, newpg; - uptr d; - - for (ls = weaksegments_to_resweep; ls != NULL; ls = ls->next) { - seginfo *dirty_si = ls->si; - from_g = dirty_si->generation; - nl = from_g == MAX_TG ? (ptr *)orig_next_loc[from_g][space_weakpair] : (ptr *)S_G.next_loc[from_g][space_weakpair]; - ppend = build_ptr(dirty_si->number, 0); - min_youngest = 0xff; - d = 0; - while (d < cards_per_segment) { - uptr dend = d + sizeof(iptr); - iptr *dp = (iptr *)(dirty_si->dirty_bytes + d); - /* check sizeof(iptr) bytes at a time for 0xff */ - if (*dp == -1) { - d = dend; - ppend += bytes_per_card; - } else { - while (d < dend) { - pp = ppend; - ppend += bytes_per_card / sizeof(ptr); - if (pp <= nl && nl < ppend) ppend = nl; - if (dirty_si->dirty_bytes[d] <= MAX_CG) { - youngest = ls->youngest[d]; - while (pp < ppend) { - p = *pp; - seginfo *si; - - /* handle car field */ - if (!IMMEDIATE(p) && (si = MaybeSegInfo(ptr_get_segment(p))) != NULL) { - pg = si->generation; - newpg = compute_target_generation(pg ACTUAL_CTGS); - if (si->space & space_old) { - if (locked(p)) { - if (newpg < youngest) youngest = newpg; - } else if (FWDMARKER(p) == forward_marker && TYPEBITS(p) != type_flonum) { - *pp = FWDADDRESS(p); - if (newpg < youngest) youngest = newpg; - } else { - *pp = Sbwp_object; - } - } else { - if (pg < youngest) youngest = pg; - } - } - - /* skip cdr field */ - pp += 2; - } - - dirty_si->dirty_bytes[d] = youngest < from_g ? youngest : 0xff; - if (youngest < min_youngest) min_youngest = youngest; - } else { - if (dirty_si->dirty_bytes[d] < min_youngest) min_youngest = dirty_si->dirty_bytes[d]; - } - d += 1; - } - } - } - record_dirty_segment(from_g, min_youngest, dirty_si); - } -} - -static ptr pending_ephemerons = NULL; -/* Ephemerons that we haven't looked at, chained through `next`. */ - -static ptr trigger_ephemerons = NULL; -/* Ephemerons that we've checked and added to segment triggers, - chained through `next`. Ephemerons attached to a segment are - chained through `trigger-next`. A #t in `trigger-next` means that - the ephemeron has been processed, so we don't need to remove it - from the trigger list in a segment. */ - -static ptr repending_ephemerons = NULL; -/* Ephemerons in `trigger_ephemerons` that we need to inspect again, - removed from the triggering segment and chained here through - `trigger-next`. */ - -static void add_ephemeron_to_pending(ptr pe) { - /* We could call check_ephemeron directly here, but the indirection - through `pending_ephemerons` can dramatically decrease the number - of times that we have to trigger re-checking, especially since - check_pending_pehemerons() is run only after all other sweep - opportunities are exhausted. */ - EPHEMERONNEXT(pe) = pending_ephemerons; - pending_ephemerons = pe; -} - -static void add_trigger_ephemerons_to_repending(ptr pe) { - ptr last_pe = pe, next_pe = EPHEMERONTRIGGERNEXT(pe); - while (next_pe != NULL) { - last_pe = next_pe; - next_pe = EPHEMERONTRIGGERNEXT(next_pe); - } - EPHEMERONTRIGGERNEXT(last_pe) = repending_ephemerons; - repending_ephemerons = pe; -} - -static void check_ephemeron(ptr pe, IBOOL add_to_trigger FORMAL_CTGS) { - ptr p; - seginfo *si; - IGEN from_g = GENERATION(pe); - - p = Scar(pe); - if (!IMMEDIATE(p) && (si = MaybeSegInfo(ptr_get_segment(p))) != NULL && si->space & space_old && !locked(p)) { - if (FWDMARKER(p) == forward_marker && TYPEBITS(p) != type_flonum) { -#ifndef NO_DIRTY_NEWSPACE_POINTERS - IGEN pg = compute_target_generation(si->generation ACTUAL_CTGS); - if (pg < from_g) record_new_dirty_card(&INITCAR(pe), pg); -#endif - INITCAR(pe) = FWDADDRESS(p); - relocate_impure(&INITCDR(pe), from_g); - if (!add_to_trigger) - EPHEMERONTRIGGERNEXT(pe) = Strue; /* in trigger list, #t means "done" */ - } else { - /* Not reached, so far; install as trigger */ - EPHEMERONTRIGGERNEXT(pe) = si->trigger_ephemerons; - si->trigger_ephemerons = pe; - if (add_to_trigger) { - EPHEMERONNEXT(pe) = trigger_ephemerons; - trigger_ephemerons = pe; - } - } - } else { - relocate_impure(&INITCDR(pe), from_g); - } -} - -static void check_pending_ephemerons(ONLY_FORMAL_CTGS) { - ptr pe, next_pe; - - pe = pending_ephemerons; - pending_ephemerons = NULL; - while (pe != NULL) { - next_pe = EPHEMERONNEXT(pe); - check_ephemeron(pe, 1 ACTUAL_CTGS); - pe = next_pe; - } - - pe = repending_ephemerons; - repending_ephemerons = NULL; - while (pe != NULL) { - next_pe = EPHEMERONTRIGGERNEXT(pe); - check_ephemeron(pe, 0 ACTUAL_CTGS); - pe = next_pe; - } -} - -/* Like check_ephemeron(), but for a dirty, old-generation - ephemeron (that was not yet added to the pending list), so we can - be less pessimistic than setting `youngest` to the target - generation: */ -static IGEN check_dirty_ephemeron(ptr pe, IGEN youngest FORMAL_CTGS) { - ptr p; - seginfo *si; - IGEN pg; - - p = Scar(pe); - if (!IMMEDIATE(p) && (si = MaybeSegInfo(ptr_get_segment(p))) != NULL) { - if (si->space & space_old && !locked(p)) { - if (FWDMARKER(p) == forward_marker && TYPEBITS(p) != type_flonum) { - INITCAR(pe) = FWDADDRESS(p); - if (youngest != MIN_TG && (pg = compute_target_generation(si->generation ACTUAL_CTGS)) < youngest) - youngest = pg; - relocate_dirty(&INITCDR(pe), youngest); - } else { - /* Not reached, so far; add to pending list */ - add_ephemeron_to_pending(pe); - /* Make the consistent (but pessimistic w.r.t. to wrong-way - pointers) assumption that the key will stay live and move - to the target generation. That assumption covers the value - part, too, since it can't end up younger than the target - generation. */ - if (youngest != MIN_TG && (pg = compute_target_generation(si->generation ACTUAL_CTGS)) < youngest) - youngest = pg; - } - } else { - if (youngest != MIN_TG && (pg = si->generation) < youngest) - youngest = pg; - relocate_dirty(&INITCDR(pe), youngest); - } - } else { - /* Non-collectable key means that the value determines - `youngest`: */ - relocate_dirty(&INITCDR(pe), youngest); - } - - return youngest; -} - -static void clear_trigger_ephemerons(void) { - ptr pe; - - if (pending_ephemerons != NULL) - S_error_abort("clear_trigger_ephemerons(gc): non-empty pending list"); - - pe = trigger_ephemerons; - trigger_ephemerons = NULL; - while (pe != NULL) { - if (EPHEMERONTRIGGERNEXT(pe) == Strue) { - /* The ephemeron was triggered and retains its key and value */ - } else { - seginfo *si; - ptr p = Scar(pe); - /* Key never became reachable, so clear key and value */ - INITCAR(pe) = Sbwp_object; - INITCDR(pe) = Sbwp_object; - - /* Remove trigger */ - si = SegInfo(ptr_get_segment(p)); - si->trigger_ephemerons = NULL; - } - pe = EPHEMERONNEXT(pe); - } -} diff --git a/ta6ob/c/gcwrapper.c b/ta6ob/c/gcwrapper.c deleted file mode 100644 index f00f9cd..0000000 --- a/ta6ob/c/gcwrapper.c +++ /dev/null @@ -1,864 +0,0 @@ -/* gcwrapper.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" - -/* locally defined functions */ -static IBOOL memqp(ptr x, ptr ls); -static IBOOL remove_first_nomorep(ptr x, ptr *pls, IBOOL look); -static void segment_tell(uptr seg); -static void check_heap_dirty_msg(char *msg, ptr *x); -static IBOOL dirty_listedp(seginfo *x, IGEN from_g, IGEN to_g); -static void check_dirty_space(ISPC s); -static void check_dirty(void); - -static IBOOL checkheap_noisy; - -void S_gc_init(void) { - IGEN g; INT i; - - S_checkheap = 0; /* 0 for disabled, 1 for enabled */ - S_checkheap_errors = 0; /* count of errors detected by checkheap */ - checkheap_noisy = 0; /* 0 for error output only; 1 for more noisy output */ - S_G.prcgeneration = static_generation; - - if (S_checkheap) { - printf(checkheap_noisy ? "NB: check_heap is enabled and noisy\n" : "NB: check_heap_is_enabled\n"); - fflush(stdout); - } - -#ifndef WIN32 - for (g = 0; g <= static_generation; g++) { - S_child_processes[g] = Snil; - } -#endif /* WIN32 */ - - if (!S_boot_time) return; - - for (g = 0; g <= static_generation; g++) { - S_G.guardians[g] = Snil; - S_G.locked_objects[g] = Snil; - S_G.unlocked_objects[g] = Snil; - } - S_G.max_nonstatic_generation = - S_G.new_max_nonstatic_generation = - S_G.min_free_gen = - S_G.new_min_free_gen = default_max_nonstatic_generation; - - for (g = 0; g <= static_generation; g += 1) { - for (i = 0; i < countof_types; i += 1) { - S_G.countof[g][i] = 0; - S_G.bytesof[g][i] = 0; - } - S_G.gctimestamp[g] = 0; - S_G.rtds_with_counts[g] = Snil; - } - - S_G.countof[static_generation][countof_oblist] += 1; - S_G.bytesof[static_generation][countof_oblist] += S_G.oblist_length * sizeof(bucket *); - - S_protect(&S_G.static_id); - S_G.static_id = S_intern((const unsigned char *)"static"); - - S_protect(&S_G.countof_names); - S_G.countof_names = S_vector(countof_types); - for (i = 0; i < countof_types; i += 1) { - INITVECTIT(S_G.countof_names, i) = FIX(0); - S_G.countof_size[i] = 0; - } - INITVECTIT(S_G.countof_names, countof_pair) = S_intern((const unsigned char *)"pair"); - S_G.countof_size[countof_pair] = size_pair; - INITVECTIT(S_G.countof_names, countof_symbol) = S_intern((const unsigned char *)"symbol"); - S_G.countof_size[countof_symbol] = size_symbol; - INITVECTIT(S_G.countof_names, countof_flonum) = S_intern((const unsigned char *)"flonum"); - S_G.countof_size[countof_flonum] = size_flonum; - INITVECTIT(S_G.countof_names, countof_closure) = S_intern((const unsigned char *)"procedure"); - S_G.countof_size[countof_closure] = 0; - INITVECTIT(S_G.countof_names, countof_continuation) = S_intern((const unsigned char *)"continuation"); - S_G.countof_size[countof_continuation] = size_continuation; - INITVECTIT(S_G.countof_names, countof_bignum) = S_intern((const unsigned char *)"bignum"); - S_G.countof_size[countof_bignum] = 0; - INITVECTIT(S_G.countof_names, countof_ratnum) = S_intern((const unsigned char *)"ratnum"); - S_G.countof_size[countof_ratnum] = size_ratnum; - INITVECTIT(S_G.countof_names, countof_inexactnum) = S_intern((const unsigned char *)"inexactnum"); - S_G.countof_size[countof_inexactnum] = size_inexactnum; - INITVECTIT(S_G.countof_names, countof_exactnum) = S_intern((const unsigned char *)"exactnum"); - S_G.countof_size[countof_exactnum] = size_exactnum; - INITVECTIT(S_G.countof_names, countof_box) = S_intern((const unsigned char *)"box"); - S_G.countof_size[countof_box] = size_box; - INITVECTIT(S_G.countof_names, countof_port) = S_intern((const unsigned char *)"port"); - S_G.countof_size[countof_port] = size_port; - INITVECTIT(S_G.countof_names, countof_code) = S_intern((const unsigned char *)"code"); - S_G.countof_size[countof_code] = 0; - INITVECTIT(S_G.countof_names, countof_thread) = S_intern((const unsigned char *)"thread"); - S_G.countof_size[countof_thread] = size_thread; - INITVECTIT(S_G.countof_names, countof_tlc) = S_intern((const unsigned char *)"tlc"); - S_G.countof_size[countof_tlc] = size_tlc; - INITVECTIT(S_G.countof_names, countof_rtd_counts) = S_intern((const unsigned char *)"rtd-counts"); - S_G.countof_size[countof_rtd_counts] = size_rtd_counts; - INITVECTIT(S_G.countof_names, countof_stack) = S_intern((const unsigned char *)"stack"); - S_G.countof_size[countof_stack] = 0; - INITVECTIT(S_G.countof_names, countof_relocation_table) = S_intern((const unsigned char *)"reloc-table"); - S_G.countof_size[countof_relocation_table] = 0; - INITVECTIT(S_G.countof_names, countof_weakpair) = S_intern((const unsigned char *)"weakpair"); - S_G.countof_size[countof_weakpair] = size_pair; - INITVECTIT(S_G.countof_names, countof_vector) = S_intern((const unsigned char *)"vector"); - S_G.countof_size[countof_vector] = 0; - INITVECTIT(S_G.countof_names, countof_string) = S_intern((const unsigned char *)"string"); - S_G.countof_size[countof_string] = 0; - INITVECTIT(S_G.countof_names, countof_fxvector) = S_intern((const unsigned char *)"fxvector"); - S_G.countof_size[countof_fxvector] = 0; - INITVECTIT(S_G.countof_names, countof_bytevector) = S_intern((const unsigned char *)"bytevector"); - S_G.countof_size[countof_bytevector] = 0; - INITVECTIT(S_G.countof_names, countof_locked) = S_intern((const unsigned char *)"locked"); - S_G.countof_size[countof_locked] = 0; - INITVECTIT(S_G.countof_names, countof_guardian) = S_intern((const unsigned char *)"guardian"); - S_G.countof_size[countof_guardian] = size_guardian_entry; - INITVECTIT(S_G.countof_names, countof_oblist) = S_intern((const unsigned char *)"oblist"); - S_G.countof_size[countof_guardian] = 0; - INITVECTIT(S_G.countof_names, countof_ephemeron) = S_intern((const unsigned char *)"ephemron"); - S_G.countof_size[countof_ephemeron] = 0; - for (i = 0; i < countof_types; i += 1) { - if (Svector_ref(S_G.countof_names, i) == FIX(0)) { - fprintf(stderr, "uninitialized countof_name at index %d\n", i); - S_abnormal_exit(); - } - } -} - -IGEN S_maxgen(void) { - return S_G.new_max_nonstatic_generation; -} - -void S_set_maxgen(IGEN g) { - if (g < 0 || g >= static_generation) { - fprintf(stderr, "invalid maxgen %d\n", g); - S_abnormal_exit(); - } - if (S_G.new_min_free_gen == S_G.new_max_nonstatic_generation || S_G.new_min_free_gen > g) { - S_G.new_min_free_gen = g; - } - S_G.new_max_nonstatic_generation = g; -} - -IGEN S_minfreegen(void) { - return S_G.new_min_free_gen; -} - -void S_set_minfreegen(IGEN g) { - S_G.new_min_free_gen = g; - if (S_G.new_max_nonstatic_generation == S_G.max_nonstatic_generation) { - S_G.min_free_gen = g; - } -} - -static IBOOL memqp(ptr x, ptr ls) { - for (;;) { - if (ls == Snil) return 0; - if (Scar(ls) == x) return 1; - ls = Scdr(ls); - } -} - -static IBOOL remove_first_nomorep(ptr x, ptr *pls, IBOOL look) { - ptr ls; - - for (;;) { - ls = *pls; - if (ls == Snil) break; - if (Scar(ls) == x) { - ls = Scdr(ls); - *pls = ls; - if (look) return !memqp(x, ls); - break; - } - pls = &Scdr(ls); - } - - /* must return 0 if we don't look for more */ - return 0; -} - -IBOOL Slocked_objectp(ptr x) { - seginfo *si; IGEN g; IBOOL ans; ptr ls; - - if (IMMEDIATE(x) || (si = MaybeSegInfo(ptr_get_segment(x))) == NULL || (g = si->generation) == static_generation) return 1; - - tc_mutex_acquire() - - ans = 0; - for (ls = S_G.locked_objects[g]; ls != Snil; ls = Scdr(ls)) { - if (x == Scar(ls)) { - ans = 1; - break; - } - } - - tc_mutex_release() - - return ans; -} - -ptr S_locked_objects(void) { - IGEN g; ptr ans; ptr ls; - - tc_mutex_acquire() - - ans = Snil; - for (g = 0; g <= static_generation; INCRGEN(g)) { - for (ls = S_G.locked_objects[g]; ls != Snil; ls = Scdr(ls)) { - ans = Scons(Scar(ls), ans); - } - } - - tc_mutex_release() - - return ans; -} - -void Slock_object(ptr x) { - seginfo *si; IGEN g; - - tc_mutex_acquire() - - /* weed out pointers that won't be relocated */ - if (!IMMEDIATE(x) && (si = MaybeSegInfo(ptr_get_segment(x))) != NULL && (g = si->generation) != static_generation) { - S_pants_down += 1; - /* add x to locked list. remove from unlocked list */ - S_G.locked_objects[g] = S_cons_in((g == 0 ? space_new : space_impure), g, x, S_G.locked_objects[g]); - if (S_G.enable_object_counts) { - if (g != 0) S_G.countof[g][countof_pair] += 1; - } - if (si->space & space_locked) - (void)remove_first_nomorep(x, &S_G.unlocked_objects[g], 0); - S_pants_down -= 1; - } - - tc_mutex_release() -} - -void Sunlock_object(ptr x) { - seginfo *si; IGEN g; - - tc_mutex_acquire() - - if (!IMMEDIATE(x) && (si = MaybeSegInfo(ptr_get_segment(x))) != NULL && (g = si->generation) != static_generation) { - S_pants_down += 1; - /* remove first occurrence of x from locked list. if there are no - others, add x to unlocked list */ - if (remove_first_nomorep(x, &S_G.locked_objects[g], si->space & space_locked)) { - S_G.unlocked_objects[g] = S_cons_in((g == 0 ? space_new : space_impure), g, x, S_G.unlocked_objects[g]); - if (S_G.enable_object_counts) { - if (g != 0) S_G.countof[g][countof_pair] += 1; - } - } - S_pants_down -= 1; - } - - tc_mutex_release() -} - -ptr s_help_unregister_guardian(ptr *pls, ptr tconc, ptr result) { - ptr rep, ls; - while ((ls = *pls) != Snil) { - if (GUARDIANTCONC(ls) == tconc) { - result = Scons(((rep = GUARDIANREP(ls)) == ftype_guardian_rep ? GUARDIANOBJ(ls) : rep), result); - *pls = ls = GUARDIANNEXT(ls); - } else { - ls = *(pls = &GUARDIANNEXT(ls)); - } - } - return result; -} - -ptr S_unregister_guardian(ptr tconc) { - ptr result, tc; IGEN g; - tc_mutex_acquire() - tc = get_thread_context(); - /* in the interest of thread safety, gather entries only in the current thread, ignoring any others */ - result = s_help_unregister_guardian(&GUARDIANENTRIES(tc), tconc, Snil); - /* plus, of course, any already known to the storage-management system */ - for (g = 0; g <= static_generation; INCRGEN(g)) { - result = s_help_unregister_guardian(&S_G.guardians[g], tconc, result); - } - tc_mutex_release() - return result; -} - -#ifndef WIN32 -void S_register_child_process(INT child) { - tc_mutex_acquire() - S_child_processes[0] = Scons(FIX(child), S_child_processes[0]); - tc_mutex_release() -} -#endif /* WIN32 */ - -IBOOL S_enable_object_counts(void) { - return S_G.enable_object_counts; -} - -void S_set_enable_object_counts(IBOOL eoc) { - S_G.enable_object_counts = eoc; -} - -ptr S_object_counts(void) { - IGEN grtd, g; ptr ls; iptr i; ptr outer_alist; - - tc_mutex_acquire() - - outer_alist = Snil; - - /* add rtds w/nonozero counts to the alist */ - for (grtd = 0; grtd <= static_generation; INCRGEN(grtd)) { - for (ls = S_G.rtds_with_counts[grtd]; ls != Snil; ls = Scdr(ls)) { - ptr rtd = Scar(ls); - ptr counts = RECORDDESCCOUNTS(rtd); - IGEN g; - uptr size = size_record_inst(UNFIX(RECORDDESCSIZE(rtd))); - ptr inner_alist = Snil; - - S_fixup_counts(counts); - for (g = 0; g <= static_generation; INCRGEN(g)) { - uptr count = RTDCOUNTSIT(counts, g); IGEN gcurrent = g; - if (g == S_G.new_max_nonstatic_generation) { - while (g < S_G.max_nonstatic_generation) { - g += 1; - count += RTDCOUNTSIT(counts, g); - } - } - if (count != 0) inner_alist = Scons(Scons((gcurrent == static_generation ? S_G.static_id : FIX(gcurrent)), Scons(Sunsigned(count), Sunsigned(count * size))), inner_alist); - } - if (inner_alist != Snil) outer_alist = Scons(Scons(rtd, inner_alist), outer_alist); - } - } - - /* add primary types w/nonozero counts to the alist */ - for (i = 0 ; i < countof_types; i += 1) { - ptr inner_alist = Snil; - for (g = 0; g <= static_generation; INCRGEN(g)) { - IGEN gcurrent = g; - uptr count = S_G.countof[g][i]; - uptr bytes = S_G.bytesof[g][i]; - - if (g == S_G.new_max_nonstatic_generation) { - while (g < S_G.max_nonstatic_generation) { - g += 1; - /* NB: S_G.max_nonstatic_generation + 1 <= static_generation, but coverity complains about overrun */ - /* coverity[overrun-buffer-val] */ - count += S_G.countof[g][i]; - /* coverity[overrun-buffer-val] */ - bytes += S_G.bytesof[g][i]; - } - } - - if (count != 0) { - if (bytes == 0) bytes = count * S_G.countof_size[i]; - inner_alist = Scons(Scons((gcurrent == static_generation ? S_G.static_id : FIX(gcurrent)), Scons(Sunsigned(count), Sunsigned(bytes))), inner_alist); - } - } - if (inner_alist != Snil) outer_alist = Scons(Scons(Svector_ref(S_G.countof_names, i), inner_alist), outer_alist); - } - - tc_mutex_release() - - return outer_alist; -} - -/* Scompact_heap(). Compact into as few O/S chunks as possible and - * move objects into static generation - */ -void Scompact_heap(void) { - ptr tc = get_thread_context(); - S_pants_down += 1; - S_gc_oce(tc, S_G.max_nonstatic_generation, static_generation, static_generation); - S_pants_down -= 1; -} - -/* S_check_heap checks for various kinds of heap consistency - It currently checks for: - dangling references in space_impure (generation > 0) and space_pure - extra dirty bits - missing dirty bits - - Some additional things it should check for but doesn't: - correct dirty bytes, following sweep_dirty conventions - dangling references in in space_code and space_continuation - dirty bits set for non-impure segments outside of generation zero - proper chaining of segments of a space and generation: - chains contain all and only the appropriate segments - - If noisy is nonzero, additional comments may be included in the output -*/ - -static void segment_tell(uptr seg) { - seginfo *si; - ISPC s, s1; - static char *spacename[max_space+1] = { alloc_space_names }; - - printf("segment %#tx", (ptrdiff_t)seg); - if ((si = MaybeSegInfo(seg)) == NULL) { - printf(" out of heap bounds\n"); - } else { - printf(" generation=%d", si->generation); - s = si->space; - s1 = si->space & ~(space_old|space_locked); - if (s1 < 0 || s1 > max_space) - printf(" space-bogus (%d)", s); - else { - printf(" space-%s", spacename[s1]); - if (s & space_old) printf(" oldspace"); - if (s & space_locked) printf(" locked"); - } - printf("\n"); - } - fflush(stdout); -} - -void S_ptr_tell(ptr p) { - segment_tell(ptr_get_segment(p)); -} - -void S_addr_tell(ptr p) { - segment_tell(addr_get_segment(p)); -} - -static void check_heap_dirty_msg(char *msg, ptr *x) { - INT d; seginfo *si; - - si = SegInfo(addr_get_segment(x)); - d = (INT)(((uptr)x >> card_offset_bits) & ((1 << segment_card_offset_bits) - 1)); - printf("%s dirty byte %d found in segment %#tx, card %d at %#tx\n", msg, si->dirty_bytes[d], (ptrdiff_t)(si->number), d, (ptrdiff_t)x); - printf("from "); segment_tell(addr_get_segment(x)); - printf("to "); segment_tell(addr_get_segment(*x)); -} - -void S_check_heap(IBOOL aftergc) { - uptr seg; INT d; ISPC s; IGEN g; IDIRTYBYTE dirty; IBOOL found_eos; IGEN pg; - ptr p, *pp1, *pp2, *nl; - iptr i; - uptr empty_segments = 0; - uptr used_segments = 0; - uptr static_segments = 0; - uptr nonstatic_segments = 0; - - check_dirty(); - - for (i = PARTIAL_CHUNK_POOLS; i >= -1; i -= 1) { - chunkinfo *chunk = i == -1 ? S_chunks_full : S_chunks[i]; - while (chunk != NULL) { - seginfo *si = chunk->unused_segs; - iptr count = 0; - while(si) { - count += 1; - if (si->space != space_empty) { - S_checkheap_errors += 1; - printf("!!! unused segment has unexpected space\n"); - } - si = si->next; - } - if ((chunk->segs - count) != chunk->nused_segs) { - S_checkheap_errors += 1; - printf("!!! unexpected used segs count %td with %td total segs and %td segs on the unused list\n", - (ptrdiff_t)chunk->nused_segs, (ptrdiff_t)chunk->segs, (ptrdiff_t)count); - } - used_segments += chunk->nused_segs; - empty_segments += count; - chunk = chunk->next; - } - } - - for (s = 0; s <= max_real_space; s += 1) { - seginfo *si; - for (g = 0; g <= S_G.max_nonstatic_generation; INCRGEN(g)) { - for (si = S_G.occupied_segments[g][s]; si != NULL; si = si->next) { - nonstatic_segments += 1; - } - } - for (si = S_G.occupied_segments[static_generation][s]; si != NULL; si = si->next) { - static_segments += 1; - } - } - - if (used_segments != nonstatic_segments + static_segments) { - S_checkheap_errors += 1; - printf("!!! found %#tx used segments and %#tx occupied segments\n", - (ptrdiff_t)used_segments, - (ptrdiff_t)(nonstatic_segments + static_segments)); - } - - if (S_G.number_of_nonstatic_segments != nonstatic_segments) { - S_checkheap_errors += 1; - printf("!!! S_G.number_of_nonstatic_segments %#tx is different from occupied number %#tx\n", - (ptrdiff_t)S_G.number_of_nonstatic_segments, - (ptrdiff_t)nonstatic_segments); - } - - if (S_G.number_of_empty_segments != empty_segments) { - S_checkheap_errors += 1; - printf("!!! S_G.number_of_empty_segments %#tx is different from unused number %#tx\n", - (ptrdiff_t)S_G.number_of_empty_segments, - (ptrdiff_t)empty_segments); - } - - for (i = PARTIAL_CHUNK_POOLS; i >= -1; i -= 1) { - chunkinfo *chunk = i == -1 ? S_chunks_full : S_chunks[i]; - while (chunk != NULL) { - uptr nsegs; seginfo *si; - for (si = &chunk->sis[0], nsegs = chunk->segs; nsegs != 0; nsegs -= 1, si += 1) { - seginfo *recorded_si; uptr recorded_seg; - if ((seg = si->number) != (recorded_seg = (chunk->base + chunk->segs - nsegs))) { - S_checkheap_errors += 1; - printf("!!! recorded segment number %#tx differs from actual segment number %#tx", (ptrdiff_t)seg, (ptrdiff_t)recorded_seg); - } - if ((recorded_si = SegInfo(seg)) != si) { - S_checkheap_errors += 1; - printf("!!! recorded segment %#tx seginfo %#tx differs from actual seginfo %#tx", (ptrdiff_t)seg, (ptrdiff_t)recorded_si, (ptrdiff_t)si); - } - s = si->space; - g = si->generation; - - if (s == space_new) { - if (g != 0) { - S_checkheap_errors += 1; - printf("!!! unexpected generation %d segment %#tx in space_new\n", g, (ptrdiff_t)seg); - } - } else if (s == space_impure || s == space_symbol || s == space_pure || s == space_weakpair /* || s == space_ephemeron */) { - /* out of date: doesn't handle space_port, space_continuation, space_code, space_pure_typed_object, space_impure_record */ - nl = (ptr *)S_G.next_loc[g][s]; - - /* check for dangling references */ - pp1 = (ptr *)build_ptr(seg, 0); - pp2 = (ptr *)build_ptr(seg + 1, 0); - if (pp1 <= nl && nl < pp2) pp2 = nl; - - while (pp1 != pp2) { - seginfo *psi; ISPC ps; - p = *pp1; - if (p == forward_marker) break; - if (!IMMEDIATE(p) && (psi = MaybeSegInfo(ptr_get_segment(p))) != NULL && ((ps = psi->space) & space_old || ps == space_empty)) { - S_checkheap_errors += 1; - printf("!!! dangling reference at %#tx to %#tx\n", (ptrdiff_t)pp1, (ptrdiff_t)p); - printf("from: "); segment_tell(seg); - printf("to: "); segment_tell(ptr_get_segment(p)); - } - pp1 += 1; - } - - /* verify that dirty bits are set appropriately */ - /* out of date: doesn't handle space_impure_record, space_port, and maybe others */ - /* also doesn't check the SYMCODE for symbols */ - if (s == space_impure || s == space_symbol || s == space_weakpair /* || s == space_ephemeron */) { - found_eos = 0; - pp2 = pp1 = build_ptr(seg, 0); - for (d = 0; d < cards_per_segment; d += 1) { - if (found_eos) { - if (si->dirty_bytes[d] != 0xff) { - S_checkheap_errors += 1; - printf("!!! Dirty byte set past end-of-segment for segment %#tx, card %d\n", (ptrdiff_t)seg, d); - segment_tell(seg); - } - continue; - } - - pp2 += bytes_per_card / sizeof(ptr); - if (pp1 <= nl && nl < pp2) { - found_eos = 1; - pp2 = nl; - } - -#ifdef DEBUG - printf("pp1 = %#tx, pp2 = %#tx, nl = %#tx\n", (ptrdiff_t)pp1, (ptrdiff_t)pp2, (ptrdiff_t)nl); - fflush(stdout); -#endif - - dirty = 0xff; - while (pp1 != pp2) { - seginfo *psi; - p = *pp1; - - if (p == forward_marker) { - found_eos = 1; - break; - } - if (!IMMEDIATE(p) && (psi = MaybeSegInfo(ptr_get_segment(p))) != NULL && (pg = psi->generation) < g) { - if (pg < dirty) dirty = pg; - if (si->dirty_bytes[d] > pg) { - S_checkheap_errors += 1; - check_heap_dirty_msg("!!! INVALID", pp1); - } - else if (checkheap_noisy) - check_heap_dirty_msg("... ", pp1); - } - pp1 += 1; - } - if (checkheap_noisy && si->dirty_bytes[d] < dirty) { - /* sweep_dirty won't sweep, and update dirty byte, for - cards with dirty pointers to segments older than the - maximum copied generation, so we can get legitimate - conservative dirty bytes even after gc */ - printf("... Conservative dirty byte %x (%x) %sfor segment %#tx card %d ", - si->dirty_bytes[d], dirty, - (aftergc ? "after gc " : ""), - (ptrdiff_t)seg, d); - segment_tell(seg); - } - } - } - } - if (aftergc && s != space_empty && !(s & space_locked) && (g == 0 || (s != space_impure && s != space_symbol && s != space_port && s != space_weakpair && s != space_ephemeron && s != space_impure_record))) { - for (d = 0; d < cards_per_segment; d += 1) { - if (si->dirty_bytes[d] != 0xff) { - S_checkheap_errors += 1; - printf("!!! Unnecessary dirty byte %x (%x) after gc for segment %#tx card %d ", - si->dirty_bytes[d], 0xff, (ptrdiff_t)(si->number), d); - segment_tell(seg); - } - } - } - } - chunk = chunk->next; - } - } -} - -static IBOOL dirty_listedp(seginfo *x, IGEN from_g, IGEN to_g) { - seginfo *si = DirtySegments(from_g, to_g); - while (si != NULL) { - if (si == x) return 1; - si = si->dirty_next; - } - return 0; -} - -static void check_dirty_space(ISPC s) { - IGEN from_g, to_g, min_to_g; INT d; seginfo *si; - - for (from_g = 0; from_g <= static_generation; from_g += 1) { - for (si = S_G.occupied_segments[from_g][s]; si != NULL; si = si->next) { - if (si->space & space_locked) continue; - min_to_g = 0xff; - for (d = 0; d < cards_per_segment; d += 1) { - to_g = si->dirty_bytes[d]; - if (to_g != 0xff) { - if (to_g < min_to_g) min_to_g = to_g; - if (from_g == 0) { - S_checkheap_errors += 1; - printf("!!! (check_dirty): space %d, generation %d segment %#tx card %d is marked dirty\n", s, from_g, (ptrdiff_t)(si->number), d); - } - } - } - if (min_to_g != si->min_dirty_byte) { - S_checkheap_errors += 1; - printf("!!! (check_dirty): space %d, generation %d segment %#tx min_dirty_byte is %d while actual min is %d\n", s, from_g, (ptrdiff_t)(si->number), si->min_dirty_byte, min_to_g); - segment_tell(si->number); - } else if (min_to_g != 0xff) { - if (!dirty_listedp(si, from_g, min_to_g)) { - S_checkheap_errors += 1; - printf("!!! (check_dirty): space %d, generation %d segment %#tx is marked dirty but not in dirty-segment list\n", s, from_g, (ptrdiff_t)(si->number)); - segment_tell(si->number); - } - } - } - } -} - -static void check_dirty(void) { - IGEN from_g, to_g; seginfo *si; - - for (from_g = 1; from_g <= static_generation; from_g = from_g == S_G.max_nonstatic_generation ? static_generation : from_g + 1) { - for (to_g = 0; (from_g == static_generation) ? (to_g <= S_G.max_nonstatic_generation) : (to_g < from_g); to_g += 1) { - si = DirtySegments(from_g, to_g); - if (from_g > S_G.max_nonstatic_generation && from_g != static_generation) { - if (si != NULL) { - S_checkheap_errors += 1; - printf("!!! (check_dirty): unexpected nonempty from-generation %d, to-generation %d dirty segment list\n", from_g, to_g); - } - } else { - while (si != NULL) { - ISPC s = si->space & ~space_locked; - IGEN g = si->generation; - IGEN mingval = si->min_dirty_byte; - if (g != from_g) { - S_checkheap_errors += 1; - printf("!!! (check_dirty): generation %d segment %#tx in %d -> %d dirty list\n", g, (ptrdiff_t)(si->number), from_g, to_g); - } - if (mingval != to_g) { - S_checkheap_errors += 1; - printf("!!! (check_dirty): dirty byte = %d for segment %#tx in %d -> %d dirty list\n", mingval, (ptrdiff_t)(si->number), from_g, to_g); - } - if (s != space_new && s != space_impure && s != space_symbol && s != space_port && s != space_impure_record && s != space_weakpair && s != space_ephemeron) { - S_checkheap_errors += 1; - printf("!!! (check_dirty): unexpected space %d for dirty segment %#tx\n", s, (ptrdiff_t)(si->number)); - } - si = si->dirty_next; - } - } - } - } - - check_dirty_space(space_impure); - check_dirty_space(space_symbol); - check_dirty_space(space_port); - check_dirty_space(space_impure_record); - check_dirty_space(space_weakpair); - check_dirty_space(space_ephemeron); - - fflush(stdout); -} - -void S_fixup_counts(ptr counts) { - IGEN g; U64 timestamp; - - timestamp = RTDCOUNTSTIMESTAMP(counts); - for (g = 0; g <= static_generation; INCRGEN(g)) { - if (timestamp >= S_G.gctimestamp[g]) break; - RTDCOUNTSIT(counts, g) = 0; - } - RTDCOUNTSTIMESTAMP(counts) = S_G.gctimestamp[0]; -} - -void S_do_gc(IGEN max_cg, IGEN min_tg, IGEN max_tg) { - ptr tc = get_thread_context(); - ptr code; - - code = CP(tc); - if (Sprocedurep(code)) code = CLOSCODE(code); - Slock_object(code); - - /* Scheme side grabs mutex before calling S_do_gc */ - S_pants_down += 1; - - if (S_G.new_max_nonstatic_generation > S_G.max_nonstatic_generation) { - S_G.min_free_gen = S_G.new_min_free_gen; - S_G.max_nonstatic_generation = S_G.new_max_nonstatic_generation; - } - - if (max_tg == max_cg && max_cg == S_G.new_max_nonstatic_generation && max_cg < S_G.max_nonstatic_generation) { - IGEN new_g, old_g, from_g, to_g; ISPC s; seginfo *si, *nextsi, *tail; - /* reducing max_nonstatic_generation */ - new_g = S_G.new_max_nonstatic_generation; - old_g = S_G.max_nonstatic_generation; - /* first, collect everything to old_g, ignoring min_tg */ - S_gc(tc, old_g, old_g, old_g); - /* now transfer old_g info to new_g, and clear old_g info */ - S_G.bytes_of_generation[new_g] = S_G.bytes_of_generation[old_g]; S_G.bytes_of_generation[old_g] = 0; - for (s = 0; s <= max_real_space; s += 1) { - S_G.first_loc[new_g][s] = S_G.first_loc[old_g][s]; S_G.first_loc[old_g][s] = FIX(0); - S_G.base_loc[new_g][s] = S_G.base_loc[old_g][s]; S_G.base_loc[old_g][s] = FIX(0); - S_G.next_loc[new_g][s] = S_G.next_loc[old_g][s]; S_G.next_loc[old_g][s] = FIX(0); - S_G.bytes_left[new_g][s] = S_G.bytes_left[old_g][s]; S_G.bytes_left[old_g][s] = 0; - S_G.bytes_of_space[new_g][s] = S_G.bytes_of_space[old_g][s]; S_G.bytes_of_space[old_g][s] = 0; - S_G.occupied_segments[new_g][s] = S_G.occupied_segments[old_g][s]; S_G.occupied_segments[old_g][s] = NULL; - for (si = S_G.occupied_segments[new_g][s]; si != NULL; si = si->next) { - si->generation = new_g; - } - } - S_G.guardians[new_g] = S_G.guardians[old_g]; S_G.guardians[old_g] = Snil; - S_G.locked_objects[new_g] = S_G.locked_objects[old_g]; S_G.locked_objects[old_g] = Snil; - S_G.unlocked_objects[new_g] = S_G.unlocked_objects[old_g]; S_G.unlocked_objects[old_g] = Snil; - S_G.buckets_of_generation[new_g] = S_G.buckets_of_generation[old_g]; S_G.buckets_of_generation[old_g] = NULL; - if (S_G.enable_object_counts) { - INT i; ptr ls; - for (i = 0; i < countof_types; i += 1) { - S_G.countof[new_g][i] = S_G.countof[old_g][i]; S_G.countof[old_g][i] = 0; - S_G.bytesof[new_g][i] = S_G.bytesof[old_g][i]; S_G.bytesof[old_g][i] = 0; - } - S_G.rtds_with_counts[new_g] = S_G.rtds_with_counts[old_g]; S_G.rtds_with_counts[old_g] = Snil; - for (ls = S_G.rtds_with_counts[new_g]; ls != Snil; ls = Scdr(ls)) { - ptr counts = RECORDDESCCOUNTS(Scar(ls)); - RTDCOUNTSIT(counts, new_g) = RTDCOUNTSIT(counts, old_g); RTDCOUNTSIT(counts, old_g) = 0; - } - for (ls = S_G.rtds_with_counts[static_generation]; ls != Snil; ls = Scdr(ls)) { - ptr counts = RECORDDESCCOUNTS(Scar(ls)); - RTDCOUNTSIT(counts, new_g) = RTDCOUNTSIT(counts, old_g); RTDCOUNTSIT(counts, old_g) = 0; - } - } -#ifndef WIN32 - S_child_processes[new_g] = S_child_processes[old_g]; -#endif - - /* change old_g dirty bytes in static generation to new_g; splice list of old_g - seginfos onto front of new_g seginfos */ - for (from_g = 1; from_g <= static_generation; INCRGEN(from_g)) { - for (to_g = 0; (from_g == static_generation) ? (to_g <= S_G.max_nonstatic_generation) : (to_g < from_g); to_g += 1) { - if ((si = DirtySegments(from_g, to_g)) != NULL) { - if (from_g == old_g) { - DirtySegments(from_g, to_g) = NULL; - DirtySegments(new_g, to_g) = si; - si->dirty_prev = &DirtySegments(new_g, to_g); - } else if (from_g == static_generation) { - if (to_g == old_g) { - DirtySegments(from_g, to_g) = NULL; - tail = DirtySegments(from_g, new_g); - DirtySegments(from_g, new_g) = si; - si->dirty_prev = &DirtySegments(from_g, new_g); - for (;;) { - INT d; - si->min_dirty_byte = new_g; - for (d = 0; d < cards_per_segment; d += 1) { - if (si->dirty_bytes[d] == old_g) si->dirty_bytes[d] = new_g; - } - nextsi = si->dirty_next; - if (nextsi == NULL) break; - si = nextsi; - } - if (tail != NULL) tail->dirty_prev = &si->dirty_next; - si->dirty_next = tail; - } else { - do { - INT d; - for (d = 0; d < cards_per_segment; d += 1) { - if (si->dirty_bytes[d] == old_g) si->dirty_bytes[d] = new_g; - } - si = si->dirty_next; - } while (si != NULL); - } - } else { - S_error_abort("S_do_gc(gc): unexpected nonempty dirty segment list"); - } - } - } - } - - /* tell profile_release_counters to scan only through new_g */ - if (S_G.prcgeneration == old_g) S_G.prcgeneration = new_g; - - /* finally reset max_nonstatic_generation */ - S_G.min_free_gen = S_G.new_min_free_gen; - S_G.max_nonstatic_generation = new_g; - } else { - S_gc(tc, max_cg, min_tg, max_tg); - } - - /* eagerly give collecting thread, the only one guaranteed to be - active, a fresh allocation area. the other threads have to trap - to get_more_room if and when they awake and try to allocate */ - S_reset_allocation_pointer(tc); - - S_pants_down -= 1; - - Sunlock_object(code); -} - - -void S_gc(ptr tc, IGEN max_cg, IGEN min_tg, IGEN max_tg) { - if (max_cg == 0 && min_tg == 1 && max_tg == 1 && S_G.locked_objects[0] == Snil) - S_gc_011(tc); - else if (max_tg == static_generation || S_G.enable_object_counts) - S_gc_oce(tc, max_cg, min_tg, max_tg); - else - S_gc_ocd(tc, max_cg, min_tg, max_tg); -} diff --git a/ta6ob/c/gcwrapper.o b/ta6ob/c/gcwrapper.o deleted file mode 100644 index cdc4f71..0000000 Binary files a/ta6ob/c/gcwrapper.o and /dev/null differ diff --git a/ta6ob/c/globals.h b/ta6ob/c/globals.h deleted file mode 100644 index f08c2b9..0000000 --- a/ta6ob/c/globals.h +++ /dev/null @@ -1,156 +0,0 @@ -/* globals.h - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* globals that do NOT need to be preserved in a saved heap. - * they must be initialized each time the system is brought up. */ - -/* gc.c */ -EXTERN IBOOL S_checkheap; -EXTERN uptr S_checkheap_errors; -#ifndef WIN32 -EXTERN ptr S_child_processes[static_generation+1]; -#endif /* WIN32 */ - -/* scheme.c */ -EXTERN IBOOL S_boot_time; -EXTERN IBOOL S_errors_to_console; -EXTERN ptr S_threads; -EXTERN uptr S_nthreads; -EXTERN uptr S_pagesize; -EXTERN void (*S_abnormal_exit_proc)(); -EXTERN char *Sschemeheapdirs; -EXTERN char *Sdefaultheapdirs; -#ifdef PTHREADS -EXTERN s_thread_key_t S_tc_key; -EXTERN scheme_mutex_t S_tc_mutex; -EXTERN s_thread_cond_t S_collect_cond; -EXTERN INT S_tc_mutex_depth; -#endif - -/* segment.c */ -#ifdef segment_t2_bits -#ifdef segment_t3_bits -EXTERN t2table *S_segment_info[1< -#include - -#ifdef FLUSHCACHE -oops, no S_flushcache_max_gap or S_doflush -#endif /* FLUSHCACHE */ - -void S_machine_init(void) {} diff --git a/ta6ob/c/i3le.o b/ta6ob/c/i3le.o deleted file mode 100644 index 3d62b44..0000000 Binary files a/ta6ob/c/i3le.o and /dev/null differ diff --git a/ta6ob/c/intern.c b/ta6ob/c/intern.c deleted file mode 100644 index 3758a3b..0000000 --- a/ta6ob/c/intern.c +++ /dev/null @@ -1,389 +0,0 @@ -/* intern.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" - -/* locally defined functions */ -static void oblist_insert(ptr sym, iptr idx, IGEN g); -static iptr hash(const unsigned char *s, iptr n); -static iptr hash_sc(const string_char *s, iptr n); -static iptr hash_uname(const string_char *s, iptr n); -static ptr mkstring(const string_char *s, iptr n); - -/* list of some primes to use for oblist sizes */ -#if (ptr_bits == 32) -static iptr oblist_lengths[] = { - 1031, - 2053, - 4099, - 8209, - 16411, - 32771, - 65537, - 131101, - 262147, - 524309, - 1048583, - 2097169, - 4194319, - 8388617, - 16777259, - 33554467, - 67108879, - 134217757, - 268435459, - 536870923, - 1073741827, - 0}; -#endif -#if (ptr_bits == 64) -static iptr oblist_lengths[] = { - 1031, - 2053, - 4099, - 8209, - 16411, - 32771, - 65537, - 131101, - 262147, - 524309, - 1048583, - 2097169, - 4194319, - 8388617, - 16777259, - 33554467, - 67108879, - 134217757, - 268435459, - 536870923, - 1073741827, - 2147483659, - 4294967311, - 8589934609, - 17179869209, - 34359738421, - 68719476767, - 137438953481, - 274877906951, - 549755813911, - 1099511627791, - 2199023255579, - 4398046511119, - 8796093022237, - 17592186044423, - 35184372088891, - 70368744177679, - 140737488355333, - 281474976710677, - 562949953421381, - 1125899906842679, - 2251799813685269, - 4503599627370517, - 9007199254740997, - 18014398509482143, - 36028797018963971, - 72057594037928017, - 144115188075855881, - 288230376151711813, - 576460752303423619, - 1152921504606847009, - 2305843009213693967, - 4611686018427388039, - 0}; -#endif - -void S_intern_init(void) { - IGEN g; - - if (!S_boot_time) return; - - S_G.oblist_length_pointer = &oblist_lengths[3]; - S_G.oblist_length = *S_G.oblist_length_pointer; - S_G.oblist_count = 0; - S_G.oblist = S_getmem(S_G.oblist_length * sizeof(bucket *), 1); - for (g = 0; g < static_generation; g += 1) S_G.buckets_of_generation[g] = NULL; -} - -static void oblist_insert(ptr sym, iptr idx, IGEN g) { - bucket *b, *oldb, **pb; - - find_room(g == 0 ? space_new : space_data, g, typemod, sizeof(bucket), b); - b->sym = sym; - if (g == 0) { - b->next = S_G.oblist[idx]; - S_G.oblist[idx] = b; - } else { - for (pb = &S_G.oblist[idx]; (oldb = *pb) != NULL && SegmentGeneration(addr_get_segment(oldb)) < g; pb = &oldb->next); - b->next = oldb; - *pb = b; - } - - if (g != static_generation) { - bucket_list *bl; - find_room(g == 0 ? space_new : space_data, g, typemod, sizeof(bucket_list), bl); - bl->car = b; - bl->cdr = S_G.buckets_of_generation[g]; - S_G.buckets_of_generation[g] = bl; - } - - S_G.oblist_count += 1; -} - -void S_resize_oblist(void) { - bucket **new_oblist, *b, *oldb, **pb, *bnext; - iptr *new_oblist_length_pointer, new_oblist_length, i, idx; - ptr sym; - IGEN g; - - new_oblist_length_pointer = S_G.oblist_length_pointer; - - if (S_G.oblist_count < S_G.oblist_length) { - while (new_oblist_length_pointer != &oblist_lengths[0] && *(new_oblist_length_pointer - 1) >= S_G.oblist_count) { - new_oblist_length_pointer -= 1; - } - } else if (S_G.oblist_count > S_G.oblist_length) { - while (*(new_oblist_length_pointer + 1) != 0 && *(new_oblist_length_pointer + 1) <= S_G.oblist_count) { - new_oblist_length_pointer += 1; - } - } - - if (new_oblist_length_pointer == S_G.oblist_length_pointer) return; - - new_oblist_length = *new_oblist_length_pointer; - new_oblist = S_getmem(new_oblist_length * sizeof(bucket *), 1); - - for (i = 0; i < S_G.oblist_length; i += 1) { - for (b = S_G.oblist[i]; b != NULL; b = bnext) { - bnext = b->next; - sym = b->sym; - idx = UNFIX(SYMHASH(sym)) % new_oblist_length; - g = GENERATION(sym); - - for (pb = &new_oblist[idx]; (oldb = *pb) != NULL && SegmentGeneration(addr_get_segment(oldb)) < g; pb = &oldb->next); - b->next = oldb; - *pb = b; - } - } - - S_freemem(S_G.oblist, S_G.oblist_length * sizeof(bucket *)); - S_G.bytesof[static_generation][countof_oblist] += (new_oblist_length - S_G.oblist_length) * sizeof(bucket *); - - S_G.oblist_length_pointer = new_oblist_length_pointer; - S_G.oblist_length = new_oblist_length; - S_G.oblist = new_oblist; -} - -/* hash function: multiplier weights each character, h = n factors in the length */ -#define multiplier 3 - -static iptr hash(const unsigned char *s, iptr n) { - iptr h = n + 401887359; - while (n--) h = h * multiplier + *s++; - return h & most_positive_fixnum; -} - -static iptr hash_sc(const string_char *s, iptr n) { - iptr h = n + 401887359; - while (n--) h = h * multiplier + Schar_value(*s++); - return h & most_positive_fixnum; -} - -static iptr hash_uname(const string_char *s, iptr n) { - /* attempting to get dissimilar hash codes for gensyms created in the same session */ - iptr i = n, h = 0; iptr pos = 1; int d, c; - - while (i-- > 0) { - if ((c = Schar_value(s[i])) == '-') { - if (pos <= 10) break; - return (h + 523658599) & most_positive_fixnum; - } - d = c - '0'; - if (d < 0 || d > 9) break; - h += d * pos; - pos *= 10; - } - - return hash_sc(s, n); -} - -static ptr mkstring(const string_char *s, iptr n) { - iptr i; - ptr str = S_string(NULL, n); - for (i = 0; i != n; i += 1) STRIT(str, i) = s[i]; - return str; -} - -/* handles single-byte characters, implicit length */ -ptr S_intern(const unsigned char *s) { - iptr n = strlen((const char *)s); - iptr hc = hash(s, n); - iptr idx = hc % S_G.oblist_length; - ptr sym; - bucket *b; - - tc_mutex_acquire() - - b = S_G.oblist[idx]; - while (b != NULL) { - sym = b->sym; - if (!GENSYMP(sym)) { - ptr str = SYMNAME(sym); - if (Sstring_length(str) == n) { - iptr i; - for (i = 0; ; i += 1) { - if (i == n) { - tc_mutex_release() - return sym; - } - if (Sstring_ref(str, i) != s[i]) break; - } - } - } - b = b->next; - } - - sym = S_symbol(S_string((const char *)s, n)); - INITSYMHASH(sym) = FIX(hc); - oblist_insert(sym, idx, 0); - - tc_mutex_release() - return sym; -} - -/* handles string_chars, explicit length */ -ptr S_intern_sc(const string_char *name, iptr n, ptr name_str) { - iptr hc = hash_sc(name, n); - iptr idx = hc % S_G.oblist_length; - ptr sym; - bucket *b; - - tc_mutex_acquire() - - b = S_G.oblist[idx]; - while (b != NULL) { - sym = b->sym; - if (!GENSYMP(sym)) { - ptr str = SYMNAME(sym); - if (Sstring_length(str) == n) { - iptr i; - for (i = 0; ; i += 1) { - if (i == n) { - tc_mutex_release() - return sym; - } - if (STRIT(str, i) != name[i]) break; - } - } - } - b = b->next; - } - - /* if (name_str == Sfalse) */ name_str = mkstring(name, n); - sym = S_symbol(name_str); - INITSYMHASH(sym) = FIX(hc); - oblist_insert(sym, idx, 0); - - tc_mutex_release() - return sym; -} - -ptr S_intern3(const string_char *pname, iptr plen, const string_char *uname, iptr ulen, ptr pname_str, ptr uname_str) { - iptr hc = hash_uname(uname, ulen); - iptr idx = hc % S_G.oblist_length; - ptr sym; - bucket *b; - - tc_mutex_acquire() - - b = S_G.oblist[idx]; - while (b != NULL) { - sym = b->sym; - if (GENSYMP(sym)) { - ptr str = Scar(SYMNAME(sym)); - if (Sstring_length(str) == ulen) { - iptr i; - for (i = 0; ; i += 1) { - if (i == ulen) { - tc_mutex_release() - return sym; - } - if (STRIT(str, i) != uname[i]) break; - } - } - } - b = b->next; - } - - if (pname_str == Sfalse) pname_str = mkstring(pname, plen); - if (uname_str == Sfalse) uname_str = mkstring(uname, ulen); - sym = S_symbol(Scons(uname_str, pname_str)); - INITSYMHASH(sym) = FIX(hc); - oblist_insert(sym, idx, 0); - - tc_mutex_release() - return sym; -} - -void S_intern_gensym(ptr sym) { - ptr uname_str = Scar(SYMNAME(sym)); - const string_char *uname = &STRIT(uname_str, 0); - iptr ulen = Sstring_length(uname_str); - iptr hc = hash_uname(uname, ulen); - iptr idx = hc % S_G.oblist_length; - bucket *b; - - tc_mutex_acquire() - - b = S_G.oblist[idx]; - while (b != NULL) { - ptr x = b->sym; - if (GENSYMP(x)) { - ptr str = Scar(SYMNAME(x)); - if (Sstring_length(str) == ulen) { - iptr i; - for (i = 0; ; i += 1) { - if (i == ulen) { - tc_mutex_release() - S_error1("intern-gensym", "unique name ~s already interned", uname_str); - } - if (Sstring_ref(str, i) != uname[i]) break; - } - } - } - b = b->next; - } - - INITSYMHASH(sym) = FIX(hc); - oblist_insert(sym, idx, GENERATION(sym)); - - tc_mutex_release() -} - -/* retrofit existing symbols once nonprocedure_code is available */ -void S_retrofit_nonprocedure_code(void) { - ptr npc, sym, val; bucket_list *bl; - - npc = S_G.nonprocedure_code; - - /* assuming this happens early, before collector has been called, so need look only for generation 0 symbols */ - for (bl = S_G.buckets_of_generation[0]; bl != NULL; bl = bl->cdr) { - sym = bl->car->sym; - val = SYMVAL(sym); - SETSYMCODE(sym, Sprocedurep(val) ? CLOSCODE(val) : npc); - } -} diff --git a/ta6ob/c/intern.o b/ta6ob/c/intern.o deleted file mode 100644 index 627da63..0000000 Binary files a/ta6ob/c/intern.o and /dev/null differ diff --git a/ta6ob/c/io.c b/ta6ob/c/io.c deleted file mode 100644 index 9c2eea6..0000000 --- a/ta6ob/c/io.c +++ /dev/null @@ -1,277 +0,0 @@ -/* io.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" -#include -#include -#include -#ifdef WIN32 -#include -#include -#pragma comment(lib, "shell32.lib") -#else /* WIN32 */ -#include -#include -#include -#endif /* WIN32 */ - -/* locally defined functions */ -#ifdef WIN32 -static ptr s_wstring_to_bytevector(const wchar_t *s); -#else -static ptr s_string_to_bytevector(const char *s); -#endif - -/* raises an exception if insufficient space cannot be malloc'd. - otherwise returns a freshly allocated version of inpath with ~ (home directory) - prefix expanded, if possible */ -char *S_malloc_pathname(const char *inpath) { - char *outpath; const char *ip; - -#ifdef WIN32 - if (*inpath == '~' && (*(ip = inpath + 1) == 0 || DIRMARKERP(*ip))) { - wchar_t* homew; - if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, &homew))) { - char *home = Swide_to_utf8(homew); - CoTaskMemFree(homew); - if (NULL != home) { - size_t n1, n2; - n1 = strlen(home); - n2 = strlen(ip) + 1; - if ((outpath = malloc(n1 + n2)) == NULL) { - free(home); - S_error("expand_pathname", "malloc failed"); - } - memcpy(outpath, home, n1); - memcpy(outpath + n1, ip, n2); - free(home); - return outpath; - } - } - } -#else /* WIN32 */ - if (*inpath == '~') { - const char *dir; size_t n1, n2; struct passwd *pwent; - if (*(ip = inpath + 1) == 0 || DIRMARKERP(*ip)) { - if ((dir = getenv("HOME")) == NULL) - if ((pwent = getpwuid(getuid())) != NULL) - dir = pwent->pw_dir; - } else { - char *userbuf; const char *user_start = ip; - do { ip += 1; } while (*ip != 0 && !DIRMARKERP(*ip)); - if ((userbuf = malloc(ip - user_start + 1)) == NULL) S_error("expand_pathname", "malloc failed"); - memcpy(userbuf, user_start, ip - user_start); - userbuf[ip - user_start] = 0; - dir = (pwent = getpwnam(userbuf)) != NULL ? pwent->pw_dir : NULL; - free(userbuf); - } - if (dir != NULL) { - n1 = strlen(dir); - n2 = strlen(ip) + 1; - if ((outpath = malloc(n1 + n2)) == NULL) S_error("expand_pathname", "malloc failed"); - memcpy(outpath, dir, n1); - memcpy(outpath + n1, ip, n2); - return outpath; - } - } -#endif /* WIN32 */ - - /* if no ~ or tilde dir can't be found, copy inpath */ - { - size_t n = strlen(inpath) + 1; - if ((outpath = (char *)malloc(n)) == NULL) S_error("expand_pathname", "malloc failed"); - memcpy(outpath, inpath, n); - return outpath; - } -} - -#ifdef WIN32 -wchar_t *S_malloc_wide_pathname(const char *inpath) { - char *path = S_malloc_pathname(inpath); - wchar_t *wpath = Sutf8_to_wide(path); - free(path); - return wpath; -} -#endif - -IBOOL S_fixedpathp(const char *inpath) { - char c; IBOOL res; char *path; - - path = S_malloc_pathname(inpath); - res = (c = *path) == 0 - || DIRMARKERP(c) -#ifdef WIN32 - || ((*(path + 1) == ':') && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) -#endif - || ((c == '.') - && ((c = *(path + 1)) == 0 - || DIRMARKERP(c) - || (c == '.' && ((c = *(path + 2)) == 0 || DIRMARKERP(c))))); - free(path); - return res; -} - -IBOOL S_file_existsp(const char *inpath, IBOOL followp) { -#ifdef WIN32 - wchar_t *wpath; IBOOL res; - WIN32_FILE_ATTRIBUTE_DATA filedata; - - if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { - return 0; - } else { - res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata); - free(wpath); - return res; - } -#else /* WIN32 */ - struct STATBUF statbuf; char *path; IBOOL res; - - path = S_malloc_pathname(inpath); - res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0; - free(path); - return res; -#endif /* WIN32 */ -} - -IBOOL S_file_regularp(const char *inpath, IBOOL followp) { -#ifdef WIN32 - wchar_t *wpath; IBOOL res; - WIN32_FILE_ATTRIBUTE_DATA filedata; - - if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { - return 0; - } else { - res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata) - && (filedata.dwFileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == 0; - free(wpath); - return res; - } -#else /* WIN32 */ - struct STATBUF statbuf; char *path; IBOOL res; - - path = S_malloc_pathname(inpath); - res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0 - && (statbuf.st_mode & S_IFMT) == S_IFREG; - free(path); - return res; -#endif /* WIN32 */ -} - -IBOOL S_file_directoryp(const char *inpath, IBOOL followp) { -#ifdef WIN32 - wchar_t *wpath; IBOOL res; - WIN32_FILE_ATTRIBUTE_DATA filedata; - - if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { - return 0; - } else { - res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata) - && filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; - free(wpath); - return res; - } -#else /* WIN32 */ - struct STATBUF statbuf; char *path; IBOOL res; - - path = S_malloc_pathname(inpath); - res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0 - && (statbuf.st_mode & S_IFMT) == S_IFDIR; - free(path); - return res; -#endif /* WIN32 */ -} - -IBOOL S_file_symbolic_linkp(const char *inpath) { -#ifdef WIN32 - wchar_t *wpath; IBOOL res; - WIN32_FILE_ATTRIBUTE_DATA filedata; - - if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { - return 0; - } else { - res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata) - && filedata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT; - free(wpath); - return res; - } -#else /* WIN32 */ - struct STATBUF statbuf; char *path; IBOOL res; - - path = S_malloc_pathname(inpath); - res = LSTAT(path, &statbuf) == 0 && (statbuf.st_mode & S_IFMT) == S_IFLNK; - free(path); - return res; -#endif /* WIN32 */ -} - -#ifdef WIN32 -static ptr s_wstring_to_bytevector(const wchar_t *s) { - iptr n; ptr bv; - if ((n = wcslen(s)) == 0) return S_G.null_bytevector; - n *= sizeof(wchar_t); - bv = S_bytevector(n); - memcpy(&BVIT(bv,0), s, n); - return bv; -} - -ptr S_find_files(const char *wildpath) { - wchar_t *wwildpath; - intptr_t handle; - struct _wfinddata_t fileinfo; - - if ((wwildpath = S_malloc_wide_pathname(wildpath)) == NULL) - return S_LastErrorString(); - - if ((handle = _wfindfirst(wwildpath, &fileinfo)) == (intptr_t)-1) { - free(wwildpath); - return S_strerror(errno); - } else { - ptr ls = Snil; - do { - ls = Scons(s_wstring_to_bytevector(fileinfo.name), ls); - } while (_wfindnext(handle, &fileinfo) == 0); - _findclose(handle); - free(wwildpath); - return ls; - } -} -#else /* WIN32 */ -static ptr s_string_to_bytevector(const char *s) { - iptr n; ptr bv; - if ((n = strlen(s)) == 0) return S_G.null_bytevector; - bv = S_bytevector(n); - memcpy(&BVIT(bv,0), s, n); - return bv; -} - -ptr S_directory_list(const char *inpath) { - char *path; DIR *dirp; - - path = S_malloc_pathname(inpath); - if ((dirp = opendir(path)) == (DIR *)0) { - free(path); - return S_strerror(errno); - } else { - struct dirent *dep; ptr ls = Snil; - - while ((dep = readdir(dirp)) != (struct dirent *)0) - ls = Scons(s_string_to_bytevector(dep->d_name), ls); - closedir(dirp); - free(path); - return ls; - } -} -#endif /* WIN32 */ diff --git a/ta6ob/c/io.o b/ta6ob/c/io.o deleted file mode 100644 index bcfd662..0000000 Binary files a/ta6ob/c/io.o and /dev/null differ diff --git a/ta6ob/c/itest.c b/ta6ob/c/itest.c deleted file mode 100644 index 21c1847..0000000 --- a/ta6ob/c/itest.c +++ /dev/null @@ -1,247 +0,0 @@ -/* itest.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define r_EOF 0 -#define r_LPAREN 1 -#define r_RPAREN 2 -#define r_CONST 3 - -static INT digit_value(ICHAR c, INT r) { - switch (r) { - case 2: - if ('0' <= c && c <= '1') return c - '0'; - break; - case 8: - if ('0' <= c && c <= '8') return c - '0'; - break; - case 10: - if ('0' <= c && c <= '9') return c - '0'; - break; - case 16: - if ('0' <= c && c <= '9') return c - '0'; - if ('a' <= c && c <= 'f') return c - 'a'; - if ('A' <= c && c <= 'F') return c - 'A'; - default: - break; - } - return -1; -} - -static INT read_int(ptr *v, ptr n, INT r, IBOOL sign) { - INT i, c; - - for (;;) { - if ((i = digit_value((c = getchar()), r)) == -1) { - ungetc(c, stdin); - break; - } - n = S_add(S_mul(n, FIX(r)), FIX(i)); - } - *v = sign ? S_sub(FIX(0), n) : n; - return r_CONST; -} - -static INT read_token(ptr *v) { - ICHAR c = getchar(); - switch (c) { - case SEOF: return r_EOF; - case '\n': - case ' ': return read_token(v); - case ';': - for (;;) { - switch (getchar()) { - case SEOF: - return r_EOF; - case '\n': - return read_token(v); - default: - break; - } - } - case '(': return r_LPAREN; - case ')': return r_RPAREN; - case '#': { - ICHAR c = getchar(); - INT r = 10; - switch (c) { - case 'x': - r = 16; - case 'o': - if (r == 0) r = 8; - case 'b': - if (r == 10) r = 2; - case 'd': { - INT i; - IBOOL sign = 0; - c = getchar(); - if (c == '+') - c = getchar(); - else if (c == '-') { - sign = 1; - c = getchar(); - } - - if ((i = digit_value(c, r)) != -1) - return read_int(v, FIX(i), r, sign); - } - default: - printf("malformed hash prefix ignored\n"); - return read_token(v); - } - } - case '+': - case '-': { - INT i, c2; - if ((i = digit_value((c2 = getchar()), 10)) == -1) { - ungetc(c2, stdin); - } else { - return read_int(v, FIX(i), 10, c == '-'); - } - } - case '*': - case '/': - case 'q': - case 'r': - case 'g': - case '=': - case '<': - case 'f': - case 'c': - case 'd': - *v = Schar(c); - return r_CONST; - default: { - INT i; - if ((i = digit_value(c, 10)) != -1) - return read_int(v, FIX(i), 10, 0); - } - break; - } - printf("invalid character %d ignored\n", c); - return read_token(v); -} - -static ptr readx(INT t, ptr v); - -static ptr read_list(void) { - INT t; ptr v, x; - - t = read_token(&v); - if (t == r_RPAREN) return Snil; - x = readx(t, v); - return Scons(x, read_list()); -} - -static ptr readx(INT t, ptr v) { - - switch (t) { - case r_EOF: - printf("unexpected EOF\n"); - exit(1); - case r_LPAREN: return read_list(); - case r_RPAREN: - printf("unexpected right paren ignored\n"); - t = read_token(&v); - return readx(t, v); - case r_CONST: return v; - default: - printf("invalid token %d\n", t); - exit(1); - } -} - -static ptr read_top(void) { - INT t; ptr v; - - t = read_token(&v); - switch (t) { - case r_EOF: return Seof_object; - case r_RPAREN: return read_top(); - default: return readx(t, v); - } -} - -static ptr eval(ptr x); - -#define First(x) eval(Scar(Scdr(x))) -#define Second(x) eval(Scar(Scdr(Scdr(x)))) - -static ptr eval(ptr x) { - if (Spairp(x)) { - switch (Schar_value(Scar(x))) { - case '+': return S_add(First(x), Second(x)); - case '-': return S_sub(First(x), Second(x)); - case '*': return S_mul(First(x), Second(x)); - case '/': return S_div(First(x), Second(x)); - case 'q': return S_trunc(First(x), Second(x)); - case 'r': return S_rem(First(x), Second(x)); - case 'g': return S_gcd(First(x), Second(x)); - case '=': { - ptr x1 = First(x), x2 = Second(x); - if (Sfixnump(x1) && Sfixnump(x2)) - return Sboolean(x1 == x2); - else if (Sbignump(x1) && Sbignump(x2)) - return Sboolean(S_big_eq(x1, x2)); - else return Sfalse; - } - case '<': { - ptr x1 = First(x), x2 = Second(x); - if (Sfixnump(x1)) - if (Sfixnump(x2)) - return Sboolean(x1 < x2); - else - return Sboolean(!BIGSIGN(x2)); - else - if (Sfixnump(x2)) - return Sboolean(BIGSIGN(x1)); - else - return Sboolean(S_big_lt(x1, x2)); - } - case 'f': return Sflonum(S_floatify(First(x))); - case 'c': - S_gc(get_thread_context(), UNFIX(First(x)),UNFIX(Second(x))); - return Svoid; - case 'd': return S_decode_float(Sflonum_value(First(x))); - default: - S_prin1(x); - putchar('\n'); - printf("unrecognized operator, returning zero\n"); - return FIX(0); - } - } else - return x; -} - -#undef PROMPT -#undef NOISY -static void bignum_test(void) { - ptr x; - for (;;) { -#ifdef PROMPT - putchar('*'); - putchar(' '); -#endif - x = read_top(); - if (x == Seof_object) { putchar('\n'); exit(0); } -#ifdef NOISY - S_prin1(x); - putchar('\n'); -#endif - x = eval(x); - S_prin1(x); - putchar('\n'); - } -} diff --git a/ta6ob/c/main.c b/ta6ob/c/main.c deleted file mode 100644 index de8c719..0000000 --- a/ta6ob/c/main.c +++ /dev/null @@ -1,376 +0,0 @@ -/* main.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include "scheme.h" -#include "config.h" - -/**** - CUSTOM_INIT may be defined as a function with the signature shown to - perform boot-time initialization, e.g., registering foreign symbols. -****/ -#ifndef CUSTOM_INIT -#define CUSTOM_INIT ((void (*)(void))0) -#endif /* CUSTOM_INIT */ - -/**** - ABNORMAL_EXIT may be defined as a function with the signature shown to - take some action, such as printing a special error message or performing - a nonlocal exit with longjmp, when the Scheme system exits abnormally, - i.e., when an unrecoverable error occurs. If left null, the default - is to call exit(1). -****/ -#ifndef ABNORMAL_EXIT -#define ABNORMAL_EXIT ((void (*)(void))0) -#endif /* ABNORMAL_EXIT */ - -#ifndef SCHEME_SCRIPT -#define SCHEME_SCRIPT "scheme-script" -#endif - -static const char *path_last(const char *p) { - const char *s; -#ifdef WIN32 - char c; - if ((c = *p) >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') - if (*(p + 1) == ':') - p += 2; - - for (s = p; *s != 0; s += 1) - if ((c = *s) == '/' || c == '\\') p = ++s; -#else /* WIN32 */ - for (s = p; *s != 0; s += 1) if (*s == '/') p = ++s; -#endif /* WIN32 */ - return p; -} - -#if defined(WIN32) && !defined(__MINGW32__) -#define GETENV Sgetenv -#define GETENV_FREE free -int wmain(int argc, wchar_t* wargv[], wchar_t* wenvp[]) { - const char** argv = (char**)malloc((argc + 1) * sizeof(char*)); - int i; - for (i = 0; i < argc; i++) { - wchar_t* warg = wargv[i]; - if (NULL == (argv[i] = Swide_to_utf8(warg))) { - fprintf_s(stderr, "Invalid argument: %S\n", warg); - exit(1); - } - } - argv[argc] = NULL; -#else /* WIN32 */ -#define GETENV getenv -#define GETENV_FREE (void) -int main(int argc, const char *argv[]) { -#endif /* WIN32 */ - int n, new_argc = 1; -#ifdef SAVEDHEAPS - int compact = 1, savefile_level = 0; - const char *savefile = (char *)0; -#endif /* SAVEDHEAPS */ - const char *execpath = argv[0]; - const char *scriptfile = (char *)0; - const char *programfile = (char *)0; - const char *libdirs = (char *)0; - const char *libexts = (char *)0; - int status; - const char *arg; - int quiet = 0; - int eoc = 0; - int optlevel = 0; - int debug_on_exception = 0; - int import_notify = 0; - int compile_imported_libraries = 0; -#ifdef FEATURE_EXPEDITOR - int expeditor_enable = 1; - const char *expeditor_history_file = ""; /* use "" for default location */ -#endif /* FEATURE_EXPEDITOR */ - - if (strcmp(Skernel_version(), VERSION) != 0) { - (void) fprintf(stderr, "unexpected shared library version %s for %s version %s\n", Skernel_version(), execpath, VERSION); - exit(1); - } - - Sscheme_init(ABNORMAL_EXIT); - - if (strcmp(path_last(execpath), SCHEME_SCRIPT) == 0) { - if (argc < 2) { - (void) fprintf(stderr,"%s requires program-path argument\n", execpath); - exit(1); - } - argv[0] = programfile = argv[1]; - n = 1; - while (++n < argc) argv[new_argc++] = argv[n]; - } else { - /* process command-line arguments, registering boot and heap files */ - for (n = 1; n < argc; n += 1) { - arg = argv[n]; - if (strcmp(arg,"--") == 0) { - while (++n < argc) argv[new_argc++] = argv[n]; - } else if (strcmp(arg,"-b") == 0 || strcmp(arg,"--boot") == 0) { - if (++n == argc) { - (void) fprintf(stderr,"%s requires argument\n", arg); - exit(1); - } - Sregister_boot_file(argv[n]); - } else if (strcmp(arg,"--eedisable") == 0) { - #ifdef FEATURE_EXPEDITOR - expeditor_enable = 0; - #endif /* FEATURE_EXPEDITOR */ - } else if (strcmp(arg,"--eehistory") == 0) { - if (++n == argc) { - (void) fprintf(stderr,"%s requires argument\n", arg); - exit(1); - } - #ifdef FEATURE_EXPEDITOR - if (strcmp(argv[n], "off") == 0) - expeditor_history_file = (char *)0; - else - expeditor_history_file = argv[n]; - #endif /* FEATURE_EXPEDITOR */ - } else if (strcmp(arg,"-q") == 0 || strcmp(arg,"--quiet") == 0) { - quiet = 1; - } else if (strcmp(arg,"--retain-static-relocation") == 0) { - Sretain_static_relocation(); - } else if (strcmp(arg,"--enable-object-counts") == 0) { - eoc = 1; -#ifdef SAVEDHEAPS - } else if (strcmp(arg,"-c") == 0 || strcmp(arg,"--compact") == 0) { - compact = !compact; - } else if (strcmp(arg,"-h") == 0 || strcmp(arg,"--heap") == 0) { - if (++n == argc) { - (void) fprintf(stderr,"%s requires argument\n", arg); - exit(1); - } - Sregister_heap_file(argv[n]); - } else if (strncmp(arg,"-s",2) == 0 && - (savefile_level = -2, - *(arg+2) == 0 || - *(arg+3) == 0 && - ((savefile_level = *(arg+2) - '+' - 1) == -1 || - (savefile_level = *(arg+2) - '0') >= 0 && - savefile_level <= 9)) || - strncmp(arg,"--saveheap",10) == 0 && - (savefile_level = -2, - *(arg+10) == 0 || - *(arg+11) == 0 && - ((savefile_level = *(arg+2) - '+' - 1) == -1 || - (savefile_level = *(arg+10) - '0') >= 0 && - savefile_level <= 9))) { - if (++n == argc) { - (void) fprintf(stderr,"%s requires argument\n", arg); - exit(1); - } - savefile = argv[n]; -#else /* SAVEDHEAPS */ - } else if (strcmp(arg,"-c") == 0 || strcmp(arg,"--compact") == 0) { - fprintf(stderr, "-c and --compact options are not presently supported\n"); - exit(1); - } else if (strcmp(arg,"-h") == 0 || strcmp(arg,"--heap") == 0) { - fprintf(stderr, "-h and --heap options are not presently supported\n"); - exit(1); - } else if (strncmp(arg,"-s",2) == 0 || strncmp(arg,"--saveheap",10) == 0) { - fprintf(stderr, "-s and --saveheap options are not presently supported\n"); - exit(1); -#endif /* SAVEDHEAPS */ - } else if (strcmp(arg,"--script") == 0) { - if (++n == argc) { - (void) fprintf(stderr,"%s requires argument\n", arg); - exit(1); - } - scriptfile = argv[n]; - while (++n < argc) argv[new_argc++] = argv[n]; - } else if (strcmp(arg,"--optimize-level") == 0) { - const char *nextarg; - if (++n == argc) { - (void) fprintf(stderr,"%s requires argument\n", arg); - exit(1); - } - nextarg = argv[n]; - if (strcmp(nextarg,"0") == 0) - optlevel = 0; - else if (strcmp(nextarg,"1") == 0) - optlevel = 1; - else if (strcmp(nextarg,"2") == 0) - optlevel = 2; - else if (strcmp(nextarg,"3") == 0) - optlevel = 3; - else { - (void) fprintf(stderr,"invalid optimize-level %s\n", nextarg); - exit(1); - } - } else if (strcmp(arg,"--debug-on-exception") == 0) { - debug_on_exception = 1; - } else if (strcmp(arg,"--import-notify") == 0) { - import_notify = 1; - } else if (strcmp(arg,"--libexts") == 0) { - if (++n == argc) { - (void) fprintf(stderr,"%s requires argument\n", arg); - exit(1); - } - libexts = argv[n]; - } else if (strcmp(arg,"--libdirs") == 0) { - if (++n == argc) { - (void) fprintf(stderr,"%s requires argument\n", arg); - exit(1); - } - libdirs = argv[n]; - } else if (strcmp(arg,"--compile-imported-libraries") == 0) { - compile_imported_libraries = 1; - } else if (strcmp(arg,"--program") == 0) { - if (++n == argc) { - (void) fprintf(stderr,"%s requires argument\n", arg); - exit(1); - } - programfile = argv[n]; - while (++n < argc) argv[new_argc++] = argv[n]; - } else if (strcmp(arg,"--help") == 0) { - fprintf(stderr,"usage: %s [options and files]\n", execpath); - fprintf(stderr,"options:\n"); - fprintf(stderr," -q, --quiet suppress greeting and prompt\n"); - fprintf(stderr," --script run as shell script\n"); - fprintf(stderr," --program run rnrs program as shell script\n"); -#ifdef WIN32 -#define sep ";" -#else -#define sep ":" -#endif - fprintf(stderr," --libdirs %s... set library directories\n", sep); - fprintf(stderr," --libexts %s... set library extensions\n", sep); - fprintf(stderr," --compile-imported-libraries compile libraries before loading\n"); - fprintf(stderr," --import-notify enable import search messages\n"); - fprintf(stderr," --optimize-level <0 | 1 | 2 | 3> set optimize-level\n"); - fprintf(stderr," --debug-on-exception on uncaught exception, call debug\n"); - fprintf(stderr," --eedisable disable expression editor\n"); - fprintf(stderr," --eehistory expression-editor history file\n"); - fprintf(stderr," --enable-object-counts have collector maintain object counts\n"); - fprintf(stderr," --retain-static-relocation keep reloc info for compute-size, etc.\n"); - fprintf(stderr," -b , --boot load boot file\n"); -// fprintf(stderr," -c, --compact toggle compaction flag\n"); -// fprintf(stderr," -h , --heap load heap file\n"); -// fprintf(stderr," -s[] , --saveheap[] save heap file\n"); - fprintf(stderr," --verbose trace boot/heap search process\n"); - fprintf(stderr," --version print version and exit\n"); - fprintf(stderr," --help print help and exit\n"); - fprintf(stderr," -- pass through remaining args\n"); - exit(0); - } else if (strcmp(arg,"--verbose") == 0) { - Sset_verbose(1); - } else if (strcmp(arg,"--version") == 0) { - fprintf(stderr,"%s\n", VERSION); - exit(0); - } else { - argv[new_argc++] = arg; - } - } - } - - /* must call Sbuild_heap after registering boot and heap files. - * Sbuild_heap() completes the initialization of the Scheme system - * and loads the boot or heap files. If no boot or heap files have - * been registered, the first argument to Sbuild_heap must be a - * non-null path string; in this case, Sbuild_heap looks for - * a heap or boot file named .boot, where is the last - * component of the path. If no heap files are loaded and - * CUSTOM_INIT is non-null, Sbuild_heap calls CUSTOM_INIT just - * prior to loading the boot file(s). */ - Sbuild_heap(execpath, CUSTOM_INIT); - -#define CALL0(who) Scall0(Stop_level_value(Sstring_to_symbol(who))) -#define CALL1(who, arg) Scall1(Stop_level_value(Sstring_to_symbol(who)), arg) -#ifdef FunCRepl - { - ptr p; - - for (;;) { - CALL1("display", Sstring("* ")); - p = CALL0("read"); - if (Seof_objectp(p)) break; - p = CALL1("eval", p); - if (p != Svoid) CALL1("pretty-print", p); - } - CALL0("newline"); - status = 0; - } -#else /* FunCRepl */ - if (quiet) { - CALL1("suppress-greeting", Strue); - CALL1("waiter-prompt-string", Sstring("")); - } - if (eoc) { - CALL1("enable-object-counts", Strue); - } - if (optlevel != 0) { - CALL1("optimize-level", Sinteger(optlevel)); - } - if (debug_on_exception != 0) { - CALL1("debug-on-exception", Strue); - } - if (import_notify != 0) { - CALL1("import-notify", Strue); - } - if (libdirs == 0) { - char *cslibdirs = GETENV("CHEZSCHEMELIBDIRS"); - if (cslibdirs != 0) { - CALL1("library-directories", Sstring_utf8(cslibdirs, -1)); - GETENV_FREE(cslibdirs); - } - } else { - CALL1("library-directories", Sstring_utf8(libdirs, -1)); - } - if (libexts == 0) { - char *cslibexts = GETENV("CHEZSCHEMELIBEXTS"); - if (cslibexts != 0) { - CALL1("library-extensions", Sstring_utf8(cslibexts, -1)); - GETENV_FREE(cslibexts); - } - } else { - CALL1("library-extensions", Sstring_utf8(libexts, -1)); - } - if (compile_imported_libraries != 0) { - CALL1("compile-imported-libraries", Strue); - } -#ifdef FEATURE_EXPEDITOR - /* Senable_expeditor must be called before Scheme_start/Scheme_script (if at all) */ - if (!quiet && expeditor_enable) Senable_expeditor(expeditor_history_file); -#endif /* FEATURE_EXPEDITOR */ - - if (scriptfile != (char *)0) - /* Sscheme_script invokes the value of the scheme-script parameter */ - status = Sscheme_script(scriptfile, new_argc, argv); - else if (programfile != (char *)0) - /* Sscheme_program invokes the value of the scheme-program parameter */ - status = Sscheme_program(programfile, new_argc, argv); - else { - /* Sscheme_start invokes the value of the scheme-start parameter */ - status = Sscheme_start(new_argc, argv); - } -#endif /* FunCRepl */ - -#ifdef SAVEDHEAPS - if (status == 0 && savefile != (char *)0) { - if (compact) Scompact_heap(); - Ssave_heap(savefile, savefile_level); - } -#endif /* SAVEDHEAPS */ - - /* must call Scheme_deinit after saving the heap and before exiting */ - Sscheme_deinit(); - - exit(status); -} diff --git a/ta6ob/c/main.o b/ta6ob/c/main.o deleted file mode 100644 index 5255463..0000000 Binary files a/ta6ob/c/main.o and /dev/null differ diff --git a/ta6ob/c/new-io.c b/ta6ob/c/new-io.c deleted file mode 100644 index cbd2799..0000000 --- a/ta6ob/c/new-io.c +++ /dev/null @@ -1,970 +0,0 @@ -/* new-io.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" -#include -#include -#include -#ifdef WIN32 -#include -#else /* WIN32 */ -#include -#include -#include -#endif /* WIN32 */ -#include -#include "zlib.h" -#include "lz4.h" -#include "lz4hc.h" - -/* !!! UNLESS you enjoy spending endless days tracking down race conditions - !!! involving the garbage collector, please note: DEACTIVATE and - !!! REACTIVATE or LOCKandDEACTIVATE and REACTIVATEandLOCK should be used - !!! around operations that can block. While deactivated, the process - !!! MUST NOT touch any unlocked Scheme objects (ptrs) or allocate any - !!! new Scheme objects. It helps to bracket only small pieces of code - !!! with DEACTIVATE/REACTIVATE or LOCKandDEACTIVATE/REACTIVATE_and_LOCK. */ -#ifdef PTHREADS -/* assume the scheme wrapper has us in a critical section */ -#define DEACTIVATE(tc) if (DISABLECOUNT(tc) == FIX(1)) { deactivate_thread(tc); } -#define REACTIVATE(tc) if (DISABLECOUNT(tc) == FIX(1)) { reactivate_thread(tc); } -#define LOCKandDEACTIVATE(tc,bv) if (DISABLECOUNT(tc) == FIX(1)) { Slock_object(bv); deactivate_thread(tc); } -#define REACTIVATEandUNLOCK(tc,bv) if (DISABLECOUNT(tc) == FIX(1)) { reactivate_thread(tc); Sunlock_object(bv); } -#else /* PTHREADS */ -#define DEACTIVATE(tc) -#define REACTIVATE(tc) -#define LOCKandDEACTIVATE(tc,bv) -#define REACTIVATEandUNLOCK(tc,bv) -#endif /* PTHREADS */ - -/* locally defined functions */ -static ptr new_open_output_fd_helper(const char *filename, INT mode, - INT flags, INT no_create, INT no_fail, INT no_truncate, - INT append, INT lock, INT replace, INT compressed); -static INT lockfile(INT fd); -static int is_valid_zlib_length(iptr count); -static int is_valid_lz4_length(iptr count); - -/* - not_ok_is_fatal: !ok definitely implies error, so ignore glzerror - ok: whether the result of body seems to be ok - flag: will be set when an error is detected and cleared if no error - fd: the glzFile object to call glzerror on - body: the operation we are checking the error on -*/ -#ifdef EINTR -/* like FD_EINTR_GUARD and GZ_EINTR_GUARD but ignores EINTR. - used for calls to close so we don't close a file descriptor that - might already have been reallocated by a different thread */ -#define FD_GUARD(ok,flag,body) \ - do { body; \ - flag = !(ok) && errno != EINTR; \ - } while (0) -#define GZ_GUARD(not_ok_is_fatal,ok,flag,fd,body) \ - do { body; \ - if (ok) { flag = 0; } \ - else { \ - INT errnum; \ - S_glzerror((fd),&errnum); \ - S_glzclearerr((fd)); \ - if (errnum == Z_ERRNO) { \ - flag = errno != EINTR; \ - } else { \ - flag = not_ok_is_fatal || errnum != Z_OK; \ - errno = 0; \ - } \ - } \ - } while (0) -/* like FD_GUARD and GZ_GUARD but spins on EINTR */ -#define FD_EINTR_GUARD(ok,flag,body) \ - do { body; \ - if (ok) { flag = 0; break; } \ - else if (errno != EINTR) { flag = 1; break; } \ - } while (1) -#define GZ_EINTR_GUARD(not_ok_is_fatal,ok,flag,fd,body) \ - do { body; \ - if (ok) { flag = 0; break; } \ - else { \ - INT errnum; \ - S_glzerror((fd),&errnum); \ - S_glzclearerr((fd)); \ - if (errnum == Z_ERRNO) { \ - if (errno != EINTR) { flag = 1; break; } \ - } else { \ - flag = not_ok_is_fatal || errnum != Z_OK; \ - errno = 0; \ - break; \ - } \ - } \ - } while (1) -#else /* EINTR */ -#define FD_GUARD(ok,flag,body) do { body; flag = !(ok); } while (0) -#define GZ_GUARD(not_ok_is_fatal,ok,flag,fd,body) \ - do { body; \ - if (ok) { flag = 0; } \ - else { \ - INT errnum; \ - S_glzerror((fd),&errnum); \ - S_glzclearerr((fd)); \ - if (errnum == Z_ERRNO) { flag = 1; } \ - else { \ - flag = not_ok_is_fatal || errnum != Z_OK; \ - errno = 0; \ - } \ - } \ - } while (0) -#define FD_EINTR_GUARD FD_GUARD -#define GZ_EINTR_GUARD GZ_GUARD -#endif /* EINTR */ - -#ifndef O_BINARY -#define O_BINARY 0 -#endif /* O_BINARY */ - - -/* These functions are intended for use immediately upon opening - * (lockfile) fd. They need to be redesigned for general-purpose - * locking. */ -#ifdef FLOCK -static INT lockfile(INT fd) { return FLOCK(fd, LOCK_EX); } -#endif -#ifdef LOCKF -static INT lockfile(INT fd) { return lockf(fd, F_LOCK, (off_t)0); } -#endif - -#define MAKE_GZXFILE(x) Sinteger((iptr)x) -#define GZXFILE_GZFILE(x) ((glzFile)Sinteger_value(x)) - -INT S_gzxfile_fd(ptr x) { - return GZXFILE_GZFILE(x)->fd; -} - -glzFile S_gzxfile_gzfile(ptr x) { - return GZXFILE_GZFILE(x); -} - -ptr S_new_open_input_fd(const char *infilename, IBOOL compressed) { - char *filename; - INT saved_errno = 0; - INT fd, dupfd, error, result, ok, flag; - glzFile file; -#ifdef PTHREADS - ptr tc = get_thread_context(); -#endif - - filename = S_malloc_pathname(infilename); - - /* NB: don't use infilename, which might point into a Scheme string, after this point */ - DEACTIVATE(tc) - FD_EINTR_GUARD(fd>=0, error, fd=OPEN(filename,O_BINARY|O_RDONLY,0)); - saved_errno = errno; - REACTIVATE(tc) - - /* NB: don't use free'd filename after this point */ - free(filename); - - if (error) { - ptr str = S_strerror(saved_errno); - switch (saved_errno) { - case EACCES: - return Scons(FIX(OPEN_ERROR_PROTECTION), str); - case ENOENT: - return Scons(FIX(OPEN_ERROR_EXISTSNOT), str); - default: - return Scons(FIX(OPEN_ERROR_OTHER), str); - } - } - - if (!compressed) { - return MAKE_FD(fd); - } - - if ((dupfd = DUP(fd)) == -1) { - ptr str = S_strerror(errno); - FD_GUARD(result == 0, error, result = CLOSE(fd)); - return Scons(FIX(OPEN_ERROR_OTHER), str); - } - - DEACTIVATE(tc) /* glzdopen_input reads the magic word from the file */ - if ((file = S_glzdopen_input(dupfd)) == Z_NULL) { - REACTIVATE(tc) - FD_GUARD(result == 0, error, result = CLOSE(fd)); - FD_GUARD(result == 0, error, result = CLOSE(dupfd)); - return Scons(FIX(OPEN_ERROR_OTHER), Sstring("unable to allocate compression state (too many open files?)")); - } - - compressed = !S_glzdirect(file); - REACTIVATE(tc) - - if (compressed) { - FD_GUARD(result == 0, error, result = CLOSE(fd)); - /* box indicates compressed */ - return Sbox(MAKE_GZXFILE(file)); - } - - GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = S_glzclose(file)); - if (flag) {} /* make the compiler happy */ - if (LSEEK(fd, 0, SEEK_SET) != 0) { /* glzdopen and glzdirect might not leave fd at position 0 */ - FD_GUARD(result == 0, error, result = CLOSE(fd)); - return Scons(FIX(OPEN_ERROR_OTHER),Sstring("unable to reset after reading header bytes")); - } - return MAKE_FD(fd); -} - -ptr S_compress_input_fd(INT fd, I64 pos) { - INT dupfd, error, result, ok, flag; IBOOL compressed; - glzFile file; -#ifdef PTHREADS - ptr tc = get_thread_context(); -#endif - - if ((dupfd = DUP(fd)) == -1) { - return S_strerror(errno); - } - - DEACTIVATE(tc) - if ((file = S_glzdopen_input(dupfd)) == Z_NULL) { - REACTIVATE(tc) - FD_GUARD(result == 0, error, result = CLOSE(dupfd)); - return Sstring("unable to allocate compression state (too many open files?)"); - } - - compressed = !S_glzdirect(file); - REACTIVATE(tc) - - if (compressed) { - FD_GUARD(result == 0, error, result = CLOSE(fd)); - if (error) {} /* make the compiler happy */ - /* box indicates compressed */ - return Sbox(MAKE_GZXFILE(file)); - } - - GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = S_glzclose(file)); - if (flag) {} /* make the compiler happy */ - if (LSEEK(fd, pos, SEEK_SET) != pos) { /* glzdirect does not leave fd at same position */ - return Sstring("unable to reset after reading header bytes"); - } - return MAKE_FD(fd); -} - -ptr S_compress_output_fd(INT fd) { - glzFile file; - ptr tc = get_thread_context(); - - file = S_glzdopen_output(fd, (INT)UNFIX(COMPRESSFORMAT(tc)), (INT)UNFIX(COMPRESSLEVEL(tc))); - - if (file == Z_NULL) - return Sstring("unable to allocate compression state (too many open files?)"); - - /* box indicates compressed */ - return Sbox(MAKE_GZXFILE(file)); -} - -static ptr new_open_output_fd_helper( - const char *infilename, INT mode, INT flags, - IBOOL no_create, IBOOL no_fail, IBOOL no_truncate, - IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed) { - char *filename; - INT saved_errno = 0; - iptr error; - INT fd, result; - ptr tc = get_thread_context(); - - flags |= - (no_create ? 0 : O_CREAT) | - ((no_fail || no_create) ? 0 : O_EXCL) | - (no_truncate ? 0 : O_TRUNC) | - ((!append) ? 0 : O_APPEND); - - filename = S_malloc_pathname(infilename); - - if (replace && UNLINK(filename) != 0 && errno != ENOENT) { - ptr str = S_strerror(errno); - switch (errno) { - case EACCES: - return Scons(FIX(OPEN_ERROR_PROTECTION), str); - default: - return Scons(FIX(OPEN_ERROR_OTHER), str); - } - } - - /* NB: don't use infilename, which might point into a Scheme string, after this point */ - DEACTIVATE(tc) - FD_EINTR_GUARD(fd >= 0, error, fd = OPEN(filename, flags, mode)); - saved_errno = errno; - REACTIVATE(tc) - - /* NB: don't use free'd filename after this point */ - free(filename); - - if (error) { - ptr str = S_strerror(saved_errno); - switch (saved_errno) { - case EACCES: - return Scons(FIX(OPEN_ERROR_PROTECTION), str); - case EEXIST: - return Scons(FIX(OPEN_ERROR_EXISTS), str); - case ENOENT: - return Scons(FIX(OPEN_ERROR_EXISTSNOT), str); - default: - return Scons(FIX(OPEN_ERROR_OTHER), str); - } - } - - if (lock) { - DEACTIVATE(tc) - error = lockfile(fd); - saved_errno = errno; - REACTIVATE(tc) - if (error) { - FD_GUARD(result == 0, error, result = CLOSE(fd)); - return Scons(FIX(OPEN_ERROR_OTHER), S_strerror(saved_errno)); - } - } - - if (!compressed) { - return MAKE_FD(fd); - } - - glzFile file; - file = S_glzdopen_output(fd, (INT)UNFIX(COMPRESSFORMAT(tc)), (INT)UNFIX(COMPRESSLEVEL(tc))); - if (file == Z_NULL) { - FD_GUARD(result == 0, error, result = CLOSE(fd)); - return Scons(FIX(OPEN_ERROR_OTHER), Sstring("unable to allocate compression state")); - } - - return MAKE_GZXFILE(file); -} - -ptr S_new_open_output_fd( - const char *filename, INT mode, - IBOOL no_create, IBOOL no_fail, IBOOL no_truncate, - IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed) { - return new_open_output_fd_helper( - filename, mode, O_BINARY | O_WRONLY, - no_create, no_fail, no_truncate, - append, lock, replace, compressed); -} - -ptr S_new_open_input_output_fd( - const char *filename, INT mode, - IBOOL no_create, IBOOL no_fail, IBOOL no_truncate, - IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed) { - if (compressed) - return Sstring("compressed input/output files not supported"); - else - return new_open_output_fd_helper( - filename, mode, O_BINARY | O_RDWR, - no_create, no_fail, no_truncate, - append, lock, replace, 0); -} - -ptr S_close_fd(ptr file, IBOOL gzflag) { - INT saved_errno = 0; - INT ok, flag; - INT fd = gzflag ? 0 : GET_FD(file); - glzFile gzfile = gzflag ? GZXFILE_GZFILE(file) : NULL; -#ifdef PTHREADS - ptr tc = get_thread_context(); -#endif - - /* refuse to close stdin, stdout, and stderr fds */ - if (!gzflag && fd <= 2) return Strue; - - /* file is not locked; do not reference after deactivating thread! */ - file = (ptr)-1; - - /* NOTE: close automatically releases locks so we don't to call unlock*/ - DEACTIVATE(tc) - if (!gzflag) { - FD_GUARD(ok == 0, flag, ok = CLOSE(fd)); - } else { - /* zlib 1.2.1 returns Z_BUF_ERROR when closing an empty file opened for reading */ - GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, gzfile, ok = S_glzclose(gzfile)); - } - saved_errno = errno; - REACTIVATE(tc) - - if (!flag) { - return Strue; - } - - if (gzflag && saved_errno == 0) { - return Sstring("compression failed"); - } - - return S_strerror(saved_errno); -} - -#define GZ_IO_SIZE_T unsigned int - -#ifdef WIN32 -#define IO_SIZE_T unsigned int -static HANDLE hStdin = NULL; -static iptr read_console(char* buf, unsigned size) { - static char u8buf[1024]; - static int u8i = 0; - static int u8n = 0; - iptr n = 0; - do { - for (; size > 0 && u8n > 0; size--, u8n--, n++) - *buf++ = u8buf[u8i++]; - if (n == 0 && size > 0) { - wchar_t wbuf[256]; - DWORD wn; - if (!ReadConsoleW(hStdin, wbuf, 256, &wn, NULL) || wn == 0) - return 0; - u8n = WideCharToMultiByte(CP_UTF8, 0, wbuf, wn, u8buf, 1024, NULL, NULL); - u8i = 0; - } - } while (n == 0); - return n; -} -#else /* WIN32 */ -#define IO_SIZE_T size_t -#endif /* WIN32 */ - -/* Returns string on error, #!eof on end-of-file and integer-count otherwise */ -ptr S_bytevector_read(ptr file, ptr bv, iptr start, iptr count, IBOOL gzflag) { - INT saved_errno = 0; - ptr tc = get_thread_context(); - iptr m, flag = 0; - INT fd = gzflag ? 0 : GET_FD(file); - glzFile gzfile = gzflag ? GZXFILE_GZFILE(file) : NULL; - - /* file is not locked; do not reference after deactivating thread! */ - file = (ptr)-1; - -#if (iptr_bits > 32) - if ((WIN32 || gzflag) && (unsigned int)count != count) count = 0xffffffff; -#endif - - LOCKandDEACTIVATE(tc, bv) -#ifdef CHECK_FOR_ROSETTA - /* If we are running on Apple Silicon under Rosetta 2 translation, work around - a bug (present in 11.2.3 at least) in its handling of memory page protection - bits. One of the tasks that Rosetta handles is to appropriately twiddle the - execute and write bits based on what's happening to the memory in order to - preserve the illusion that the pages have RWX permissions, whereas Apple - Silicon enforces a W^X (write XOR execute) model. For some reason, this - bit-twiddling sometimes fails when the bytevector passed to `read` extends - onto a page that's currently R-X, causing the `read` to fail with EFAULT - ("bad address"). By writing to each subsequent page, we force Rosetta to - do the right magic to the protection bits. (Or at least it makes the error - go away and all the mats pass.) - */ - if (is_rosetta) { - for (iptr idx = start+count; idx > start; idx -= S_pagesize) { - volatile octet b = BVIT(bv,idx); - BVIT(bv,idx) = b; - } - } -#endif - -#ifdef WIN32 - if (!gzflag && fd == 0 && hStdin != NULL) { - DWORD error_code; - SetConsoleCtrlHandler(NULL, TRUE); - SetLastError(0); - m = read_console(&BVIT(bv,start), (IO_SIZE_T)count); - error_code = GetLastError(); - if (m == 0 && error_code == 0x3e3) { - /* Guard against Windows calling the ConsoleCtrlHandler after we - * turn it back on by waiting a bit. */ - Sleep(1); -#ifdef PTHREADS - /* threaded io.ss doesn't handle interrupts because - * with-tc-mutex disables them, so bail out. */ - SetConsoleCtrlHandler(NULL, FALSE); - REACTIVATEandUNLOCK(tc, bv) - S_noncontinuable_interrupt(); -#else - KEYBOARDINTERRUPTPENDING(tc) = Strue; - SOMETHINGPENDING(tc) = Strue; -#endif - } - SetConsoleCtrlHandler(NULL, FALSE); - } else -#endif /* WIN32 */ - { - if (!gzflag) { - FD_EINTR_GUARD( - m >= 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)), flag, - m = READ(fd,&BVIT(bv,start),(IO_SIZE_T)count)); - } else { - GZ_EINTR_GUARD( - 1, m >= 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)), - flag, gzfile, - m = S_glzread(gzfile, &BVIT(bv,start), (GZ_IO_SIZE_T)count)); - } - } - saved_errno = errno; - REACTIVATEandUNLOCK(tc, bv) - - if (Sboolean_value(KEYBOARDINTERRUPTPENDING(tc))) { - return Sstring("interrupt"); - } - - if (!flag) { - return m == 0 ? Seof_object : FIX(m); - } - - if (saved_errno == EAGAIN) { - return FIX(0); - } - - return S_strerror(saved_errno); -} - -/* Returns: - string on error, including if not supported, - n when read, - 0 on non-blocking and - #!eof otherwise */ -ptr S_bytevector_read_nb(ptr file, ptr bv, iptr start, iptr count, IBOOL gzflag) { -#ifdef WIN32 - HANDLE h; - - /* assume compressed files are always ready */ - if (gzflag) return FIX(1); - - if ((h = (HANDLE)_get_osfhandle(GET_FD(file))) != INVALID_HANDLE_VALUE) { - switch (GetFileType(h)) { - case FILE_TYPE_CHAR: - /* if h is hStdin, PeekConsoleInput can tell us if a key down event - is waiting, but if it's not a newline, we can't be sure that - a read will succeed. so PeekConsoleInput is basically useless - for our purposes. */ - break; - case FILE_TYPE_PIPE: { - DWORD bytes; - if (PeekNamedPipe(h, NULL, 0, NULL, &bytes, NULL) && bytes == 0) return FIX(0); - /* try the read on error or if bytes > 0 */ - return S_bytevector_read(file, bv, start, count, gzflag); - } - default: { - if (WaitForSingleObject(h, 0) == WAIT_TIMEOUT) return FIX(0); - /* try the read on error or if bytes > 0 */ - return S_bytevector_read(file, bv, start, count, gzflag); - } - } - } - - return Sstring("cannot determine ready status"); -#else /* WIN32 */ - INT fcntl_flags; - ptr result; - INT fd; - - /* assume compressed files are always ready */ - if (gzflag) return FIX(1); - - fd = GET_FD(file); - - /* set NOBLOCK for nonblocking read */ - fcntl_flags = fcntl(fd, F_GETFL, 0); - if (!(fcntl_flags & NOBLOCK)) (void) fcntl(fd, F_SETFL, fcntl_flags | NOBLOCK); - - result = S_bytevector_read(file, bv, start, count, gzflag); - - /* reset NOBLOCK for normal blocking read */ - if (!(fcntl_flags & NOBLOCK)) (void) fcntl(fd, F_SETFL, fcntl_flags); - - return result; -#endif /* WIN32 */ -} - -ptr S_bytevector_write(ptr file, ptr bv, iptr start, iptr count, IBOOL gzflag) { - iptr i, s, c; - ptr tc = get_thread_context(); - INT flag = 0, saved_errno = 0; - INT fd = gzflag ? 0 : GET_FD(file); - glzFile gzfile = gzflag ? GZXFILE_GZFILE(file) : NULL; - - for (s = start, c = count; c > 0; s += i, c -= i) { - iptr cx = c; - -#if (iptr_bits > 32) - if ((WIN32 || gzflag) && (unsigned int)cx != cx) cx = 0xffffffff; -#endif - - /* if we could know that fd is nonblocking, we wouldn't need to deactivate. - we could test ioctl, but some other thread could change it before we actually - get around to writing. */ - LOCKandDEACTIVATE(tc, bv) - if (gzflag) { - /* strangely, gzwrite returns 0 on error */ - GZ_EINTR_GUARD( - i < 0, i > 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)), - flag, gzfile, - i = S_glzwrite(gzfile, &BVIT(bv,s), (GZ_IO_SIZE_T)cx)); - } else { - FD_EINTR_GUARD(i >= 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)), - flag, i = WRITE(fd, &BVIT(bv,s), (IO_SIZE_T)cx)); - } - saved_errno = errno; - REACTIVATEandUNLOCK(tc, bv) - - if (flag) { - if (saved_errno == EAGAIN) { flag = 0; } - break; - } - - /* we escape from loop if keyboard interrupt is pending, but this won't - do much good until we fix up the interrupt protocol to guarantee - that the interrupt handler is actually called */ - if (Sboolean_value(KEYBOARDINTERRUPTPENDING(tc))) { - if (i >= 0) s += i; - break; - } - } - - if (!flag) { - return FIX(s - start); - } - - if (saved_errno == EAGAIN) { - return FIX(0); - } - - if (gzflag && saved_errno == 0) { - return Sstring("compression failed"); - } - - return S_strerror(saved_errno); -} - -/* S_put_byte is a simplified version of S_bytevector_write for writing one - byte on unbuffered ports */ -ptr S_put_byte(ptr file, INT byte, IBOOL gzflag) { - iptr i; - ptr tc = get_thread_context(); - INT flag = 0, saved_errno = 0; - INT fd = gzflag ? 0 : GET_FD(file); - glzFile gzfile = gzflag ? GZXFILE_GZFILE(file) : NULL; - octet buf[1]; - - buf[0] = (octet)byte; - - DEACTIVATE(tc) - if (gzflag) { - /* strangely, gzwrite returns 0 on error */ - GZ_EINTR_GUARD( - i < 0, i > 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)), - flag, gzfile, - i = S_glzwrite(gzfile, buf, 1)); - } else { - FD_EINTR_GUARD(i >= 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)), - flag, i = WRITE(fd, buf, 1)); - } - saved_errno = errno; - REACTIVATE(tc) - - if (flag) { - if (saved_errno == EAGAIN) { flag = 0; } - } - - if (!flag) { - return FIX(i); - } - - if (saved_errno == EAGAIN) { - return FIX(0); - } - - if (gzflag && saved_errno == 0) { - return Sstring("compression failed"); - } - - return S_strerror(saved_errno); -} - -ptr S_get_fd_pos(ptr file, IBOOL gzflag) { - errno = 0; - if (gzflag) { - z_off_t offset = S_glzseek(GZXFILE_GZFILE(file), 0, SEEK_CUR); - if (offset != -1) return Sinteger64(offset); - } else { - OFF_T offset = LSEEK(GET_FD(file), 0, SEEK_CUR); - if (offset != -1) return Sinteger64(offset); - } - if (gzflag && errno == 0) return Sstring("compression failed"); - return S_strerror(errno); -} - -/* assume wrapper ensures 0 <= pos <= 2^63-1 */ -ptr S_set_fd_pos(ptr file, ptr pos, IBOOL gzflag) { - I64 offset64 = S_int64_value("set-file-position", pos); - - if (gzflag) { - z_off_t offset = (z_off_t)offset64; - if (sizeof(z_off_t) != sizeof(I64)) - if (offset != offset64) return Sstring("invalid position"); - errno = 0; - if (S_glzseek(GZXFILE_GZFILE(file),offset,SEEK_SET) == offset) return Strue; - if (errno == 0) return Sstring("compression failed"); - return S_strerror(errno); - } else { - OFF_T offset = (OFF_T)offset64; - if (sizeof(OFF_T) != sizeof(I64)) - if (offset != offset64) return Sstring("invalid position"); - if (LSEEK(GET_FD(file), offset, SEEK_SET) == offset) return Strue; - return S_strerror(errno); - } -} - -ptr S_get_fd_non_blocking(ptr file, IBOOL gzflag) { -#ifdef WIN32 - return Sfalse; -#else /* WIN32 */ - INT fcntl_flags; - - if (gzflag) return Sfalse; - - fcntl_flags = fcntl(GET_FD(file), F_GETFL, 0); - - if (fcntl_flags == -1) { - return S_strerror(errno); - } - - return Sboolean(NOBLOCK & fcntl_flags); -#endif /* WIN32 */ -} - -ptr S_set_fd_non_blocking(ptr file, IBOOL x, IBOOL gzflag) { -#ifdef WIN32 - return Sstring("unsupported"); -#else /* WIN32 */ - iptr fd; - INT fcntl_flags; - - if (gzflag) { - if (x) return Sstring("Compressed non-blocking ports not supported"); - else return Strue; - } - - fd = GET_FD(file); - fcntl_flags = fcntl(fd, F_GETFL, 0); - - if (fcntl_flags == -1) { - return S_strerror(errno); - } - - if (x) { - if (fcntl_flags & NOBLOCK) { - return Strue; - } - if (0 == fcntl(fd, F_SETFL, fcntl_flags | NOBLOCK)) { - return Strue; - } - return S_strerror(errno); - } else { - if (!(fcntl_flags & NOBLOCK)) { - return Strue; - } - if (0 == fcntl(fd, F_SETFL, fcntl_flags & ~NOBLOCK)) { - return Strue; - } - return S_strerror(errno); - } -#endif /* WIN32 */ -} - -ptr S_get_fd_length(ptr file, IBOOL gzflag) { - struct STATBUF statbuf; - - if (gzflag) return Sstring("Not supported on compressed files"); - - if (FSTAT(GET_FD(file), &statbuf) == 0) { - return Sinteger64(statbuf.st_size); - } - - return S_strerror(errno); -} - -ptr S_set_fd_length(ptr file, ptr length, IBOOL gzflag) { - INT fd, ok, flag = 0; - I64 len64; off_t len; -#ifdef PTHREADS - ptr tc = get_thread_context(); -#endif - - if (gzflag) return Sstring("Not supported on compressed files"); - - len64 = S_int64_value("set-file-length", length); - len = (off_t)len64; - if (sizeof(off_t) != sizeof(I64)) - if (len != len64) return Sstring("invalid length"); - - fd = GET_FD(file); - DEACTIVATE(tc) - FD_EINTR_GUARD(ok == 0, flag, ok = ftruncate(fd, len)); - REACTIVATE(tc) - - return flag ? S_strerror(errno) : Strue; -} - -void S_new_io_init(void) { - if (S_boot_time) { - S_set_symbol_value(S_intern((const unsigned char *)"$c-bufsiz"), Sinteger(SBUFSIZ)); - } -#ifdef WIN32 - { /* Get the console input handle for reading Unicode characters */ - HANDLE h; - DWORD mode; - if ((h = GetStdHandle(STD_INPUT_HANDLE)) != INVALID_HANDLE_VALUE - && GetConsoleMode(h, &mode)) - hStdin = h; - } - /* transcoder, if any, does its own cr, lf translations */ - _setmode(_fileno(stdin), O_BINARY); - _setmode(_fileno(stdout), O_BINARY); - _setmode(_fileno(stderr), O_BINARY); - /* Set the console output to handle UTF-8 */ - SetConsoleOutputCP(CP_UTF8); -#endif /* WIN32 */ -} - -static int is_valid_zlib_length(iptr count) { - /* A zlib `uLong` may be the same as `unsigned long`, - which is not as big as `iptr` on 64-bit Windows. */ - return count == (iptr)(uLong)count; -} - -static int is_valid_lz4_length(iptr len) { - return (len <= LZ4_MAX_INPUT_SIZE); -} - -/* Accept `iptr` because we expect it to represent a bytevector size, - which always fits in `iptr`. Return `uptr`, because the result might - not fit in `iptr`. */ -uptr S_bytevector_compress_size(iptr s_count, INT compress_format) { - switch (compress_format) { - case COMPRESS_GZIP: - if (is_valid_zlib_length(s_count)) - return compressBound((uLong)s_count); - else { - /* Compression will report "source too long" */ - return 0; - } - case COMPRESS_LZ4: - if (is_valid_lz4_length(s_count)) - return LZ4_compressBound((uLong)s_count); - else { - /* Compression will report "source too long" */ - return 0; - } - default: - S_error1("S_bytevector_compress_size", "unexpected compress format ~s", FIX(compress_format)); - return 0; - } -} - -ptr S_bytevector_compress(ptr dest_bv, iptr d_start, iptr d_count, - ptr src_bv, iptr s_start, iptr s_count, - INT compress_format) { - ptr tc = get_thread_context(); - int compress_level = (INT)UNFIX(COMPRESSLEVEL(tc)); - - /* On error, an message-template string with ~s for the bytevector */ - switch (compress_format) { - case COMPRESS_GZIP: - { - int r; - uLong destLen; - - if (!is_valid_zlib_length(s_count)) - return Sstring("source bytevector ~s is too large"); - - destLen = (uLong)d_count; - - r = compress2(&BVIT(dest_bv, d_start), &destLen, &BVIT(src_bv, s_start), (uLong)s_count, S_zlib_compress_level(compress_level)); - - if (r == Z_OK) - return FIX(destLen); - else if (r == Z_BUF_ERROR) - return Sstring("destination bytevector is too small for compressed form of ~s"); - else - return Sstring("internal error compressing ~s"); - } - case COMPRESS_LZ4: - { - int destLen; - - if (!is_valid_lz4_length(s_count)) - return Sstring("source bytevector ~s is too large"); - - if (compress_level == COMPRESS_MIN) { - destLen = LZ4_compress_default((char *)&BVIT(src_bv, s_start), (char *)&BVIT(dest_bv, d_start), (int)s_count, (int)d_count); - } else { - destLen = LZ4_compress_HC((char *)&BVIT(src_bv, s_start), (char *)&BVIT(dest_bv, d_start), (int)s_count, (int)d_count, S_lz4_compress_level(compress_level)); - } - - if (destLen > 0) - return Sfixnum(destLen); - else - return Sstring("compression failed for ~s"); - } - default: - S_error1("S_bytevector_compress", "unexpected compress format ~s", FIX(compress_format)); - return Sfalse; - } -} - -ptr S_bytevector_uncompress(ptr dest_bv, iptr d_start, iptr d_count, - ptr src_bv, iptr s_start, iptr s_count, - INT compress_format) { - /* On error, an message-template string with ~s for the bytevector */ - switch (compress_format) { - case COMPRESS_GZIP: - { - int r; - uLongf destLen; - - if (!is_valid_zlib_length(d_count)) - return Sstring("expected result size of uncompressed source ~s is too large"); - - destLen = (uLongf)d_count; - - r = uncompress(&BVIT(dest_bv, d_start), &destLen, &BVIT(src_bv, s_start), (uLong)s_count); - - if (r == Z_OK) - return FIX(destLen); - else if (r == Z_BUF_ERROR) - return Sstring("uncompressed ~s is larger than expected size"); - else if (r == Z_DATA_ERROR) - return Sstring("invalid data in source bytevector ~s"); - else - return Sstring("internal error uncompressing ~s"); - } - case COMPRESS_LZ4: - { - int r; - - if (!is_valid_lz4_length(d_count)) - return Sstring("expected result size of uncompressed source ~s is too large"); - - r = LZ4_decompress_safe((char *)&BVIT(src_bv, s_start), (char *)&BVIT(dest_bv, d_start), (int)s_count, (int)d_count); - - if (r >= 0) - return Sfixnum(r); - else - return Sstring("internal error uncompressing ~s"); - } - default: - return Sstring("unexpected compress format ~s"); - } -} diff --git a/ta6ob/c/new-io.o b/ta6ob/c/new-io.o deleted file mode 100644 index a52729a..0000000 Binary files a/ta6ob/c/new-io.o and /dev/null differ diff --git a/ta6ob/c/nocurses.h b/ta6ob/c/nocurses.h deleted file mode 100644 index 4b17450..0000000 --- a/ta6ob/c/nocurses.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef ERR -# define ERR -1 -#endif - -#define setupterm(a, b, e) (*(e) = 0, ERR) -#define tputs(c, x, f) (f(c)) - -#define lines 0 -#define columns 0 - -#define cursor_left 0 -#define cursor_right 0 -#define cursor_up 0 -#define cursor_down 0 -#define enter_am_mode 0 -#define exit_am_mode 0 -#define clr_eos 0 -#define clr_eol 0 -#define clear_screen 0 -#define carriage_return 0 -#define bell 0 -#define scroll_reverse 0 -#define auto_right_margin 0 -#define eat_newline_glitch 0 diff --git a/ta6ob/c/number.c b/ta6ob/c/number.c deleted file mode 100644 index 105e94c..0000000 --- a/ta6ob/c/number.c +++ /dev/null @@ -1,2120 +0,0 @@ -/* number.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* -*** - * assumptions: - * bigits are unsigned - * uptr is either one or two bigits wide -*** -*/ - -#include "system.h" - -/* locally defined functions */ -static ptr copy_normalize(ptr tc, const bigit *p, iptr len, IBOOL sign); -static IBOOL abs_big_lt(ptr x, ptr y, iptr xl, iptr yl); -static IBOOL abs_big_eq(ptr x, ptr y, iptr xl, iptr yl); -static ptr big_negate(ptr tc, ptr x); -static ptr big_add_pos(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL sign); -static ptr big_add_neg(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL sign); -static ptr big_add(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL xs, IBOOL ys); -static ptr big_mul(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL sign); -static void big_short_trunc(ptr tc, ptr x, bigit s, iptr xl, IBOOL qs, IBOOL rs, ptr *q, ptr *r); -static void big_trunc(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL qs, IBOOL rs, ptr *q, ptr *r); -static INT normalize(bigit *xp, bigit *yp, iptr xl, iptr yl); -static bigit quotient_digit(bigit *xp, bigit *yp, iptr yl); -static bigit qhat(bigit *xp, bigit *yp); -static ptr big_short_gcd(ptr tc, ptr x, bigit y, iptr xl); -static ptr big_gcd(ptr tc, ptr x, ptr y, iptr xl, iptr yl); -static ptr s_big_ash(ptr tc, bigit *xp, iptr xl, IBOOL sign, iptr cnt); -static double big_short_floatify(ptr tc, ptr x, bigit s, iptr xl, IBOOL sign); -static double big_floatify(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL sign); -static double floatify_normalize(bigit *p, iptr e, IBOOL sign, IBOOL sticky); -static double floatify_ratnum(ptr tc, ptr x); -static ptr big_logbitp(iptr n, ptr x, iptr xl, IBOOL xs); -static ptr big_logbit0(ptr tc, ptr origx, iptr n, ptr x, iptr xl, IBOOL xs); -static ptr big_logbit1(ptr tc, ptr origx, iptr n, ptr x, iptr xl, IBOOL xs); -static ptr big_logtest(ptr x, ptr y, iptr xl, iptr yl, IBOOL xs, IBOOL ys); -static ptr big_logand(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL xs, IBOOL ys); -static ptr big_logor(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL xs, IBOOL ys); -static ptr big_logxor(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL xs, IBOOL ys); - -/* use w/o trailing semicolon */ -#define PREPARE_BIGNUM(tc,x,l)\ - {if (x == FIX(0) || BIGLEN(x) < (l)) x = S_bignum(tc, (l)*2, 0);} - -#define bigit_mask (~(bigit)0) - -#define IBIGIT_TO_BIGNUM(tc,B,x,cnt,sign) {\ - ibigit _i_ = x;\ - PREPARE_BIGNUM(tc, B, 1)\ - *cnt = 1;\ - BIGIT(B,0) = (*sign = (_i_ < 0)) ? -_i_ : _i_;\ -} - -#define UBIGIT_TO_BIGNUM(tc,B,u,cnt) {\ - PREPARE_BIGNUM(tc, B, 1)\ - *cnt = 1;\ - BIGIT(B,0) = u;\ -} - -#define IBIGITBIGIT_TO_BIGNUM(tc,B,x,cnt,sign) {\ - ibigitbigit _i_ = x; bigitbigit _u_; bigit _b_;\ - PREPARE_BIGNUM(tc, B, 2)\ - _u_ = (*sign = (_i_ < 0)) ? -_i_ : _i_;\ - if ((_b_ = (_u_ & (bigitbigit)bigit_mask)) == _u_) {\ - *cnt = 1;\ - BIGIT(B,0) = (bigit)_u_;\ - } else {\ - *cnt = 2;\ - BIGIT(B,0) = (bigit)(_u_ >> bigit_bits);\ - BIGIT(B,1) = _b_;\ - }\ -} - -#define UBIGITBIGIT_TO_BIGNUM(tc,B,x,cnt) {\ - bigitbigit _u_ = x; bigit _b_;\ - PREPARE_BIGNUM(tc, B, 2)\ - if ((_b_ = (_u_ & (bigitbigit)bigit_mask)) == _u_) {\ - *cnt = 1;\ - BIGIT(B,0) = (bigit)_u_;\ - } else {\ - *cnt = 2;\ - BIGIT(B,0) = (bigit)(_u_ >> bigit_bits);\ - BIGIT(B,1) = _b_;\ - }\ -} - -#define U32_bigits (32 / bigit_bits) - -#if (U32_bigits == 1) -#define I32_TO_BIGNUM(tc,B,x,cnt,sign) IBIGIT_TO_BIGNUM(tc,B,x,cnt,sign) -#define U32_TO_BIGNUM(tc,B,x,cnt) UBIGIT_TO_BIGNUM(tc,B,x,cnt) -#endif - -#if (U32_bigits == 2) -#define I32_TO_BIGNUM(tc,B,x,cnt,sign) IBIGITBIGIT_TO_BIGNUM(tc,B,x,cnt,sign) -#define U32_TO_BIGNUM(tc,B,x,cnt) UBIGITBIGIT_TO_BIGNUM(tc,B,x,cnt) -#endif - -#define U64_bigits (64 / bigit_bits) - -#if (U64_bigits == 2) -#define I64_TO_BIGNUM(tc,B,x,cnt,sign) IBIGITBIGIT_TO_BIGNUM(tc,B,x,cnt,sign) -#define U64_TO_BIGNUM(tc,B,x,cnt) UBIGITBIGIT_TO_BIGNUM(tc,B,x,cnt) -#endif - -#if (U64_bigits == 4) -see v7.4 number.c for U64_TO_BIGNUM w/U64_bigits == 4 -#endif - -#define ptr_bigits (ptr_bits / bigit_bits) - -#if (ptr_bigits == 1) -#define IPTR_TO_BIGNUM(tc,B,x,cnt,sign) IBIGIT_TO_BIGNUM(tc,B,x,cnt,sign) -#define UPTR_TO_BIGNUM(tc,B,x,cnt) UBIGIT_TO_BIGNUM(tc,B,x,cnt) -#endif - -#if (ptr_bigits == 2) -#define IPTR_TO_BIGNUM(tc,B,x,cnt,sign) IBIGITBIGIT_TO_BIGNUM(tc,B,x,cnt,sign) -#define UPTR_TO_BIGNUM(tc,B,x,cnt) UBIGITBIGIT_TO_BIGNUM(tc,B,x,cnt) -#endif - -#define FIXNUM_TO_BIGNUM(tc,B,p,cnt,sign) IPTR_TO_BIGNUM(tc,B,UNFIX(p),cnt,sign) - -ptr S_normalize_bignum(ptr x) { - uptr n = BIGIT(x, 0); iptr len = BIGLEN(x); IBOOL sign = BIGSIGN(x); - -#if (ptr_bigits == 1) - if (len == 1) { - if (sign) { - if (n <= -most_negative_fixnum) return FIX(-(iptr)n); - } else { - if (n <= most_positive_fixnum) return FIX(n); - } - } -#elif (ptr_bigits == 2) - if (len == 1) - return sign ? FIX(-(iptr)n) : FIX(n); - else if (len == 2) { - n = (n << bigit_bits) | BIGIT(x, 1); - if (sign) { - /* avoid -most-negative-fixnum to avoid bogus Sun compiler warning */ - if (n <= most_positive_fixnum+1) return FIX(-(iptr)n); - } else { - if (n <= most_positive_fixnum) return FIX(n); - } - } -#endif - - return x; -} - -static ptr copy_normalize(ptr tc, const bigit *p, iptr len, IBOOL sign) { - bigit *p1; uptr n; ptr b; - - for (;;) { - if ((n = *p) != 0) - break; - else if (--len == 0) - return FIX(0); - else p++; - } - -#if (ptr_bigits == 1) - if (len == 1) { - if (sign) { - if (n <= -most_negative_fixnum) return FIX(-(iptr)n); - } else { - if (n <= most_positive_fixnum) return FIX(n); - } - } -#elif (ptr_bigits == 2) - if (len == 1) - return sign ? FIX(-(iptr)n) : FIX(n); - else if (len == 2) { - n = (n << bigit_bits) | *(p+1); - if (sign) { - /* avoid -most-negative-fixnum to avoid bogus Sun compiler warning */ - if (n <= most_positive_fixnum+1) return FIX(-(iptr)n); - } else { - if (n <= most_positive_fixnum) return FIX(n); - } - } -#endif - - b = S_bignum(tc, len, sign); - for (p1 = &BIGIT(b, 0); len--;) *p1++ = *p++; - return b; -} - -/* -2^(b-1) <= x <= 2^b-1, where b = number of bits in a uptr */ -iptr S_integer_value(const char *who, ptr x) { - if (Sfixnump(x)) return UNFIX(x); - - if (Sbignump(x)) { - iptr xl; uptr u; - - if ((xl = BIGLEN(x)) > ptr_bigits) S_error1(who, "~s is out of range", x); - - u = BIGIT(x,0); - -#if (ptr_bigits == 2) - if (xl == 2) u = (u << bigit_bits) | BIGIT(x,1); -#endif - - if (!BIGSIGN(x)) return (iptr)u; - if (u < ((uptr)1 << (ptr_bits - 1))) return -(iptr)u; - if (u > ((uptr)1 << (ptr_bits - 1))) S_error1(who, "~s is out of range", x); -#if (fixnum_bits > 32) - return (iptr)0x8000000000000000; -#else - return (iptr)0x80000000; -#endif - } - - S_error1(who, "~s is not an integer", x); - - return 0 /* not reached */; -} - -/* -2^(b-1) <= x <= 2^b-1, where b = number of bits in a uptr */ -IBOOL S_integer_valuep(ptr x) { - if (Sfixnump(x)) return 1; - - if (Sbignump(x)) { - iptr xl; uptr u; - - if ((xl = BIGLEN(x)) > ptr_bigits) return 0; - - u = BIGIT(x,0); - -#if (ptr_bigits == 2) - if (xl == 2) u = (u << bigit_bits) | BIGIT(x,1); -#endif - - if (!BIGSIGN(x)) return 1; - return u <= ((uptr)1 << (ptr_bits - 1)); - } - - return 0; -} - -iptr Sinteger_value(ptr x) { - return S_integer_value("Sinteger_value", x); -} - -/* -2^31 <= x <= 2^32-1 */ -I32 S_int32_value(char *who, ptr x) { -#if (fixnum_bits > 32) - if (Sfixnump(x)) { - iptr n = UNFIX(x); - if (n < 0) { - I32 m = (I32)n; - if ((iptr)m == UNFIX(x)) return m; - } else { - U32 m = (U32)n; - if ((uptr)m == (uptr)UNFIX(x)) return (I32)m; - } - S_error1(who, "~s is out of range", x); - } - if (Sbignump(x)) S_error1(who, "~s is out of range", x); -#else /* (fixnum_bits > 32) */ - if (Sfixnump(x)) return UNFIX(x); - - if (Sbignump(x)) { - iptr xl; U32 u; - - if ((xl = BIGLEN(x)) > U32_bigits) S_error1(who, "~s is out of range", x); - - u = BIGIT(x,0); - -#if (U32_bigits == 2) - if (xl == 2) u = (u << bigit_bits) | BIGIT(x,1); -#endif - - if (!BIGSIGN(x)) return (I32)u; - if (u < ((U32)1 << 31)) return -(I32)u; - if (u > ((U32)1 << 31)) S_error1(who, "~s is out of range", x); - return (I32)0x80000000; - } -#endif /* (fixnum_bits > 32) */ - - S_error1(who, "~s is not an integer", x); - - return 0 /* not reached */; -} - -I32 Sinteger32_value(ptr x) { - return S_int32_value("Sinteger32_value", x); -} - -/* -2^63 <= x <= 2^64-1 */ -I64 S_int64_value(char *who, ptr x) { - if (Sfixnump(x)) return UNFIX(x); - - if (Sbignump(x)) { - iptr xl; U64 u; - - if ((xl = BIGLEN(x)) > U64_bigits) S_error1(who, "~s is out of range", x); - - u = BIGIT(x,0); - -#if (U64_bigits == 2) - if (xl == 2) u = (u << bigit_bits) | BIGIT(x,1); -#endif - - if (!BIGSIGN(x)) return (I64)u; - if (u < ((U64)1 << 63)) return -(I64)u; - if (u > ((U64)1 << 63)) S_error1(who, "~s is out of range", x); - return (I64)0x8000000000000000; - } - - S_error1(who, "~s is not an integer", x); - - return 0 /* not reached */; -} - -I64 Sinteger64_value(ptr x) { - return S_int64_value("Sinteger64_value", x); -} - -ptr Sunsigned(uptr u) { /* convert arg to Scheme integer */ - if (u <= most_positive_fixnum) - return FIX(u); - else { - ptr x = FIX(0); iptr xl; - UPTR_TO_BIGNUM(get_thread_context(), x, u, &xl) - SETBIGLENANDSIGN(x, xl, 0); - return x; - } -} - -ptr Sinteger(iptr i) { /* convert arg to Scheme integer */ - if (FIXRANGE(i)) - return FIX(i); - else { - ptr x = FIX(0); iptr xl; IBOOL xs; - IPTR_TO_BIGNUM(get_thread_context(), x, i, &xl, &xs) - SETBIGLENANDSIGN(x, xl, xs); - return x; - } -} - -ptr Sunsigned32(U32 u) { /* convert arg to Scheme integer */ -#if (fixnum_bits > 32) - return FIX((uptr)u); -#else - if (u <= most_positive_fixnum) - return FIX((uptr)u); - else { - ptr x = FIX(0); iptr xl; - U32_TO_BIGNUM(get_thread_context(), x, u, &xl) - SETBIGLENANDSIGN(x, xl, 0); - return x; - } -#endif -} - -ptr Sinteger32(I32 i) { /* convert arg to Scheme integer */ -#if (fixnum_bits > 32) - return FIX((iptr)i); -#else - if (i > most_negative_fixnum && i <= most_positive_fixnum) - return FIX((iptr)i); - else { - ptr x = FIX(0); iptr xl; IBOOL xs; - I32_TO_BIGNUM(get_thread_context(), x, i, &xl, &xs) - SETBIGLENANDSIGN(x, xl, xs); - return x; - } -#endif -} - -ptr Sunsigned64(U64 u) { /* convert arg to Scheme integer */ - if (u <= most_positive_fixnum) - return FIX((uptr)u); - else { - ptr x = FIX(0); iptr xl; - U64_TO_BIGNUM(get_thread_context(), x, u, &xl) - SETBIGLENANDSIGN(x, xl, 0); - return x; - } -} - -ptr Sinteger64(I64 i) { /* convert arg to Scheme integer */ - if (i > most_negative_fixnum && i <= most_positive_fixnum) - return FIX((iptr)i); - else { - ptr x = FIX(0); iptr xl; IBOOL xs; - I64_TO_BIGNUM(get_thread_context(), x, i, &xl, &xs) - SETBIGLENANDSIGN(x, xl, xs); - return x; - } -} - -/* extended arithmetic macros: use w/o trailing semicolon */ -#define ELSH(n,x,k) { /* undefined when n == 0 */\ - INT _n_ = (INT)(n); bigit _b_ = *(x), _newk_ = _b_>>(bigit_bits-_n_);\ - *(x) = _b_<<_n_ | *(k);\ - *(k) = _newk_;} - -#define ERSH(n,x,k) { /* undefined when n == 0 */\ - INT _n_ = (INT)(n); bigit _b_ = *(x), _newk_ = _b_<<(bigit_bits-_n_);\ - *(x) = _b_>>_n_ | *(k);\ - *(k) = _newk_;} - -#define ERSH2(n,x,y,k) { /* undefined when n == 0 */\ - INT _n_ = (INT)(n); bigit _b_ = (x), _newk_ = _b_<<(bigit_bits-_n_);\ - *(y) = _b_>>_n_ | *(k);\ - *(k) = _newk_;} - -#define EADDC(a1, a2, sum, k) {\ - bigit _tmp1_, _tmp2_, _tmpk_;\ - _tmp1_ = (a1);\ - _tmp2_ = _tmp1_ + (a2);\ - _tmpk_ = _tmp2_ < _tmp1_;\ - _tmp1_ = _tmp2_ + *(k);\ - *k = _tmpk_ + (_tmp1_ < _tmp2_);\ - *sum = _tmp1_;} - -#define ESUBC(s1, s2, diff, b) {\ - bigit _tmp1_, _tmp2_, tmpb;\ - _tmp1_ = (s1);\ - _tmp2_ = _tmp1_ - (s2);\ - tmpb = _tmp2_ > _tmp1_;\ - _tmp1_ = _tmp2_ - *(b);\ - *b = tmpb + (_tmp1_ > _tmp2_);\ - *diff = _tmp1_;} - -/* bigit x bigit -> bigitbigit */ -#define EMUL(m1,m2,a1,low,high) {\ - bigitbigit _tmp_;\ - _tmp_ = (bigitbigit)m1 * m2 + a1;\ - *low = (bigit)(_tmp_ & (bigitbigit)bigit_mask);\ - *high = (bigit)(_tmp_ >> bigit_bits);} - -/* bigitbigit / bigit -> bigit */ -#define EDIV(high,low,divr,quo,rem) {\ - bigit _tmpr_; bigitbigit _tmp_;\ - _tmp_ = ((bigitbigit)high << bigit_bits) | low;\ - _tmpr_ = divr;\ - *quo = (bigit)(_tmp_ / _tmpr_);\ - *rem = (bigit)(_tmp_ % _tmpr_);} - -/* -*** -comparison -*** -*/ - -IBOOL S_big_lt(ptr x, ptr y) { - if (BIGSIGN(x)) - if (BIGSIGN(y)) - return abs_big_lt(y, x, BIGLEN(y), BIGLEN(x)); /* both negative */ - else - return 1; /* x negative, y positive */ - else - if (BIGSIGN(y)) - return 0; /* x positive, y negative */ - else - return abs_big_lt(x, y, BIGLEN(x), BIGLEN(y)); /* both positive */ -} - -IBOOL S_big_eq(ptr x, ptr y) { - return (BIGSIGN(x) == BIGSIGN(y)) && abs_big_eq(x, y, BIGLEN(x), BIGLEN(y)); -} - -static IBOOL abs_big_lt(ptr x, ptr y, iptr xl, iptr yl) { - if (xl != yl) - return xl < yl; - else { - bigit *xp, *yp; - - for (xp = &BIGIT(x,0), yp = &BIGIT(y,0); xl-- > 0; xp++, yp++) - if (*xp != *yp) return (*xp < *yp); - - return 0; - } -} - -static IBOOL abs_big_eq(ptr x, ptr y, iptr xl, iptr yl) { - if (xl != yl) - return 0; - else { - bigit *xp, *yp; - - for (xp = &BIGIT(x,0), yp = &BIGIT(y,0); xl-- > 0; xp++, yp++) - if (*xp != *yp) return 0; - - return 1; - } -} - -/* -*** -addition/subtraction -*** -*/ - -static ptr big_negate(ptr tc, ptr x) { - return copy_normalize(tc, &BIGIT(x,0),BIGLEN(x),!BIGSIGN(x)); -} - -ptr S_big_negate(ptr x) { - return big_negate(get_thread_context(), x); -} - -/* assumptions: BIGLEN(x) >= BIGLEN(y) */ -static ptr big_add_pos(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL sign) { - iptr i; - bigit *xp, *yp, *zp; - bigit k = 0; - - PREPARE_BIGNUM(tc, W(tc),xl+1) - - xp = &BIGIT(x,xl-1); yp = &BIGIT(y,yl-1); zp = &BIGIT(W(tc),xl); - - for (i = yl; i-- > 0; ) - EADDC(*xp--, *yp--, zp--, &k) - for (i = xl - yl; k != 0 && i-- > 0; ) - EADDC(*xp--, 0, zp--, &k) - for (; i-- > 0; ) - *zp-- = *xp--; - - *zp = k; - - return copy_normalize(tc, zp,xl+1,sign); -} - -/* assumptions: x >= y */ -static ptr big_add_neg(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL sign) { - iptr i; - bigit *xp, *yp, *zp; - bigit b = 0; - - PREPARE_BIGNUM(tc, W(tc),xl) - - xp = &BIGIT(x,xl-1); yp = &BIGIT(y,yl-1); zp = &BIGIT(W(tc),xl-1); - - for (i = yl; i-- > 0; ) - ESUBC(*xp--, *yp--, zp--, &b) - for (i = xl-yl; b != 0 && i-- > 0; ) - ESUBC(*xp--, 0, zp--, &b) - for (; i-- > 0; ) - *zp-- = *xp--; - - return copy_normalize(tc, zp+1,xl,sign); -} - -static ptr big_add(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL xs, IBOOL ys) { - if (xs == ys) - if (xl < yl) - return big_add_pos(tc, y, x, yl, xl, xs); - else - return big_add_pos(tc, x, y, xl, yl, xs); - else - if (abs_big_lt(x, y, xl, yl)) - return big_add_neg(tc, y, x, yl, xl, ys); - else - return big_add_neg(tc, x, y, xl, yl, xs); -} - -/* arguments must be integers, fixnums or bignums */ -ptr S_add(ptr x, ptr y) { - ptr tc = get_thread_context(); - - if (Sfixnump(x)) { - if (Sfixnump(y)) { - iptr n = UNFIX(x) + UNFIX(y); - return FIXRANGE(n) ? FIX(n) : Sinteger(n); - } else { - iptr xl; IBOOL xs; - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs) - return big_add(tc, X(tc), y, xl, BIGLEN(y), xs, BIGSIGN(y)); - } - } else { - if (Sfixnump(y)) { - iptr yl; IBOOL ys; - FIXNUM_TO_BIGNUM(tc,Y(tc),y,&yl,&ys) - return big_add(tc, x, Y(tc), BIGLEN(x), yl, BIGSIGN(x), ys); - } else { - return big_add(tc, x, y, BIGLEN(x), BIGLEN(y), BIGSIGN(x), BIGSIGN(y)); - } - } -} - -/* arguments must be integers, fixnums or bignums */ -ptr S_sub(ptr x, ptr y) { - ptr tc = get_thread_context(); - - if (Sfixnump(x)) { - if (Sfixnump(y)) { - iptr n = UNFIX(x) - UNFIX(y); - return FIXRANGE(n) ? FIX(n) : Sinteger(n); - } else { - iptr xl; IBOOL xs; - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs) - return big_add(tc, X(tc), y, xl, BIGLEN(y), xs, !BIGSIGN(y)); - } - } else { - if (Sfixnump(y)) { - iptr yl; IBOOL ys; - FIXNUM_TO_BIGNUM(tc,Y(tc),y,&yl,&ys) - return big_add(tc, x, Y(tc), BIGLEN(x), yl, BIGSIGN(x), !ys); - } else { - return big_add(tc, x, y, BIGLEN(x), BIGLEN(y), BIGSIGN(x), !BIGSIGN(y)); - } - } -} - -/* -*** -multiplication -*** -*/ - -static ptr big_mul(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL sign) { - iptr xi, yi; - bigit *xp, *yp, *zp, *zpa; - bigit k, k1, prod; - - PREPARE_BIGNUM(tc, W(tc),xl+yl) - for (xi = xl, zp = &BIGIT(W(tc),xl+yl-1); xi-- > 0; ) *zp-- = 0; - - for (yi=yl,yp= &BIGIT(y,yl-1),zp= &BIGIT(W(tc),xl+yl-1); yi-- > 0; yp--, zp--) - if (*yp == 0) - *(zp-xl) = 0; - else { - for (xi=xl,k=0,zpa=zp,xp= &BIGIT(x,xl-1); xi-- > 0; xp--,zpa--) { - EMUL(*xp, *yp, *zpa, &prod, &k1) - EADDC(prod, 0, zpa, &k) - k += k1; - } - *zpa = k; - } - - return copy_normalize(tc, &BIGIT(W(tc),0),xl+yl,sign); -} - -/* SHORTRANGE is -floor(sqrt(most_positive_fixnum))..floor(sqrt(most_positive_fixnum)). - We don't use sqrt because it rounds up for fixnum_bits = 61 */ -#if (fixnum_bits == 30) -#define SHORTRANGE(x) (-23170 <= (x) && (x) <= 23170) -#elif (fixnum_bits == 61) -#define SHORTRANGE(x) (-0x3FFFFFFF <= (x) && (x) <= 0x3FFFFFFF) -#endif - -ptr S_mul(ptr x, ptr y) { - ptr tc = get_thread_context(); - - iptr xl, yl; IBOOL xs, ys; - - if (Sfixnump(x)) { - if (Sfixnump(y)) { - iptr xn = UNFIX(x); - iptr yn = UNFIX(y); - if (SHORTRANGE(xn) && SHORTRANGE(yn)) - return FIX(xn * yn); - else { - FIXNUM_TO_BIGNUM(tc, X(tc),x,&xl,&xs) x = X(tc); - FIXNUM_TO_BIGNUM(tc, Y(tc),y,&yl,&ys) y = Y(tc); - } - } else { - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs) x = X(tc); - yl = BIGLEN(y); ys = BIGSIGN(y); - } - } else { - if (Sfixnump(y)) { - xl = BIGLEN(x); xs = BIGSIGN(x); - FIXNUM_TO_BIGNUM(tc,Y(tc),y,&yl,&ys) y = Y(tc); - } else { - xl = BIGLEN(x); xs = BIGSIGN(x); - yl = BIGLEN(y); ys = BIGSIGN(y); - } - } - return big_mul(tc, x, y, xl, yl, xs ^ ys); -} - -/* -*** -division -*** -*/ - -/* arguments must be integers (fixnums or bignums), y must be nonzero */ -ptr S_div(ptr x, ptr y) { - ptr g, n, d; - ptr tc = get_thread_context(); - - g = S_gcd(x,y); - if (Sfixnump(y) ? UNFIX(y) < 0 : BIGSIGN(y)) { - g = Sfixnump(g) ? Sinteger(-UNFIX(g)) : big_negate(tc, g); - } - - S_trunc_rem(tc, x, g, &n, (ptr *)NULL); - S_trunc_rem(tc, y, g, &d, (ptr *)NULL); - - return S_rational(n, d); -} - -ptr S_trunc(ptr x, ptr y) { - ptr q; - S_trunc_rem(get_thread_context(), x, y, &q, (ptr *)NULL); - return q; -} - -ptr S_rem(ptr x, ptr y) { - ptr r; - S_trunc_rem(get_thread_context(), x, y, (ptr *)NULL, &r); - return r; -} - -/* arguments must be integers (fixnums or bignums), y must be nonzero */ -void S_trunc_rem(ptr tc, ptr origx, ptr y, ptr *q, ptr *r) { - iptr xl, yl; IBOOL xs, ys; ptr x = origx; - - if (Sfixnump(x)) { - if (Sfixnump(y)) { - if (x == FIX(most_negative_fixnum) && y == FIX(-1)) { - iptr m = most_negative_fixnum /* pull out to avoid bogus Sun C warning */; - if (q != (ptr)NULL) *q = Sinteger(-m); - if (r != (ptr)NULL) *r = FIX(0); - return; - } else { - if (q != (ptr)NULL) *q = FIX((iptr)x / (iptr)y); - if (r != (ptr)NULL) *r = (ptr)((iptr)x % (iptr)y); - return; - } - } else { - FIXNUM_TO_BIGNUM(tc, X(tc),x,&xl,&xs) x = X(tc); - yl = BIGLEN(y); ys = BIGSIGN(y); - } - } else { - if (Sfixnump(y)) { - xl = BIGLEN(x); xs = BIGSIGN(x); - FIXNUM_TO_BIGNUM(tc, Y(tc),y,&yl,&ys) y = Y(tc); - } else { - xl = BIGLEN(x); xs = BIGSIGN(x); - yl = BIGLEN(y); ys = BIGSIGN(y); - } - } - - if (xl < yl) { - if (q != (ptr *)NULL) *q = FIX(0); - if (r != (ptr *)NULL) *r = origx; - } else if (yl == 1) /* must have two bigits for full algorithm */ - big_short_trunc(tc, x, BIGIT(y,0), xl, xs^ys, xs, q, r); - else - big_trunc(tc, x, y, xl, yl, xs^ys, xs, q, r); -} - -/* sparc C compiler barfs w/o full declaration */ -static void big_short_trunc(ptr tc, ptr x, bigit s, iptr xl, IBOOL qs, IBOOL rs, ptr *q, ptr *r) { - iptr i; - bigit *xp, *zp; - bigit k; - - PREPARE_BIGNUM(tc, W(tc),xl) - - for (i = xl, k = 0, xp = &BIGIT(x,0), zp = &BIGIT(W(tc),0); i-- > 0; ) - EDIV(k, *xp++, s, zp++, &k) - - if (q != (ptr *)NULL) *q = copy_normalize(tc, &BIGIT(W(tc),0),xl,qs); - if (r != (ptr *)NULL) *r = copy_normalize(tc, &k,1,rs); -} - -static void big_trunc(tc, x, y, xl, yl, qs, rs, q, r) - ptr tc, x, y; iptr xl, yl; IBOOL qs, rs; ptr *q, *r; { - iptr i; - bigit *p, *xp, *yp; - iptr m = xl-yl+1; - INT d; - bigit k; - - PREPARE_BIGNUM(tc, U(tc), xl+1) - for (i = xl, xp = &BIGIT(U(tc),xl+1), p = &BIGIT(x,xl); i-- > 0;) *--xp = *--p; - *--xp = 0; - - PREPARE_BIGNUM(tc, V(tc), yl) - for (i = yl, yp = &BIGIT(V(tc),yl), p = &BIGIT(y,yl); i-- > 0;) *--yp = *--p; - - d = normalize(xp, yp, xl, yl); - - if (q == (ptr *)NULL) { - for (i = m; i-- > 0 ; xp++) (void) quotient_digit(xp, yp, yl); - } else { - PREPARE_BIGNUM(tc, W(tc),m) - p = &BIGIT(W(tc),0); - for (i = m; i-- > 0 ; xp++) *p++ = quotient_digit(xp, yp, yl); - *q = copy_normalize(tc, &BIGIT(W(tc),0),m,qs); - } - - if (r != (ptr *)NULL) { - /* unnormalize the remainder */ - if (d != 0) { - for (i = yl, p = xp, k = 0; i-- > 0; p++) ERSH(d,p,&k) - } - *r = copy_normalize(tc, xp, yl, rs); - } -} - -static INT normalize(bigit *xp, bigit *yp, iptr xl, iptr yl) { - iptr i; - bigit *p, k, b; - INT shft; - - for (shft = bigit_bits-1, b = *yp; b >>= 1; shft -= 1); - - if (shft != 0) { - for (i = yl, p = yp+yl-1, k = 0; i-- > 0; p--) ELSH(shft,p,&k) - for (i = xl, p = xp+xl, k = 0; i-- > 0; p--) ELSH(shft,p,&k) - *xp = k; - } - - return shft; -} - -static bigit quotient_digit(bigit *xp, bigit *yp, iptr yl) { - bigit *p1, *p2, q, k, b, prod; - iptr i; - - q = qhat(xp, yp); - - for (i = yl, p1 = xp+yl, p2 = yp+yl-1, k = 0, b = 0; i-- > 0; p1--, p2--) { - EMUL(*p2, q, k, &prod, &k) - ESUBC(*p1, prod, p1, &b) - } - - ESUBC(*p1, k, p1, &b) - - if (b != 0) { - for (i = yl, p1 = xp+yl, p2 = yp+yl-1, k = 0; i-- > 0; p1--, p2--) { - EADDC(*p2, *p1, p1, &k) - } - EADDC(0,*p1,p1,&k) - q--; - } - - return q; -} - -static bigit qhat(bigit *xp, bigit *yp) { - bigit q, r, high, low, k; - - k = 0; - - if (*xp == *yp) { - q = bigit_mask; - EADDC(*(xp+1), *yp, &r, &k) - } else { - EDIV(*xp, *(xp+1), *yp, &q, &r) - } - - for (; k == 0; q--) { - EMUL(*(yp+1), q, 0, &low, &high) - if (high < r || (high == r && low <= *(xp+2))) break; - EADDC(r, *yp, &r, &k) - } - - return q; -} - -/* -*** -gcd -*** -*/ - -static ptr uptr_gcd(uptr x, uptr y) { - uptr r; - - while (y != 0) { - r = x % y; - x = y; - y = r; - } - - return Sunsigned(x); -} - -/* sparc C compiler barfs w/o full declaration */ -static ptr big_short_gcd(ptr tc, ptr x, bigit y, iptr xl) { - bigit *xp; - iptr i; - bigit r, q; - - if (y == 0) return BIGSIGN(x) ? big_negate(tc, x) : x; - - for (i = xl, r = 0, xp = &BIGIT(x,0); i-- > 0; ) - EDIV(r, *xp++, y, &q, &r) - - return uptr_gcd((uptr)y,(uptr)r); -} - -static ptr big_gcd(ptr tc, ptr x, ptr y, iptr xl, iptr yl) { - iptr i; - INT shft, asc; - bigit *p, *xp, *yp, k, b; - - /* Copy x to scratch bignum, with a leading zero */ - PREPARE_BIGNUM(tc, U(tc),xl+1) - xp = &BIGIT(U(tc),xl+1); - for (i = xl, p = &BIGIT(x,xl); i-- > 0; ) *--xp = *--p; - *--xp = 0; /* leave xp pointing at leading 0-bigit */ - - /* Copy y to scratch bignum, with a leading zero */ - PREPARE_BIGNUM(tc, V(tc),yl+1) - yp = &BIGIT(V(tc),yl+1); - for (i = yl, p = &BIGIT(y,yl); i-- > 0; ) *--yp = *--p; - *(yp-1) = 0; /* leave yp pointing just after leading 0-bigit */ - - /* initialize aggregate shift count (asc) */ - asc = 0; - - for (;;) { - /* find number of leading zeros in first bigit of y */ - for (shft = bigit_bits - 1, b = *yp; b >>= 1; shft--); - - /* find directed distance to shift and new asc */ - if (asc+shft >= bigit_bits) shft -= bigit_bits; - asc += shft; - - /* shift left or right; adjust lengths, xp and yp */ - if (shft < 0) { /* shift right */ - for (i = yl--, p = yp++, k = 0; i-- > 0; p++) ERSH(-shft,p,&k) - for (i = xl+1, p = xp, k = 0; i-- > 0; p++) ERSH(-shft,p,&k) - /* don't need two leading zeros */ - if (*(xp+1) == 0) xp++, xl--; - /* we have shrunk y, so test the length here */ - if (yl == 1) break; - } else if (shft > 0) { /* left shift */ - for (i=yl, p=yp+yl-1, k=0; i-- > 0; p--) ELSH(shft,p,&k) - for (i=xl+1, p=xp+xl, k=0; i-- > 0; p--) ELSH(shft,p,&k) - } - - /* destructive remainder x = x rem y */ - for (i = xl-yl+1; i-- > 0; xp++) (void) quotient_digit(xp, yp, yl); - - /* strip leading zero bigits. remainder is at most yl bigits long */ - for (i = yl ; *xp == 0 && i > 0; xp++, i--); - - /* swap x and y */ - p = yp; /* leading bigit of y */ - yp = xp; /* remainder */ - xp = p-1; /* new dividend w/leading zero */ - xl = yl; - yl = i; - - /* may have lopped off all or all but one bigit of the remainder */ - if (yl <= 1) break; - } - - /* point xp after the leading zero */ - xp += 1; - - /* if y is already zero, shift x and leave */ - if (yl == 0) { - if (asc != 0) { - for (i = xl, p = xp, k = 0; i-- > 0; p++) ERSH(asc,p,&k) - } - return copy_normalize(tc, xp,xl,0); - } else { - bigit d, r; - - d = *yp; - for (r = 0; xl-- > 0; xp++) EDIV(r, *xp, d, xp, &r) - return uptr_gcd((uptr)(d>>asc), (uptr)(r>>asc)); - } -} - -ptr S_gcd(ptr x, ptr y) { - ptr tc = get_thread_context(); - iptr xl, yl; IBOOL xs, ys; - - if (Sfixnump(x)) - if (Sfixnump(y)) { - iptr xi = UNFIX(x), yi = UNFIX(y); - if (xi < 0) xi = -xi; - if (yi < 0) yi = -yi; - return xi >= yi ? - uptr_gcd((uptr)xi, (uptr)yi) : - uptr_gcd((uptr)yi, (uptr)xi); - } else { - FIXNUM_TO_BIGNUM(tc, X(tc),x,&xl,&xs) x = X(tc); - yl = BIGLEN(y); ys = BIGSIGN(y); - } - else - if (Sfixnump(y)) { - xl = BIGLEN(x); xs = BIGSIGN(x); - FIXNUM_TO_BIGNUM(tc, Y(tc),y,&yl,&ys) y = Y(tc); - } else { - xl = BIGLEN(x); xs = BIGSIGN(x); - yl = BIGLEN(y); ys = BIGSIGN(y); - } - - if (xl == 1) - if (yl == 1) { - uptr xu = BIGIT(x,0), yu = BIGIT(y,0); - return xu >= yu ? uptr_gcd(xu, yu) : uptr_gcd(yu, xu); - } else - return big_short_gcd(tc, y, BIGIT(x,0), yl); - else - if (yl == 1) - return big_short_gcd(tc, x, BIGIT(y,0), xl); - else - if (abs_big_lt(x, y, xl, yl)) - return big_gcd(tc, y, x, yl, xl); - else - return big_gcd(tc, x, y, xl, yl); -} - -/* -*** -floating-point operations -*** -*/ - -#ifdef IEEE_DOUBLE -/* exponent stored + 1024, hidden bit to left of decimal point */ -#define bias 1023 -#define bitstoright 52 -#define m1mask 0xf -#ifdef WIN32 -#define hidden_bit 0x10000000000000 -#else -#define hidden_bit 0x10000000000000ULL -#endif -#ifdef LITTLE_ENDIAN_IEEE_DOUBLE -struct dblflt { - UINT m4: 16; - UINT m3: 16; - UINT m2: 16; - UINT m1: 4; - UINT e: 11; - UINT sign: 1; -}; -#else -struct dblflt { - UINT sign: 1; - UINT e: 11; - UINT m1: 4; - UINT m2: 16; - UINT m3: 16; - UINT m4: 16; -}; -#endif -#endif - -double S_random_double(U32 m1, U32 m2, U32 m3, U32 m4, double scale) { - /* helper for s_fldouble in prim5.c */ - union dxunion { - double d; - struct dblflt x; - } dx; - - dx.x.m1 = m1 >> 16 & m1mask; - dx.x.m2 = m2 >> 16; - dx.x.m3 = m3 >> 16; - dx.x.m4 = m4 >> 16; - dx.x.sign = 0; - dx.x.e = bias; - return (dx.d - 1.0) * scale; -} - -/* number of quotient bigits to guarantee at least 64 bits */ -/* +2 since first bigit may be zero and second may not be full */ -#define enough (64 / bigit_bits + 2) - -/* sparc C compiler barfs w/o full declaration */ -static double big_short_floatify(ptr tc, ptr x, bigit s, iptr xl, IBOOL sign) { - iptr i; - bigit *xp, *zp, k; - - PREPARE_BIGNUM(tc, W(tc),enough+1) - - /* compute only as much of quotient as we need */ - for (i = 0, k = 0, xp = &BIGIT(x,0), zp = &BIGIT(W(tc),0); i < enough; i++) - if (i < xl) - EDIV(k, *xp++, s, zp++, &k) - else - EDIV(k, 0, s, zp++, &k) - - /* then see if there's a bit set somewhere beyond */ - while (k == 0 && i++ < xl) k = *xp++; - - return floatify_normalize(&BIGIT(W(tc),0), xl*bigit_bits, sign, k != 0); -} - -static double big_floatify(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL sign) { - iptr i, ul; - bigit *p, *xp, *yp, k; - - /* copy x to U(tc), scaling with added zero bigits as necessary */ - ul = xl < yl + enough-1 ? yl + enough-1 : xl; - PREPARE_BIGNUM(tc, U(tc), ul+1) - for (i = ul - xl, xp = &BIGIT(U(tc),ul+1); i-- > 0;) *--xp = 0; - for (i = xl, p = &BIGIT(x,xl); i-- > 0;) *--xp = *--p; - *--xp = 0; - - /* copy y to V(tc) */ - PREPARE_BIGNUM(tc, V(tc), yl) - for (i = yl, yp = &BIGIT(V(tc),yl), p = &BIGIT(y,yl); i-- > 0;) *--yp = *--p; - - (void) normalize(xp, yp, ul, yl); - - PREPARE_BIGNUM(tc, W(tc),4) - p = &BIGIT(W(tc),0); - - /* compute 'enough' bigits of the quotient */ - for (i = enough; i-- > 0; xp++) *p++ = quotient_digit(xp, yp, yl); - - /* set k if remainder is nonzero */ - k = 0; - for (i = ul + 1, xp = &BIGIT(U(tc),ul); k == 0 && i-- > 0; xp--) k = *xp; - - return floatify_normalize(&BIGIT(W(tc),0), (xl-yl+1)*bigit_bits, sign, k != 0); -} - -/* come in with exactly 'enough' bigits */ -static double floatify_normalize(bigit *p, iptr e, IBOOL sign, IBOOL sticky) { - /* *p: first bigit; e: exponent; sign: sign; sticky: sticky bit */ - union dxunion { - double d; - struct dblflt x; - } dx; - bigit mhigh; - U64 mlow; - IBOOL cutbit = 0; - INT n; - - /* shift in what we need, plus at least one bit */ - mhigh = 0; mlow = 0; n = enough; - while (mhigh == 0 && mlow < hidden_bit * 2) { - mhigh = (bigit)(mlow >> (64-bigit_bits)); - mlow = (mlow << bigit_bits) | *p++; - n -= 1; - e -= bigit_bits; - } - - /* back up to align high bit on hidden bit, setting cut bit to last loser */ - do { - sticky = sticky || cutbit; - cutbit = (bigit)(mlow & 1); - mlow = (U64)mhigh << 63 | mlow >> 1; - mhigh = mhigh >> 1; - e = e + 1; - } while (mhigh != 0 || mlow >= hidden_bit * 2); - - e = e + bitstoright + bias; - - /* back up further if denormalized */ - if (e <= 0) { - for (;;) { - sticky = sticky || cutbit; - cutbit = (bigit)(mlow & 1); - mlow = mlow >> 1; - if (e == 0 || mlow == 0) break; - e = e + 1; - } - } - - if (e < 0) { - e = 0; /* NB: e < 0 => mlow == 0 */ - } else { - /* round up if necessary */ - if (cutbit) { - IBOOL round; - /* cutbit = 1 => at least half way to next number. round up if odd or - if there are any bits set to the right of cutbit */ - round = (mlow & 1) || sticky; - while (!round && n-- > 0) round = *p++ != 0; - if (round) { - mlow += 1; - if (e == 0 && mlow == hidden_bit) { - e = 1; /* squeaking into lowest normalized spot */ - } else if (mlow == hidden_bit * 2) { - /* don't bother with mlow = mlow >> 1 since hidden bit and up are ignored after this */ - e += 1; - } - } - } - - if (e > 2046) { /* infinity */ - e = 2047; - mlow = 0; - } - } - - /* fill in the fields */ - dx.x.sign = sign; - dx.x.e = (UINT)e; - dx.x.m1 = (UINT)(mlow >> 48 & m1mask); - dx.x.m2 = (UINT)(mlow >> 32 & 0xffff); - dx.x.m3 = (UINT)(mlow >> 16 & 0xffff); - dx.x.m4 = (UINT)(mlow & 0xffff); - - return dx.d; -} - -static double floatify_ratnum(ptr tc, ptr p) { - ptr x, y; iptr xl, yl; IBOOL xs; - - x = RATNUM(p); y = RATDEN(p); - - if (fixnum_bits <= bitstoright && Sfixnump(x) && Sfixnump(y)) - return (double)UNFIX(x) / (double)UNFIX(y); - - /* make sure we are dealing with bignums */ - if (Sfixnump(x)) { - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs) - x = X(tc); - } else { - xl = BIGLEN(x); - xs = BIGSIGN(x); - } - - if (Sfixnump(y)) { - IBOOL ys; - FIXNUM_TO_BIGNUM(tc,Y(tc),y,&yl,&ys) - y = Y(tc); - } else { - yl = BIGLEN(y); - } - - /* need second bignum to be at least two bigits for full algorithm */ - if (yl == 1) - return big_short_floatify(tc, x, BIGIT(y,0), xl, xs); - else - return big_floatify(tc, x, y, xl, yl, xs); -} - -double S_floatify(ptr x) { - ptr tc = get_thread_context(); - - if (Sflonump(x)) return FLODAT(x); - else if (Sfixnump(x)) return (double)UNFIX(x); - else if (Sbignump(x)) return big_short_floatify(tc, x, 1, BIGLEN(x), BIGSIGN(x)); - else if (Sratnump(x)) return floatify_ratnum(tc, x); - else S_error1("", "~s is not a real number", x); - - return 0.0 /* not reached */; -} - -#ifdef IEEE_DOUBLE -ptr S_decode_float(double d) { - union dxunion { - double d; - struct dblflt x; - } dx; - IBOOL s; INT e; U64 m; - ptr x, p; - - /* pick apart the fields */ - dx.d = d; - s = dx.x.sign; - e = dx.x.e; - m = (U64)dx.x.m1 << 48 | (U64)dx.x.m2 << 32 | (U64)dx.x.m3 << 16 | (U64)dx.x.m4; - if (e != 0) { - e = e - bias - bitstoright; - m |= hidden_bit; - } else if (m != 0) { - /* denormalized */ - e = 1 - bias - bitstoright; - } - - /* compute significand */ - if (m <= most_positive_fixnum) - x = FIX((uptr)m); - else { - iptr xl; - x = FIX(0); - U64_TO_BIGNUM(get_thread_context(), x, m, &xl) - SETBIGLENANDSIGN(x, xl, 0); - } - - /* construct return vector */ - p = S_vector(3); - INITVECTIT(p,0) = x; - INITVECTIT(p, 1) = FIX(e); - INITVECTIT(p, 2) = s ? FIX(-1) : FIX(1); - return p; -} -#endif - -/* -*** -logical operations -*** -*/ - -static ptr s_big_ash(ptr tc, bigit *xp, iptr xl, IBOOL sign, iptr cnt) { - iptr i; - bigit *p1, *p2, k; - - if (cnt < 0) { /* shift to the right */ - iptr whole_bigits; - - /* decrement length to shift by whole bigits */ - if ((xl -= (whole_bigits = (cnt = -cnt) / bigit_bits)) <= 0) return sign ? FIX(-1) : FIX(0); - cnt -= whole_bigits * bigit_bits; - - /* shift by remaining count to scratch bignum, tracking bits shifted off to the right; - prepare a bignum one larger than probably needed, in case we have to deal with a - carry bit when rounding down for a negative number */ - PREPARE_BIGNUM(tc, W(tc),xl+1) - p1 = &BIGIT(W(tc), 0); - p2 = xp; - k = 0; - i = xl; - if (cnt == 0) { - do { *p1++ = *p2++; } while (--i > 0); - } else { - do { ERSH2(cnt,*p2,p1,&k); p1++; p2++; } while (--i > 0); - } - - if (sign) { - if (k == 0) { - /* check for one bits in the shifted-off bigits, looking */ - /* from both ends in an attempt to get out more quickly for what */ - /* seem like the most likely patterns. of course, there might */ - /* be no one bits (in which case this won't help) or they might be */ - /* only in the middle (in which case this will be slower) */ - p2 = (p1 = xp + xl) + whole_bigits; - while (p1 != p2) { - if ((k = *p1++) || p1 == p2 || (k = *--p2)) break; - } - } - - /* round down negative numbers by incrementing the magnitude if any - one bits were shifted off to the right */ - if (k) { - p1 = &BIGIT(W(tc), xl - 1); - for (i = xl, k = 1; k != 0 && i-- > 0; p1 -= 1) - EADDC(0, *p1, p1, &k) - if (k) { - /* add carry bit back; we prepared a large enough bignum, - and since all of the middle are zero, we don't have to reshift */ - BIGIT(W(tc), xl) = 0; - BIGIT(W(tc), 0) = 1; - xl++; - } - } - } - - return copy_normalize(tc, &BIGIT(W(tc), 0), xl, sign); - } else { /* shift to the left */ - iptr xlplus, newxl; - - /* determine how many zero bigits to add on the end */ - xlplus = 0; - while (cnt >= bigit_bits) { - xlplus += 1; - cnt -= bigit_bits; - } - - /* maximum total length includes +1 for shift out of top bigit */ - newxl = xl + xlplus + 1; - - PREPARE_BIGNUM(tc, W(tc),newxl) - - /* fill bigits to right with zero */ - for (i = xlplus, p1 = &BIGIT(W(tc), newxl); i-- > 0; ) *--p1 = 0; - - /* shift to the left */ - for (i = xl, p2 = xp + xl, k = 0; i-- > 0; ) { - *--p1 = *--p2; - if (cnt != 0) ELSH(cnt, p1, &k); - } - *--p1 = k; - - return copy_normalize(tc, p1, newxl, sign); - } -} - -/* x is a bignum or fixnum, n is a fixnum */ -ptr S_ash(ptr x, ptr n) { - ptr tc = get_thread_context(); - iptr cnt = UNFIX(n); - - if (Sfixnump(x)) { - /* when we get here with a fixnum, we've done what we could in Scheme - code to avoid use of bignums, so go straight to it. it's difficult to - do much here anyway since semantics of signed >> are undefined in C */ - iptr xl; IBOOL xs; - - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs); - return s_big_ash(tc, &BIGIT(X(tc),0), xl, xs, cnt); - } else - return s_big_ash(tc, &BIGIT(x,0), BIGLEN(x), BIGSIGN(x), cnt); -} - -/* x is a bignum */ -ptr S_integer_length(ptr x) { - iptr a; bigit b; - - if (BIGSIGN(x)) x = S_sub(FIX(-1), x); - - b = BIGIT(x, 0); - a = 1; - while (b >>= 1) a += 1; - - return S_add(S_mul(FIX(BIGLEN(x) - 1), FIX(bigit_bits)), FIX(a)); -} - -/* x is a bignum */ -ptr S_big_first_bit_set(ptr x) { - iptr xl = BIGLEN(x); - bigit *xp = &BIGIT(x, xl); - bigit b; - iptr zbigits = 0; - INT zbits = 0; - - /* first bit set in signed magnitude is same as for two's complement, - since if x ends with k zeros, ~x+1 also ends with k zeros. */ - while ((b = *--xp) == 0) zbigits += 1; - while ((b & 1) == 0) { zbits += 1; b >>= 1; } - return S_add(S_mul(FIX(zbigits), FIX(bigit_bits)), FIX(zbits)); -} - -/* assumes fxstart - fxend > 0 */ -ptr S_big_positive_bit_field(ptr x, ptr fxstart, ptr fxend) { - ptr tc = get_thread_context(); - bigit *xp = &BIGIT(x, 0); - iptr start = UNFIX(fxstart), end = UNFIX(fxend), xl = BIGLEN(x); - iptr wl, bigits, i; - bigit *p1, *p2, k; - uptr bits, maskbits; - - /* shift by whole bigits by decrementing length */ - bigits = (unsigned)start / bigit_bits; - xl -= bigits; - if (xl <= 0) return FIX(0); - bits = (unsigned)bigits * bigit_bits; - start -= bits; - end -= bits; - - /* compute maximum length of result */ - bigits = (unsigned)end / bigit_bits; - if (xl <= bigits) { - wl = xl; - maskbits = 0; - } else { - end -= (unsigned)bigits * bigit_bits; - if (end != 0) { - wl = bigits + 1; - maskbits = bigit_bits - end; - } else { - wl = bigits; - maskbits = 0; - } - } - - /* copy to scratch bignum */ - PREPARE_BIGNUM(tc, W(tc),wl) - p1 = &BIGIT(W(tc), wl); - for (i = wl, p2 = xp + xl; i-- > 0; ) *--p1 = *--p2; - - /* kill unwanted bits at the top of the first bigit */ - if (maskbits != 0) *p1 = (*p1 << maskbits) >> maskbits; - - /* shift by remaining start bits */ - if (start != 0) { - k = 0; - for (i = wl; i > 0; i -= 1, p1 += 1) ERSH(start,p1,&k) - } - - return copy_normalize(tc, &BIGIT(W(tc), 0), wl, 0); -} - -/* logical operations simulate two's complement operations using the - following general strategy: - - 1. break into cases based on signs of operands - - 2. convert negative operands to two's complement - - 3. operate - - 4. convert negative results to two's complement and set sign bit. - sign of result is known based on signs of operands - - simplifications are made where possible to reduce number of operations. - - # = 2's complement; #x = ~x + 1 = ~(x - 1) if x > 0 -*/ - -ptr S_logand(ptr x, ptr y) { - ptr tc = get_thread_context(); - - if (Sfixnump(x)) { - if (Sfixnump(y)) { - return (ptr)((iptr)x & (iptr)y); - } else { - iptr xl; IBOOL xs; - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs) - return big_logand(tc, y, X(tc), BIGLEN(y), xl, BIGSIGN(y), xs); - } - } else { - if (Sfixnump(y)) { - iptr yl; IBOOL ys; - FIXNUM_TO_BIGNUM(tc,Y(tc),y,&yl,&ys) - return big_logand(tc, x, Y(tc), BIGLEN(x), yl, BIGSIGN(x), ys); - } else { - if (BIGLEN(x) >= BIGLEN(y)) - return big_logand(tc, x, y, BIGLEN(x), BIGLEN(y), BIGSIGN(x), BIGSIGN(y)); - else - return big_logand(tc, y, x, BIGLEN(y), BIGLEN(x), BIGSIGN(y), BIGSIGN(x)); - } - } -} - -/* logand on signed-magnitude bignums - # = 2's complement; #x = ~x + 1 = ~(x - 1) if x > 0 - s&(x,y) = x&y know result >= 0 - s&(x,-y) = x&#y know result >= 0 - = x&~(y-1) - s&(-x,y) = s&(y,-x) - s&(-x,-y) = -(#(#x&#y)) know result < 0 - = -(~(~(x-1)&~(y-1))+1) - = -(((x-1)|(y-1))+1) de morgan's law -*/ - -/* assumes xl >= yl */ -static ptr big_logand(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL xs, IBOOL ys) { - iptr i; - bigit *xp, *yp, *zp; - - if (xs == 0) { - if (ys == 0) { - PREPARE_BIGNUM(tc, W(tc),yl); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),yl); - for (i = yl; i > 0; i -= 1) *--zp = *--xp & *--yp; - return copy_normalize(tc, zp, yl, 0); - } else { - bigit yb; - - PREPARE_BIGNUM(tc, W(tc),xl); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),xl); - yb = 1; - for (i = yl; i > 0; i -= 1) { - bigit t1 = *--yp, t2 = t1 - yb; - yb = t2 > t1; - *--zp = *--xp & ~t2; - } - /* yb must be 0, since high-order bigit >= 1. effectively, this - means ~t2 would be all 1's from here on out. */ - for (i = xl - yl; i > 0; i -= 1) *--zp = *--xp; - return copy_normalize(tc, zp, xl, 0); - } - } else { - if (ys == 0) { - bigit xb; - - PREPARE_BIGNUM(tc, W(tc),yl); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),yl); - xb = 1; - for (i = yl; i > 0; i -= 1) { - bigit t1 = *--xp, t2 = t1 - xb; - xb = t2 > t1; - *--zp = *--yp & ~t2; - } - return copy_normalize(tc, zp, yl, 0); - } else { - bigit xb, yb, k; - - PREPARE_BIGNUM(tc, W(tc),xl+1); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),xl+1); - k = yb = xb = 1; - for (i = yl; i > 0; i -= 1) { - bigit x1, x2, y1, y2, z1, z2; - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - y1 = *--yp; y2 = y1 - yb; yb = y2 > y1; - z1 = x2 | y2; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - for (i = xl - yl; i > 0; i -= 1) { - bigit x1, x2, z1, z2; - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - z1 = x2; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - *--zp = k; - return copy_normalize(tc, zp, xl+1, 1); - } - } -} - -/* logtest is like logand but returns a boolean value */ - -ptr S_logtest(ptr x, ptr y) { - ptr tc = get_thread_context(); - - if (Sfixnump(x)) { - if (Sfixnump(y)) { - return Sboolean((iptr)x & (iptr)y); - } else { - iptr xl; IBOOL xs; - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs) - return big_logtest(y, X(tc), BIGLEN(y), xl, BIGSIGN(y), xs); - } - } else { - if (Sfixnump(y)) { - iptr yl; IBOOL ys; - FIXNUM_TO_BIGNUM(tc,Y(tc),y,&yl,&ys) - return big_logtest(x, Y(tc), BIGLEN(x), yl, BIGSIGN(x), ys); - } else { - if (BIGLEN(x) >= BIGLEN(y)) - return big_logtest(x, y, BIGLEN(x), BIGLEN(y), BIGSIGN(x), BIGSIGN(y)); - else - return big_logtest(y, x, BIGLEN(y), BIGLEN(x), BIGSIGN(y), BIGSIGN(x)); - } - } -} - -/* essentially the same logic as big_logand, but just produces true iff - logand would return a nonzero value */ - -/* assumes xl >= yl */ -static ptr big_logtest(ptr x, ptr y, iptr xl, iptr yl, IBOOL xs, IBOOL ys) { - iptr i; - bigit *xp, *yp; - - if (xs == 0) { - if (ys == 0) { - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); - for (i = yl; i > 0; i -= 1) if (*--xp & *--yp) return Strue; - return Sfalse; - } else { - bigit yb; - - if (xl > yl) return Strue; - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); - yb = 1; i = yl; - for (;;) { - bigit t1 = *--yp, t2 = t1 - yb; - if (*--xp & ~t2) return Strue; - if (--i == 0) return Sfalse; - yb = t2 > t1; - } - } - } else { - if (ys == 0) { - bigit xb; - - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); - xb = 1; i = yl; - for (;;) { - bigit t1 = *--xp, t2 = t1 - xb; - if (*--yp & ~t2) return Strue; - if (--i == 0) return Sfalse; - xb = t2 > t1; - } - } else { - /* logand of two negative bignums is always nonzero */ - return Strue; - } - } -} - -/* k must be a nonnegative fixnum. x may be a bignum or fixnum */ -ptr S_logbitp(ptr k, ptr x) { - uptr n = UNFIX(k); - - if (Sfixnump(x)) { - if (n >= fixnum_bits) - return Sboolean((iptr)x < 0); - else - return Sboolean((iptr)x & ((iptr)FIX(1) << n)); - } else { - return big_logbitp(n, x, BIGLEN(x), BIGSIGN(x)); - } -} - -/* similar logic to big_logand */ - -static ptr big_logbitp(iptr n, ptr x, iptr xl, IBOOL xs) { - iptr i; - bigit *xp; - - if (xs == 0) { - i = xl - (n / bigit_bits + 1); - if (i < 0) return Sfalse; - - n = n % bigit_bits; - return Sboolean(BIGIT(x,i) & (1 << n)); - } else { - bigit xb; - - /* get out quick when 2^n has more bigits than x */ - if (n / bigit_bits >= xl) return Strue; - - xp = &BIGIT(x,xl); xb = 1; - for (i = xl; ; i -= 1) { - bigit t1 = *--xp, t2 = t1 - xb; - if (n < bigit_bits) return Sboolean(~t2 & (1 << n)); - xb = t2 > t1; - n -= bigit_bits; - } - } -} - -/* k must be a nonnegative fixnum. x may be a bignum or fixnum */ -ptr S_logbit0(ptr k, ptr x) { - ptr tc = get_thread_context(); - iptr n = UNFIX(k); - - if (Sfixnump(x)) { - if (n < fixnum_bits - 1) { - return FIX(UNFIX(x) & ~(1 << n)); - } else { - iptr xl; IBOOL xs; - - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs); - return big_logbit0(tc, x, n, X(tc), xl, xs); - } - } else { - return big_logbit0(tc, x, n, x, BIGLEN(x), BIGSIGN(x)); - } -} - -/* logbit0 on signed-magnitude bignums - y = 1 << n - s&(x,~y) = x&~y know result >= 0 - s&(-x,~y) = -#(#x&~y) know result < 0 - = -(~(~(x-1)&~y)+1) - = -(((x-1)|y)+1) -*/ - -/* adapted from big_logor algorithm */ -static ptr big_logbit0(ptr tc, ptr origx, iptr n, ptr x, iptr xl, IBOOL xs) { - iptr i; - bigit *xp, *zp; - iptr yl = (n / bigit_bits) + 1; - - if (xs == 0) { - if (yl > xl) { - /* we'd just be clearing a bit that's already (virtually) cleared */ - return origx; - } else { - PREPARE_BIGNUM(tc, W(tc),xl); - xp = &BIGIT(x,xl); zp = &BIGIT(W(tc),xl); - for (;;) { - if (n < bigit_bits) break; - *--zp = *--xp; - n -= bigit_bits; - } - *--zp = *--xp & ~(1 << n); - for (i = xl - yl; i > 0; i -= 1) *--zp = *--xp; - return copy_normalize(tc, zp,xl,0); - } - } else { - bigit xb, k, x1, x2, z1, z2; - iptr zl = (yl > xl ? yl : xl) + 1; - - PREPARE_BIGNUM(tc, W(tc),zl); - xp = &BIGIT(x,xl); zp = &BIGIT(W(tc),zl); - k = xb = 1; - i = xl; - for (;;) { - if (i > 0) { x1 = *--xp; i -= 1; } else x1 = 0; - x2 = x1 - xb; xb = x2 > x1; - if (n < bigit_bits) break; - z1 = x2; z2 = z1 + k; k = z2 < z1; - *--zp = z2; - n -= bigit_bits; - } - z1 = x2 | (1 << n); z2 = z1 + k; k = z2 < z1; - *--zp = z2; - for (; i > 0; i -= 1) { - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - z1 = x2; z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - *--zp = k; - return copy_normalize(tc, zp, zl, 1); - } -} - -/* k must be a nonnegative fixnum. x may be a bignum or fixnum */ -ptr S_logbit1(ptr k, ptr x) { - ptr tc = get_thread_context(); - iptr n = UNFIX(k); - - if (Sfixnump(x)) { - if (n < fixnum_bits - 1) { - return FIX(UNFIX(x) | ((uptr)1 << n)); - } else { - iptr xl; IBOOL xs; - - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs); - return big_logbit1(tc, x, n, X(tc), xl, xs); - } - } else { - return big_logbit1(tc, x, n, x, BIGLEN(x), BIGSIGN(x)); - } -} - -/* adapted from big_logor algorithm */ -static ptr big_logbit1(ptr tc, ptr origx, iptr n, ptr x, iptr xl, IBOOL xs) { - iptr i; - bigit *xp, *zp; - iptr yl = (n / bigit_bits) + 1; - - if (xs == 0) { - bigit x1; - iptr zl = yl > xl ? yl : xl; - - PREPARE_BIGNUM(tc, W(tc),zl); - xp = &BIGIT(x,xl); zp = &BIGIT(W(tc),zl); - - i = xl; - for (;;) { - if (i > 0) { x1 = *--xp; i -= 1; } else x1 = 0; - if (n < bigit_bits) break; - *--zp = x1; - n -= bigit_bits; - } - *--zp = x1 | (1 << n); - for (; i > 0; i -= 1) *--zp = *--xp; - return copy_normalize(tc, zp, zl, 0); - } else if (yl > xl) { - /* we'd just be setting a bit that's already (virtually) set */ - return origx; - } else { /* xl >= yl */ - bigit xb, k, x1, x2, z1, z2; - iptr zl = xl + 1; - - PREPARE_BIGNUM(tc, W(tc),zl); - xp = &BIGIT(x,xl); zp = &BIGIT(W(tc),zl); - k = xb = 1; - for (;;) { - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - if (n < bigit_bits) break; - z1 = x2; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - n -= bigit_bits; - } - z1 = x2 & ~(1 << n); - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - for (i = xl - yl; i > 0; i -= 1) { - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - z1 = x2; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - *--zp = k; - return copy_normalize(tc, zp, zl, 1); - } -} - -ptr S_logor(ptr x, ptr y) { - ptr tc = get_thread_context(); - - if (Sfixnump(x)) { - if (Sfixnump(y)) { - return (ptr)((iptr)x | (iptr)(y)); - } else { - iptr xl; IBOOL xs; - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs) - return big_logor(tc, y, X(tc), BIGLEN(y), xl, BIGSIGN(y), xs); - } - } else { - if (Sfixnump(y)) { - iptr yl; IBOOL ys; - FIXNUM_TO_BIGNUM(tc,Y(tc),y,&yl,&ys) - return big_logor(tc, x, Y(tc), BIGLEN(x), yl, BIGSIGN(x), ys); - } else { - if (BIGLEN(x) >= BIGLEN(y)) - return big_logor(tc, x, y, BIGLEN(x), BIGLEN(y), BIGSIGN(x), BIGSIGN(y)); - else - return big_logor(tc, y, x, BIGLEN(y), BIGLEN(x), BIGSIGN(y), BIGSIGN(x)); - } - } -} - -/* logor on signed-magnitude bignums - s|(x,y) = x|y know result >= 0 - s|(x,-y) = -(#(x|#y)) know result < 0 - = -(~(x|~(y-1))+1) - = -(((y-1)&~x)+1) - s|(-x,y) = -(((x-1)&~y)+1) - s|(-x,-y) = -(#(#x|#y)) know result < 0 - = -(~(~(x-1)|~(y-1))+1) - = -(((x-1)&(y-1))+1) de morgan's law -*/ - -/* assumes xl >= yl */ -static ptr big_logor(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL xs, IBOOL ys) { - iptr i; - bigit *xp, *yp, *zp; - - if (xs == 0) { - if (ys == 0) { - PREPARE_BIGNUM(tc, W(tc),xl); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),xl); - for (i = yl; i > 0; i -= 1) *--zp = *--xp | *--yp; - for (i = xl - yl; i > 0; i -= 1) *--zp = *--xp; - return copy_normalize(tc, zp, xl, 0); - } else { - bigit yb, k; - - PREPARE_BIGNUM(tc, W(tc),yl+1); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),yl+1); - k = yb = 1; - for (i = yl; i > 0; i -= 1) { - bigit y1, y2, z1, z2; - y1 = *--yp; y2 = y1 - yb; yb = y2 > y1; - z1 = y2 & ~*--xp; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - *--zp = k; - return copy_normalize(tc, zp, yl+1, 1); - } - } else { - if (ys == 0) { - bigit xb, k; - - PREPARE_BIGNUM(tc, W(tc),xl+1); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),xl+1); - k = xb = 1; - for (i = yl; i > 0; i -= 1) { - bigit x1, x2, z1, z2; - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - z1 = x2 & ~*--yp; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - for (i = xl - yl; i > 0; i -= 1) { - bigit x1, x2, z1, z2; - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - z1 = x2; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - *--zp = k; - return copy_normalize(tc, zp, xl+1, 1); - } else { - bigit xb, yb, k; - - PREPARE_BIGNUM(tc, W(tc),yl+1); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),yl+1); - k = yb = xb = 1; - for (i = yl; i > 0; i -= 1) { - bigit x1, x2, y1, y2, z1, z2; - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - y1 = *--yp; y2 = y1 - yb; yb = y2 > y1; - z1 = x2 & y2; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - *--zp = k; - return copy_normalize(tc, zp, yl+1, 1); - } - } -} - -ptr S_logxor(ptr x, ptr y) { - ptr tc = get_thread_context(); - - if (Sfixnump(x)) { - if (Sfixnump(y)) { - return (ptr)((iptr)x ^ (iptr)(y)); - } else { - iptr xl; IBOOL xs; - FIXNUM_TO_BIGNUM(tc,X(tc),x,&xl,&xs) - return big_logxor(tc, y, X(tc), BIGLEN(y), xl, BIGSIGN(y), xs); - } - } else { - if (Sfixnump(y)) { - iptr yl; IBOOL ys; - FIXNUM_TO_BIGNUM(tc,Y(tc),y,&yl,&ys) - return big_logxor(tc, x, Y(tc), BIGLEN(x), yl, BIGSIGN(x), ys); - } else { - if (BIGLEN(x) >= BIGLEN(y)) - return big_logxor(tc, x, y, BIGLEN(x), BIGLEN(y), BIGSIGN(x), BIGSIGN(y)); - else - return big_logxor(tc, y, x, BIGLEN(y), BIGLEN(x), BIGSIGN(y), BIGSIGN(x)); - } - } -} - -/* logxor on signed-magnitude bignums - s^(x,y) = x^y know result >= 0 - s^(x,-y) = -(#(x^#y)) know result < 0 - = -(~(x^~(y-1))+1) - = -((x^(y-1))+1) since ~(a^~b) = a^b - s^(-x,y) = -((y^(x-1))+1) - s^(-x,-y) = #x^#y know result >= 0 - = ~(x-1)^~(y-1) - = (x-1)^(y-1) since ~a^~b = a^b -*/ - -/* assumes xl >= yl */ -static ptr big_logxor(ptr tc, ptr x, ptr y, iptr xl, iptr yl, IBOOL xs, IBOOL ys) { - iptr i; - bigit *xp, *yp, *zp; - - if (xs == 0) { - if (ys == 0) { - PREPARE_BIGNUM(tc, W(tc),xl); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),xl); - for (i = yl; i > 0; i -= 1) *--zp = *--xp ^ *--yp; - for (i = xl - yl; i > 0; i -= 1) *--zp = *--xp; - return copy_normalize(tc, zp, xl, 0); - } else { - bigit yb, k; - - PREPARE_BIGNUM(tc, W(tc),xl+1); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),xl+1); - k = yb = 1; - for (i = yl; i > 0; i -= 1) { - bigit y1, y2, z1, z2; - y1 = *--yp; y2 = y1 - yb; yb = y2 > y1; - z1 = *--xp ^ y2; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - for (i = xl - yl; i > 0; i -= 1) { - bigit z1, z2; - z1 = *--xp; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - *--zp = k; - return copy_normalize(tc, zp, xl+1, 1); - } - } else { - if (ys == 0) { - bigit xb, k; - - PREPARE_BIGNUM(tc, W(tc),xl+1); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),xl+1); - k = xb = 1; - for (i = yl; i > 0; i -= 1) { - bigit x1, x2, z1, z2; - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - z1 = *--yp ^ x2; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - for (i = xl - yl; i > 0; i -= 1) { - bigit x1, x2, z1, z2; - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - z1 = x2; - z2 = z1 + k; k = z2 < z1; - *--zp = z2; - } - *--zp = k; - return copy_normalize(tc, zp, xl+1, 1); - } else { - bigit xb, yb; - - PREPARE_BIGNUM(tc, W(tc),xl); - xp = &BIGIT(x,xl); yp = &BIGIT(y,yl); zp = &BIGIT(W(tc),xl); - yb = xb = 1; - for (i = yl; i > 0; i -= 1) { - bigit x1, x2, y1, y2; - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - y1 = *--yp; y2 = y1 - yb; yb = y2 > y1; - *--zp = x2 ^ y2; - } - for (i = xl - yl; i > 0; i -= 1) { - bigit x1, x2; - x1 = *--xp; x2 = x1 - xb; xb = x2 > x1; - *--zp = x2; - } - return copy_normalize(tc, zp, xl, 0); - } - } -} - -/* lognot on signed-magnitude bignums: - s~(x) = -#~x - = -(~~x+1) - = -(x+1) - s~(-x) = ~#x - = ~~(x-1) - = x-1 - therefore: - (define (lognot x) - (if (< x 0) - (- (- x) 1) - (- (+ x 1)))) - simplifying: - (define (lognot x) (- -1 x)) -*/ - -ptr S_lognot(ptr x) { - if (Sfixnump(x)) { - return FIX(~UNFIX(x)); - } else { - return S_sub(FIX(-1), x); - } -} - -void S_number_init(void) { - if ((int)(hidden_bit >> 22) != 0x40000000) { - fprintf(stderr, "hidden_bit >> 22 = %x\n", (int)(hidden_bit >> 22)); - S_abnormal_exit(); - } -} diff --git a/ta6ob/c/number.o b/ta6ob/c/number.o deleted file mode 100644 index e80340a..0000000 Binary files a/ta6ob/c/number.o and /dev/null differ diff --git a/ta6ob/c/prim.c b/ta6ob/c/prim.c deleted file mode 100644 index 4cb89d9..0000000 --- a/ta6ob/c/prim.c +++ /dev/null @@ -1,288 +0,0 @@ -/* prim.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" - -/* locally defined functions */ -static void install_library_entry(ptr n, ptr x); -static void scheme_install_library_entry(void); -static void create_library_entry_vector(void); -static void install_c_entry(iptr i, ptr x); -static void create_c_entry_vector(void); -static void s_instantiate_code_object(void); -static void s_link_code_object(ptr co, ptr objs); -static IBOOL s_check_heap_enabledp(void); -static void s_enable_check_heap(IBOOL b); -static uptr s_check_heap_errors(void); - -static void install_library_entry(ptr n, ptr x) { - if (!Sfixnump(n) || UNFIX(n) < 0 || UNFIX(n) >= library_entry_vector_size) - S_error1("$install-library-entry", "invalid index ~s", n); - if (!Sprocedurep(x) && !Scodep(x)) - S_error2("$install-library-entry", "invalid entry ~s for ~s", x, n); - if (Svector_ref(S_G.library_entry_vector, UNFIX(n)) != Sfalse) { - printf("$install-library-entry: overwriting entry for %ld\n", (long)UNFIX(n)); - fflush(stdout); - } - SETVECTIT(S_G.library_entry_vector, UNFIX(n), x); - if (n == FIX(library_nonprocedure_code)) { - S_G.nonprocedure_code = x; - S_retrofit_nonprocedure_code(); - } -} - -ptr S_lookup_library_entry(iptr n, IBOOL errorp) { - ptr p; - - if (n < 0 || n >= library_entry_vector_size) - S_error1("$lookup-library-entry", "invalid index ~s", FIX(n)); - p = Svector_ref(S_G.library_entry_vector, n); - if (p == Sfalse && errorp) - S_error1("$lookup-library-entry", "entry ~s uninitialized", FIX(n)); - return p; -} - -static void scheme_install_library_entry(void) { - ptr tc = get_thread_context(); - install_library_entry(S_get_scheme_arg(tc, 1), S_get_scheme_arg(tc, 2)); -} - -static void create_library_entry_vector(void) { - iptr i; - - S_protect(&S_G.library_entry_vector); - S_G.library_entry_vector = S_vector(library_entry_vector_size); - for (i = 0; i < library_entry_vector_size; i++) - INITVECTIT(S_G.library_entry_vector, i) = Sfalse; -} - -#ifdef HPUX -#define proc2ptr(x) int2ptr((iptr)(x)) -ptr int2ptr(iptr f) -{ - if ((f & 2) == 0) - S_error("proc2ptr", "invalid C procedure"); - return (ptr)(f & ~0x3); -} -#else /* HPUX */ -#define proc2ptr(x) (ptr)(iptr)(x) -#endif /* HPUX */ - -static void install_c_entry(iptr i, ptr x) { - if (i < 0 || i >= c_entry_vector_size) - S_error1("install_c_entry", "invalid index ~s", FIX(i)); - if (Svector_ref(S_G.c_entry_vector, i) != Sfalse) - S_error1("install_c_entry", "duplicate entry for ~s", FIX(i)); - SETVECTIT(S_G.c_entry_vector, i, x); -} - -ptr S_lookup_c_entry(iptr i) { - ptr x; - - if (i < 0 || i >= c_entry_vector_size) - S_error1("lookup_c_entry", "invalid index ~s", FIX(i)); - if ((x = Svector_ref(S_G.c_entry_vector, i)) == Sfalse) - S_error1("lookup_c_entry", "uninitialized entry ~s", FIX(i)); - return x; -} - -static ptr s_get_thread_context(void) { - return get_thread_context(); -} - -static void create_c_entry_vector(void) { - INT i; - - S_protect(&S_G.c_entry_vector); - S_G.c_entry_vector = S_vector(c_entry_vector_size); - - for (i = 0; i < c_entry_vector_size; i++) - INITVECTIT(S_G.c_entry_vector, i) = Sfalse; - - install_c_entry(CENTRY_thread_context, proc2ptr(S_G.thread_context)); - install_c_entry(CENTRY_get_thread_context, proc2ptr(s_get_thread_context)); - install_c_entry(CENTRY_handle_apply_overflood, proc2ptr(S_handle_apply_overflood)); - install_c_entry(CENTRY_handle_docall_error, proc2ptr(S_handle_docall_error)); - install_c_entry(CENTRY_handle_overflow, proc2ptr(S_handle_overflow)); - install_c_entry(CENTRY_handle_overflood, proc2ptr(S_handle_overflood)); - install_c_entry(CENTRY_handle_nonprocedure_symbol, proc2ptr(S_handle_nonprocedure_symbol)); - install_c_entry(CENTRY_thread_list, (ptr)&S_threads); - install_c_entry(CENTRY_split_and_resize, proc2ptr(S_split_and_resize)); -#ifdef PTHREADS - install_c_entry(CENTRY_raw_collect_cond, (ptr)&S_collect_cond); - install_c_entry(CENTRY_raw_tc_mutex, (ptr)&S_tc_mutex); - install_c_entry(CENTRY_activate_thread, proc2ptr(S_activate_thread)); - install_c_entry(CENTRY_deactivate_thread, proc2ptr(Sdeactivate_thread)); - install_c_entry(CENTRY_unactivate_thread, proc2ptr(S_unactivate_thread)); -#endif /* PTHREADS */ - install_c_entry(CENTRY_handle_values_error, proc2ptr(S_handle_values_error)); - install_c_entry(CENTRY_handle_mvlet_error, proc2ptr(S_handle_mvlet_error)); - install_c_entry(CENTRY_handle_arg_error, proc2ptr(S_handle_arg_error)); - install_c_entry(CENTRY_foreign_entry, proc2ptr(S_foreign_entry)); - install_c_entry(CENTRY_install_library_entry, proc2ptr(scheme_install_library_entry)); - install_c_entry(CENTRY_get_more_room, proc2ptr(S_get_more_room)); - install_c_entry(CENTRY_scan_remembered_set, proc2ptr(S_scan_remembered_set)); - install_c_entry(CENTRY_instantiate_code_object, proc2ptr(s_instantiate_code_object)); - install_c_entry(CENTRY_Sreturn, proc2ptr(S_return)); - install_c_entry(CENTRY_Scall_one_result, proc2ptr(S_call_one_result)); - install_c_entry(CENTRY_Scall_any_results, proc2ptr(S_call_any_results)); - - for (i = 0; i < c_entry_vector_size; i++) { -#ifndef PTHREADS - if (i == CENTRY_raw_collect_cond || i == CENTRY_raw_tc_mutex - || i == CENTRY_activate_thread || i == CENTRY_deactivate_thread - || i == CENTRY_unactivate_thread) - continue; -#endif /* NOT PTHREADS */ - if (Svector_ref(S_G.c_entry_vector, i) == Sfalse) { - fprintf(stderr, "c_entry_vector entry %d is uninitialized\n", i); - S_abnormal_exit(); - } - } -} - -void S_prim_init(void) { - if (!S_boot_time) return; - - create_library_entry_vector(); - create_c_entry_vector(); - - Sforeign_symbol("(cs)fixedpathp", (void *)S_fixedpathp); - Sforeign_symbol("(cs)bytes_allocated", (void *)S_compute_bytes_allocated); - Sforeign_symbol("(cs)curmembytes", (void *)S_curmembytes); - Sforeign_symbol("(cs)maxmembytes", (void *)S_maxmembytes); - Sforeign_symbol("(cs)resetmaxmembytes", (void *)S_resetmaxmembytes); - Sforeign_symbol("(cs)do_gc", (void *)S_do_gc); - Sforeign_symbol("(cs)check_heap_enabledp", (void *)s_check_heap_enabledp); - Sforeign_symbol("(cs)enable_check_heap", (void *)s_enable_check_heap); - Sforeign_symbol("(cs)check_heap_errors", (void *)s_check_heap_errors); - Sforeign_symbol("(cs)lookup_library_entry", (void *)S_lookup_library_entry); - Sforeign_symbol("(cs)link_code_object", (void *)s_link_code_object); - Sforeign_symbol("(cs)lookup_c_entry", (void *)S_lookup_c_entry); - Sforeign_symbol("(cs)lock_object", (void *)Slock_object); - Sforeign_symbol("(cs)unlock_object", (void *)Sunlock_object); - Sforeign_symbol("(cs)locked_objectp", (void *)Slocked_objectp); - Sforeign_symbol("(cs)locked_objects", (void *)S_locked_objects); - Sforeign_symbol("(cs)maxgen", (void *)S_maxgen); - Sforeign_symbol("(cs)set_maxgen", (void *)S_set_maxgen); - Sforeign_symbol("(cs)minfreegen", (void *)S_minfreegen); - Sforeign_symbol("(cs)set_minfreegen", (void *)S_set_minfreegen); - Sforeign_symbol("(cs)enable_object_counts", (void *)S_enable_object_counts); - Sforeign_symbol("(cs)set_enable_object_counts", (void *)S_set_enable_object_counts); - Sforeign_symbol("(cs)object_counts", (void *)S_object_counts); - Sforeign_symbol("(cs)unregister_guardian", (void *)S_unregister_guardian); - Sforeign_symbol("(cs)fire_collector", (void *)S_fire_collector); -} - -static void s_instantiate_code_object(void) { - ptr tc = get_thread_context(); - ptr old, cookie, proc; - ptr new, oldreloc, newreloc; - ptr pinfos; - uptr a, m, n; - iptr i, size; - - old = S_get_scheme_arg(tc, 1); - cookie = S_get_scheme_arg(tc, 2); - proc = S_get_scheme_arg(tc, 3); - - tc_mutex_acquire() - new = S_code(tc, CODETYPE(old), CODELEN(old)); - tc_mutex_release() - - oldreloc = CODERELOC(old); - size = RELOCSIZE(oldreloc); - newreloc = S_relocation_table(size); - RELOCCODE(newreloc) = new; - for (i = 0; i < size; i += 1) RELOCIT(newreloc, i) = RELOCIT(oldreloc, i); - - CODERELOC(new) = newreloc; - CODENAME(new) = CODENAME(old); - CODEARITYMASK(new) = CODEARITYMASK(old); - CODEFREE(new) = CODEFREE(old); - CODEINFO(new) = CODEINFO(old); - CODEPINFOS(new) = pinfos = CODEPINFOS(old); - if (pinfos != Snil) { - S_G.profile_counters = Scons(S_weak_cons(new, pinfos), S_G.profile_counters); - } - - for (i = 0; i < CODELEN(old); i++) CODEIT(new,i) = CODEIT(old,i); - - m = RELOCSIZE(newreloc); - a = 0; - n = 0; - while (n < m) { - uptr entry, item_off, code_off; ptr obj; - entry = RELOCIT(newreloc, n); n += 1; - if (RELOC_EXTENDED_FORMAT(entry)) { - item_off = RELOCIT(newreloc, n); n += 1; - code_off = RELOCIT(newreloc, n); n += 1; - } else { - item_off = RELOC_ITEM_OFFSET(entry); - code_off = RELOC_CODE_OFFSET(entry); - } - a += code_off; - obj = S_get_code_obj(RELOC_TYPE(entry), old, a, item_off); - - /* we've seen the enemy, and he is us */ - if (obj == old) obj = new; - - /* if we find our cookie, insert proc; otherwise, insert the object - into new to get proper adjustment of relative addresses */ - if (obj == cookie) - S_set_code_obj("fcallable", RELOC_TYPE(entry), new, a, proc, item_off); - else - S_set_code_obj("fcallable", RELOC_TYPE(entry), new, a, obj, item_off); - } - S_flush_instruction_cache(tc); - - AC0(tc) = new; -} - -static void s_link_code_object(ptr co, ptr objs) { - ptr t; uptr a, m, n; - - t = CODERELOC(co); - m = RELOCSIZE(t); - a = 0; - n = 0; - while (n < m) { - uptr entry, item_off, code_off; - entry = RELOCIT(t, n); n += 1; - if (RELOC_EXTENDED_FORMAT(entry)) { - item_off = RELOCIT(t, n); n += 1; - code_off = RELOCIT(t, n); n += 1; - } else { - item_off = RELOC_ITEM_OFFSET(entry); - code_off = RELOC_CODE_OFFSET(entry); - } - a += code_off; - S_set_code_obj("gc", RELOC_TYPE(entry), co, a, Scar(objs), item_off); - objs = Scdr(objs); - } -} - -static INT s_check_heap_enabledp(void) { - return S_checkheap; -} - -static void s_enable_check_heap(IBOOL b) { - S_checkheap = b; -} - -static uptr s_check_heap_errors(void) { - return S_checkheap_errors; -} diff --git a/ta6ob/c/prim.o b/ta6ob/c/prim.o deleted file mode 100644 index 6702195..0000000 Binary files a/ta6ob/c/prim.o and /dev/null differ diff --git a/ta6ob/c/prim5.c b/ta6ob/c/prim5.c deleted file mode 100644 index f552e74..0000000 --- a/ta6ob/c/prim5.c +++ /dev/null @@ -1,2052 +0,0 @@ -/* prim5.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" -#include "sort.h" - -#include -#include -#include -#include -#include - -/* locally defined functions */ -static INT s_errno(void); -static iptr s_addr_in_heap(uptr x); -static iptr s_ptr_in_heap(ptr x); -static ptr s_generation(ptr x); -static iptr s_fxmul(iptr x, iptr y); -static iptr s_fxdiv(iptr x, iptr y); -static ptr s_trunc_rem(ptr x, ptr y); -static ptr s_fltofx(ptr x); -static ptr s_weak_pairp(ptr p); -static ptr s_ephemeron_cons(ptr car, ptr cdr); -static ptr s_ephemeron_pairp(ptr p); -static ptr s_oblist(void); -static ptr s_bigoddp(ptr n); -static ptr s_float(ptr x); -static ptr s_decode_float(ptr x); -#ifdef segment_t2_bits -static void s_show_info(FILE *out); -#endif -static void s_show_chunks(FILE *out, ptr sorted_chunks); -static ptr sort_chunks(ptr ls, uptr n); -static ptr merge_chunks(ptr ls1, ptr ls2); -static ptr sorted_chunk_list(void); -static void s_showalloc(IBOOL show_dump, const char *outfn); -static ptr s_system(const char *s); -static ptr s_process(char *s, IBOOL stderrp); -static I32 s_chdir(const char *inpath); -static char *s_getwd(void); -static ptr s_set_code_byte(ptr p, ptr n, ptr x); -static ptr s_set_code_word(ptr p, ptr n, ptr x); -static ptr s_set_code_long(ptr p, ptr n, ptr x); -static void s_set_code_long2(ptr p, ptr n, ptr h, ptr l); -static ptr s_set_code_quad(ptr p, ptr n, ptr x); -static ptr s_set_reloc(ptr p, ptr n, ptr e); -static ptr s_flush_instruction_cache(void); -static ptr s_make_code(iptr flags, iptr free, ptr name, ptr arity_mark, iptr n, ptr info, ptr pinfos); -static ptr s_make_reloc_table(ptr codeobj, ptr n); -static ptr s_make_closure(ptr offset, ptr codeobj); -static ptr s_fxrandom(ptr n); -static ptr s_flrandom(ptr x); -static U32 s_random_seed(void); -static void s_set_random_seed(U32 x); -static ptr s_intern(ptr x); -static ptr s_intern2(ptr x, ptr n); -static ptr s_strings_to_gensym(ptr pname_str, ptr uname_str); -static ptr s_intern3(ptr x, ptr n, ptr m); -static ptr s_delete_file(const char *inpath); -static ptr s_delete_directory(const char *inpath); -static ptr s_rename_file(const char *inpath1, const char *inpath2); -static ptr s_mkdir(const char *inpath, INT mode); -static ptr s_chmod(const char *inpath, INT mode); -static ptr s_getmod(const char *inpath, IBOOL followp); -static ptr s_path_atime(const char *inpath, IBOOL followp); -static ptr s_path_ctime(const char *inpath, IBOOL followp); -static ptr s_path_mtime(const char *inpath, IBOOL followp); -static ptr s_fd_atime(INT fd); -static ptr s_fd_ctime(INT fd); -static ptr s_fd_mtime(INT fd); -static IBOOL s_fd_regularp(INT fd); -static void s_nanosleep(ptr sec, ptr nsec); -static ptr s_set_collect_trip_bytes(ptr n); -static void c_exit(I32 status); -static ptr s_get_reloc(ptr co); -#ifdef PTHREADS -static s_thread_rv_t s_backdoor_thread_start(void *p); -static iptr s_backdoor_thread(ptr p); -static ptr s_threads(void); -static void s_mutex_acquire(scheme_mutex_t *m); -static ptr s_mutex_acquire_noblock(scheme_mutex_t *m); -static void s_condition_broadcast(s_thread_cond_t *c); -static void s_condition_signal(s_thread_cond_t *c); -#endif -static void s_byte_copy(ptr src, iptr srcoff, ptr dst, iptr dstoff, iptr cnt); -static void s_ptr_copy(ptr src, iptr srcoff, ptr dst, iptr dstoff, iptr cnt); -static ptr s_tlv(ptr x); -static void s_stlv(ptr x, ptr v); -static void s_test_schlib(void); -static void s_breakhere(ptr x); -static IBOOL s_interactivep(void); -static IBOOL s_same_devicep(INT fd1, INT fd2); -static uptr s_malloc(iptr n); -static void s_free(uptr n); -#ifdef FEATURE_ICONV -static ptr s_iconv_open(const char *tocode, const char *fromcode); -static void s_iconv_close(uptr cd); -static ptr s_iconv_from_string(uptr cd, ptr in, uptr i, uptr iend, ptr out, uptr o, uptr oend); -static ptr s_iconv_to_string(uptr cd, ptr in, uptr i, uptr iend, ptr out, uptr o, uptr oend); -#endif -#ifdef WIN32 -static ptr s_multibytetowidechar(unsigned cp, ptr inbv); -static ptr s_widechartomultibyte(unsigned cp, ptr inbv); -#endif -static ptr s_profile_counters(void); -static ptr s_profile_release_counters(void); - -#define require(test,who,msg,arg) if (!(test)) S_error1(who, msg, arg) - -ptr S_strerror(INT errnum) { - ptr p; char *msg; - - tc_mutex_acquire() -#ifdef WIN32 - msg = Swide_to_utf8(_wcserror(errnum)); - if (msg == NULL) - p = Sfalse; - else { - p = Sstring_utf8(msg, -1); - free(msg); - } -#else - p = (msg = strerror(errnum)) == NULL ? Sfalse : Sstring_utf8(msg, -1); -#endif - tc_mutex_release() - return p; -} - -static INT s_errno(void) { - return errno; -} - -static iptr s_addr_in_heap(uptr x) { - return MaybeSegInfo(addr_get_segment(x)) != NULL; -} - -static iptr s_ptr_in_heap(ptr x) { - return MaybeSegInfo(ptr_get_segment(x)) != NULL; -} - -static ptr s_generation(ptr x) { - seginfo *si = MaybeSegInfo(ptr_get_segment(x)); - return si == NULL ? Sfalse : FIX(si->generation); -} - -static iptr s_fxmul(iptr x, iptr y) { - return x * y; -} - -static iptr s_fxdiv(iptr x, iptr y) { - return x / y; -} - -static ptr s_trunc_rem(ptr x, ptr y) { - ptr q, r; - S_trunc_rem(get_thread_context(), x, y, &q, &r); - return Scons(q, r); -} - -static ptr s_fltofx(ptr x) { - return FIX((iptr)FLODAT(x)); -} - -static ptr s_weak_pairp(ptr p) { - seginfo *si; - return Spairp(p) && (si = MaybeSegInfo(ptr_get_segment(p))) != NULL && (si->space & ~space_locked) == space_weakpair ? Strue : Sfalse; -} - -static ptr s_ephemeron_cons(ptr car, ptr cdr) { - ptr p; - - tc_mutex_acquire() - p = S_cons_in(space_ephemeron, 0, car, cdr); - tc_mutex_release() - return p; -} - -static ptr s_ephemeron_pairp(ptr p) { - seginfo *si; - return Spairp(p) && (si = MaybeSegInfo(ptr_get_segment(p))) != NULL && (si->space & ~space_locked) == space_ephemeron ? Strue : Sfalse; -} - -static ptr s_oblist(void) { - ptr ls = Snil; - iptr idx = S_G.oblist_length; - bucket *b; - - while (idx-- != 0) { - for (b = S_G.oblist[idx]; b != NULL; b = b->next) { - ls = Scons(b->sym, ls); - } - } - - return ls; -} - -static ptr s_bigoddp(ptr n) { - return Sboolean(BIGIT(n, BIGLEN(n) - 1) & 1); /* last bigit */; -} - -static ptr s_float(ptr x) { - return Sflonum(S_floatify(x)); -} - -static ptr s_decode_float(ptr x) { - require(Sflonump(x),"decode-float","~s is not a float",x); - return S_decode_float(FLODAT(x)); -} - -#define FMTBUFSIZE 120 -#define CHUNKADDRLT(x, y) (((chunkinfo *)(Scar(x)))->addr < ((chunkinfo *)(Scar(y)))->addr) -mkmergesort(sort_chunks, merge_chunks, ptr, Snil, CHUNKADDRLT, INITCDR) - -static ptr sorted_chunk_list(void) { - chunkinfo *chunk; INT i, n = 0; ptr ls = Snil; - - for (i = PARTIAL_CHUNK_POOLS; i >= -1; i -= 1) { - for (chunk = (i == -1) ? S_chunks_full : S_chunks[i]; chunk != NULL; chunk = chunk->next) { - ls = Scons(chunk, ls); - n += 1; - } - } - - return sort_chunks(ls, n); -} - -#ifdef segment_t2_bits -static void s_show_info(FILE *out) { - void *max_addr = 0; - INT addrwidth; - const char *addrtitle = "address"; - char fmtbuf[FMTBUFSIZE]; - uptr i2; -#ifdef segment_t3_bits - INT byteswidth; - uptr i3; - for (i3 = 0; i3 < SEGMENT_T3_SIZE; i3 += 1) { - t2table *t2t = S_segment_info[i3]; - if (t2t != NULL) { - if ((void *)t2t > max_addr) max_addr = (void *)t2t; - for (i2 = 0; i2 < SEGMENT_T2_SIZE; i2 += 1) { - t1table *t1t = t2t->t2[i2]; - if (t1t != NULL) { - if ((void *)t1t > max_addr) max_addr = (void *)t1t; - } - } - } - } - addrwidth = snprintf(fmtbuf, FMTBUFSIZE, "%#tx", (ptrdiff_t)max_addr); - if (addrwidth < (INT)strlen(addrtitle)) addrwidth = (INT)strlen(addrtitle); - byteswidth = snprintf(fmtbuf, FMTBUFSIZE, "%#tx", (ptrdiff_t)(sizeof(t1table) > sizeof(t2table) ? sizeof(t1table) : sizeof(t2table))); - snprintf(fmtbuf, FMTBUFSIZE, "%%s %%-%ds %%-%ds\n\n", addrwidth, byteswidth); - fprintf(out, fmtbuf, "level", addrtitle, "bytes"); - snprintf(fmtbuf, FMTBUFSIZE, "%%-5d %%#0%dtx %%#0%dtx\n", addrwidth, byteswidth); - for (i3 = 0; i3 < SEGMENT_T3_SIZE; i3 += 1) { - t2table *t2t = S_segment_info[i3]; - if (t2t != NULL) { - fprintf(out, fmtbuf, 2, t2t, sizeof(t2table)); - for (i2 = 0; i2 < SEGMENT_T2_SIZE; i2 += 1) { - t1table *t1t = t2t->t2[i2]; - if (t1t != NULL) { - fprintf(out, fmtbuf, 1, (ptrdiff_t)t1t, (ptrdiff_t)sizeof(t1table)); - } - } - } - } -#else - for (i2 = 0; i2 < SEGMENT_T2_SIZE; i2 += 1) { - t1table *t1t = S_segment_info[i2]; - if (t1t != NULL) { - if ((void *)t1t > max_addr) max_addr = (void *)t1t; - } - } - addrwidth = 1 + snprintf(fmtbuf, FMTBUFSIZE, "%#tx", (ptrdiff_t)max_addr); - if (addrwidth < (INT)strlen(addrtitle) + 1) addrwidth = (INT)strlen(addrtitle) + 1; - snprintf(fmtbuf, FMTBUFSIZE, "%%s %%-%ds %%s\n\n", addrwidth); - fprintf(out, fmtbuf, "level", addrtitle, "bytes"); - snprintf(fmtbuf, FMTBUFSIZE, "%%-5d %%#0%dtx %%#tx\n", (ptrdiff_t)addrwidth); - for (i2 = 0; i2 < SEGMENT_T2_SIZE; i2 += 1) { - t1table *t1t = S_segment_info[i2]; - if (t1t != NULL) { - fprintf(out, fmtbuf, 1, (ptrdiff_t)t1t, (ptrdiff_t)sizeof(t1table)); - } - } -#endif -} -#endif - -static void s_show_chunks(FILE *out, ptr sorted_chunks) { - char fmtbuf[FMTBUFSIZE]; - chunkinfo *chunk; - void *max_addr = 0; - void *max_header_addr = 0; - iptr max_segs = 0; - INT addrwidth, byteswidth, headeraddrwidth, headerbyteswidth, segswidth, headerwidth; - const char *addrtitle = "address", *bytestitle = "bytes", *headertitle = "(+ header)"; - ptr ls; - - for (ls = sorted_chunks; ls != Snil; ls = Scdr(ls)) { - chunk = Scar(ls); - max_addr = chunk->addr; - if (chunk->segs > max_segs) max_segs = chunk->segs; - if ((void *)chunk > max_header_addr) max_header_addr = (void *)chunk; - } - - addrwidth = (INT)snprintf(fmtbuf, FMTBUFSIZE, "%#tx", (ptrdiff_t)max_addr); - if (addrwidth < (INT)strlen(addrtitle)) addrwidth = (INT)strlen(addrtitle); - byteswidth = (INT)snprintf(fmtbuf, FMTBUFSIZE, "%#tx", (ptrdiff_t)(max_segs * bytes_per_segment)); - if (byteswidth < (INT)strlen(bytestitle)) byteswidth = (INT)strlen(bytestitle); - headerbyteswidth = (INT)snprintf(fmtbuf, FMTBUFSIZE, "%#tx", (ptrdiff_t)(sizeof(chunkinfo) + sizeof(seginfo) * max_segs)); - headeraddrwidth = (INT)snprintf(fmtbuf, FMTBUFSIZE, "%#tx", (ptrdiff_t)max_header_addr); - segswidth = (INT)snprintf(fmtbuf, FMTBUFSIZE, "%td", (ptrdiff_t)max_segs); - headerwidth = headerbyteswidth + headeraddrwidth + 13; - - snprintf(fmtbuf, FMTBUFSIZE, "%%-%ds %%-%ds %%-%ds %%s\n\n", addrwidth, byteswidth, headerwidth); - fprintf(out, fmtbuf, addrtitle, bytestitle, headertitle, "segments used"); - snprintf(fmtbuf, FMTBUFSIZE, "%%#0%dtx %%#0%dtx (+ %%#0%dtx bytes @ %%#0%dtx) %%%dtd of %%%dtd\n", - addrwidth, byteswidth, headerbyteswidth, headeraddrwidth, segswidth, segswidth); - for (ls = sorted_chunks; ls != Snil; ls = Scdr(ls)) { - chunk = Scar(ls); - fprintf(out, fmtbuf, (ptrdiff_t)chunk->addr, (ptrdiff_t)chunk->bytes, - (ptrdiff_t)(sizeof(chunkinfo) + sizeof(seginfo) * chunk->segs), - (ptrdiff_t)chunk, (ptrdiff_t)chunk->nused_segs, (ptrdiff_t)chunk->segs); - } -} - -#define space_bogus (max_space + 1) -#define space_total (space_bogus + 1) -#define generation_total (static_generation + 1) -#define INCRGEN(g) (g = g == S_G.max_nonstatic_generation ? static_generation : g+1) -static void s_showalloc(IBOOL show_dump, const char *outfn) { - FILE *out; - iptr count[generation_total+1][space_total+1]; - uptr bytes[generation_total+1][space_total+1]; - int i, column_size[generation_total+1]; - char fmtbuf[FMTBUFSIZE]; - static char *spacename[space_total+1] = { alloc_space_names, "bogus", "total" }; - static char spacechar[space_total+1] = { alloc_space_chars, '?', 't' }; - chunkinfo *chunk; seginfo *si; ISPC s; IGEN g; - ptr sorted_chunks; - - tc_mutex_acquire() - - if (outfn == NULL) { - out = stderr; - } else { -#ifdef WIN32 - wchar_t *outfnw = Sutf8_to_wide(outfn); - out = _wfopen(outfnw, L"w"); - free(outfnw); -#else - out = fopen(outfn, "w"); -#endif - if (out == NULL) { - ptr msg = S_strerror(errno); - if (msg != Sfalse) { - tc_mutex_release() - S_error2("fopen", "open of ~s failed: ~a", Sstring_utf8(outfn, -1), msg); - } else { - tc_mutex_release() - S_error1("fopen", "open of ~s failed", Sstring_utf8(outfn, -1)); - } - } - } - for (g = 0; g <= generation_total; INCRGEN(g)) - for (s = 0; s <= space_total; s++) - count[g][s] = bytes[g][s] = 0; - - for (g = 0; g <= static_generation; INCRGEN(g)) { - for (s = 0; s <= max_real_space; s++) { - /* add in bytes previously recorded */ - bytes[g][s] += S_G.bytes_of_space[g][s]; - /* add in bytes in active segments */ - if (S_G.next_loc[g][s] != FIX(0)) - bytes[g][s] += (char *)S_G.next_loc[g][s] - (char *)S_G.base_loc[g][s]; - } - } - - for (g = 0; g <= static_generation; INCRGEN(g)) { - for (s = 0; s <= max_real_space; s++) { - for (si = S_G.occupied_segments[g][s]; si != NULL; si = si->next) { - count[g][s] += 1; - } - } - } - - for (g = 0; g < generation_total; INCRGEN(g)) { - for (s = 0; s < space_total; s++) { - count[g][space_total] += count[g][s]; - count[generation_total][s] += count[g][s]; - count[generation_total][space_total] += count[g][s]; - bytes[g][space_total] += bytes[g][s]; - bytes[generation_total][s] += bytes[g][s]; - bytes[generation_total][space_total] += bytes[g][s]; - } - } - - for (g = 0; g <= generation_total; INCRGEN(g)) { - if (count[g][space_total] != 0) { - int n = 1 + snprintf(fmtbuf, FMTBUFSIZE, "%td", (ptrdiff_t)count[g][space_total]); - column_size[g] = n < 8 ? 8 : n; - } - } - - fprintf(out, "Segments per space & generation:\n\n"); - fprintf(out, "%8s", ""); - for (g = 0; g <= generation_total; INCRGEN(g)) { - if (count[g][space_total] != 0) { - if (g == generation_total) { - /* coverity[uninit_use] */ - snprintf(fmtbuf, FMTBUFSIZE, "%%%ds", column_size[g]); - fprintf(out, fmtbuf, "total"); - } else if (g == static_generation) { - /* coverity[uninit_use] */ - snprintf(fmtbuf, FMTBUFSIZE, "%%%ds", column_size[g]); - fprintf(out, fmtbuf, "static"); - } else { - /* coverity[uninit_use] */ - snprintf(fmtbuf, FMTBUFSIZE, "%%%dd", column_size[g]); - fprintf(out, fmtbuf, g); - } - } - } - fprintf(out, "\n"); - for (s = 0; s <= space_total; s++) { - if (s != space_empty) { - if (count[generation_total][s] != 0) { - fprintf(out, "%7s:", spacename[s]); - for (g = 0; g <= generation_total; INCRGEN(g)) { - if (count[g][space_total] != 0) { - /* coverity[uninit_use] */ - snprintf(fmtbuf, FMTBUFSIZE, "%%%dtd", column_size[g]); - fprintf(out, fmtbuf, (ptrdiff_t)(count[g][s])); - } - } - fprintf(out, "\n"); - fprintf(out, "%8s", ""); - for (g = 0; g <= generation_total; INCRGEN(g)) { - if (count[g][space_total] != 0) { - if (count[g][s] != 0 && s <= max_real_space) { - /* coverity[uninit_use] */ - snprintf(fmtbuf, FMTBUFSIZE, "%%%dd%%%%", column_size[g] - 1); - fprintf(out, fmtbuf, - (int)(((double)bytes[g][s] / - ((double)count[g][s] * bytes_per_segment)) * 100.0)); - } else { - /* coverity[uninit_use] */ - snprintf(fmtbuf, FMTBUFSIZE, "%%%ds", column_size[g]); - fprintf(out, fmtbuf, ""); - } - } - } - fprintf(out, "\n"); - } - } - } - - fprintf(out, "segment size = %#tx bytes. percentages show the portion actually occupied.\n", (ptrdiff_t)bytes_per_segment); - fprintf(out, "%td segments are presently reserved for future allocation or collection.\n", (ptrdiff_t)S_G.number_of_empty_segments); - - fprintf(out, "\nMemory chunks obtained and not returned to the O/S:\n\n"); - sorted_chunks = sorted_chunk_list(); - s_show_chunks(out, sorted_chunks); - -#ifdef segment_t2_bits - fprintf(out, "\nDynamic memory occupied by segment info table:\n\n"); - s_show_info(out); -#endif - - fprintf(out, "\nAdditional memory might be used by C libraries and programs in the\nsame address space.\n"); - - if (show_dump) { - iptr max_seg = 0; - int segwidth, segsperline; - iptr next_base = 0; - int segsprinted = 0; - char spaceline[100], genline[100]; - ptr ls; - - for (ls = sorted_chunks; ls != Snil; ls = Scdr(ls)) { - iptr last_seg; - chunk = Scar(ls); - last_seg = chunk->base + chunk->segs; - if (last_seg > max_seg) max_seg = last_seg; - } - - segwidth = snprintf(fmtbuf, FMTBUFSIZE, "%#tx ", (ptrdiff_t)max_seg); - segsperline = (99 - segwidth) & ~0xf; - - snprintf(fmtbuf, FMTBUFSIZE, " %%-%ds", segwidth); - snprintf(genline, 100, fmtbuf, ""); - - fprintf(out, "\nMap of occupied segments:\n"); - for (ls = sorted_chunks; ls != Snil; ls = Scdr(ls)) { - seginfo *si; ISPC real_s; - - chunk = Scar(ls); - - if (chunk->base != next_base && segsprinted != 0) { - for (;;) { - if (segsprinted == segsperline) { - fprintf(out, "\n%s", spaceline); - fprintf(out, "\n%s", genline); - break; - } - if (next_base == chunk->base) break; - spaceline[segwidth+segsprinted] = ' '; - genline[segwidth+segsprinted] = ' '; - segsprinted += 1; - next_base += 1; - } - } - - if (chunk->base > next_base && next_base != 0) { - fprintf(out, "\n-------- skipping %td segments --------", (ptrdiff_t)(chunk->base - next_base)); - } - - for (i = 0; i < chunk->segs; i += 1) { - if (segsprinted >= segsperline) segsprinted = 0; - - if (segsprinted == 0) { - if (i != 0) { - fprintf(out, "\n%s", spaceline); - fprintf(out, "\n%s", genline); - } - snprintf(fmtbuf, FMTBUFSIZE, "%%#0%dtx ", segwidth - 1); - snprintf(spaceline, 100, fmtbuf, (ptrdiff_t)(chunk->base + i)); - segsprinted = 0; - } - - si = &chunk->sis[i]; - real_s = si->space; - s = real_s & ~(space_locked | space_old); - if (s < 0 || s > max_space) s = space_bogus; - spaceline[segwidth+segsprinted] = - real_s & (space_locked | space_old) ? toupper(spacechar[s]) : spacechar[s]; - - g = si->generation; - genline[segwidth+segsprinted] = - (s == space_empty) ? '.' : - (g < 10) ? '0' + g : - (g < 36) ? 'A' + g - 10 : - (g == static_generation) ? '*' : '+'; - segsprinted += 1; - } - next_base = chunk->base + chunk->segs; - } - - if (segsprinted != 0) { - spaceline[segwidth+segsprinted] = 0; - genline[segwidth+segsprinted] = 0; - fprintf(out, "\n%s", spaceline); - fprintf(out, "\n%s", genline); - } - - fprintf(out, "\n\nSpaces:"); - for (s = 0; s < space_total; s += 1) - fprintf(out, "%s%c = %s", s % 5 == 0 ? "\n " : "\t", - spacechar[s], spacename[s]); - fprintf(out, "\n\nGenerations:\n 0-9: 0<=g<=9; A-Z: 10<=g<=35; +: g>=36; *: g=static; .: empty\n\n"); - } - - if (outfn == NULL) { - fflush(out); - } else { - fclose(out); - } - - tc_mutex_release() -} - -#include -#ifdef WIN32 -#include -#include -#include -#include -#include -#else /* WIN32 */ -#include -#include -#endif /* WIN32 */ - -static ptr s_system(const char *s) { - INT status; -#ifdef PTHREADS - ptr tc = get_thread_context(); -#endif - -#ifdef PTHREADS - if (DISABLECOUNT(tc) == FIX(0)) deactivate_thread(tc); -#endif - status = SYSTEM(s); -#ifdef PTHREADS - if (DISABLECOUNT(tc) == FIX(0)) reactivate_thread(tc); -#endif - - if ((status == -1) && (errno != 0)) { - ptr msg = S_strerror(errno); - - if (msg != Sfalse) - S_error1("system", "~a", msg); - else - S_error("system", "subprocess execution failed"); - } - -#ifdef WIN32 - return Sinteger(status); -#else - if WIFEXITED(status) return Sinteger(WEXITSTATUS(status)); - if WIFSIGNALED(status) return Sinteger(-WTERMSIG(status)); - S_error("system", "cannot determine subprocess exit status"); - return 0 /* not reached */; -#endif /* WIN32 */ -} - -static ptr s_process(char *s, IBOOL stderrp) { - INT ifd = -1, ofd = -1, efd = -1, child = -1; - -#ifdef WIN32 - HANDLE hToRead, hToWrite, hFromRead, hFromWrite, hFromReadErr, hFromWriteErr, hProcess; - STARTUPINFOW si = {0}; - PROCESS_INFORMATION pi; - char *comspec; - char *buffer; - wchar_t* bufferw; - - /* Create non-inheritable pipes, important to eliminate zombee children - * when the parent sides are closed. */ - if (!CreatePipe(&hToRead, &hToWrite, NULL, 0)) - S_error("process", "cannot open pipes"); - if (!CreatePipe(&hFromRead, &hFromWrite, NULL, 0)) { - CloseHandle(hToRead); - CloseHandle(hToWrite); - S_error("process", "cannot open pipes"); - } - if (stderrp && !CreatePipe(&hFromReadErr, &hFromWriteErr, NULL, 0)) { - CloseHandle(hToRead); - CloseHandle(hToWrite); - CloseHandle(hFromRead); - CloseHandle(hFromWrite); - S_error("process", "cannot open pipes"); - } - - si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES; - hProcess = GetCurrentProcess(); - - /* Duplicate the ToRead handle so that the child can inherit it. */ - if (!DuplicateHandle(hProcess, hToRead, hProcess, &si.hStdInput, - GENERIC_READ, TRUE, 0)) { - CloseHandle(hToRead); - CloseHandle(hToWrite); - CloseHandle(hFromRead); - CloseHandle(hFromWrite); - if (stderrp) { - CloseHandle(hFromReadErr); - CloseHandle(hFromWriteErr); - } - S_error("process", "cannot open pipes"); - } - CloseHandle(hToRead); - - /* Duplicate the FromWrite handle so that the child can inherit it. */ - if (!DuplicateHandle(hProcess, hFromWrite, hProcess, &si.hStdOutput, - GENERIC_WRITE, TRUE, 0)) { - CloseHandle(si.hStdInput); - CloseHandle(hToWrite); - CloseHandle(hFromRead); - CloseHandle(hFromWrite); - if (stderrp) { - CloseHandle(hFromReadErr); - CloseHandle(hFromWriteErr); - } - S_error("process", "cannot open pipes"); - } - CloseHandle(hFromWrite); - - if (stderrp) { - /* Duplicate the FromWrite handle so that the child can inherit it. */ - if (!DuplicateHandle(hProcess, hFromWriteErr, hProcess, &si.hStdError, - GENERIC_WRITE, TRUE, 0)) { - CloseHandle(si.hStdInput); - CloseHandle(hToWrite); - CloseHandle(hFromRead); - CloseHandle(hFromWrite); - CloseHandle(hFromReadErr); - CloseHandle(hFromWriteErr); - S_error("process", "cannot open pipes"); - } - CloseHandle(hFromWriteErr); - } else { - si.hStdError = si.hStdOutput; - } - - if ((comspec = Sgetenv("COMSPEC"))) { - size_t n = strlen(comspec) + strlen(s) + 7; - buffer = (char *)_alloca(n); - snprintf(buffer, n, "\"%s\" /c %s", comspec, s); - free(comspec); - } else - buffer = s; - bufferw = Sutf8_to_wide(buffer); - if (!CreateProcessW(NULL, bufferw, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { - free(bufferw); - CloseHandle(si.hStdInput); - CloseHandle(hToWrite); - CloseHandle(hFromRead); - CloseHandle(si.hStdOutput); - if (stderrp) { - CloseHandle(hFromReadErr); - CloseHandle(si.hStdError); - } - S_error("process", "cannot spawn subprocess"); - } - free(bufferw); - CloseHandle(si.hStdInput); - CloseHandle(si.hStdOutput); - if (stderrp) { - CloseHandle(si.hStdError); - } - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - - ifd = _open_osfhandle((intptr_t)hFromRead, 0); - ofd = _open_osfhandle((intptr_t)hToWrite, 0); - if (stderrp) { - efd = _open_osfhandle((intptr_t)hFromReadErr, 0); - } - child = pi.dwProcessId; - -#else /* WIN32 */ - - INT tofds[2], fromfds[2], errfds[2]; - struct sigaction act, oint_act; - - if (pipe(tofds)) S_error("process","cannot open pipes"); - if (pipe(fromfds)) { - CLOSE(tofds[0]); CLOSE(tofds[1]); - S_error("process","cannot open pipes"); - } - if (stderrp) { - if (pipe(errfds)) { - CLOSE(tofds[0]); CLOSE(tofds[1]); - CLOSE(fromfds[0]); CLOSE(fromfds[1]); - S_error("process","cannot open pipes"); - } - } - - sigemptyset(&act.sa_mask); - act.sa_flags = 0; - act.sa_handler = SIG_IGN; - sigaction(SIGINT, &act, &oint_act); - - if ((child = fork()) == 0) { - /* child does this: */ - CLOSE(0); if (dup(tofds[0]) != 0) _exit(1); - CLOSE(1); if (dup(fromfds[1]) != 1) _exit(1); - CLOSE(2); if (dup(stderrp ? errfds[1] : 1) != 2) _exit(1); - {INT i; for (i = 3; i < NOFILE; i++) (void)CLOSE(i);} - execl("/bin/sh", "/bin/sh", "-c", s, NULL); - _exit(1) /* only if execl fails */; - /*NOTREACHED*/ - } else { - /* parent does this: */ - CLOSE(tofds[0]); CLOSE(fromfds[1]); if (stderrp) CLOSE(errfds[1]); - if (child < 0) { - CLOSE(tofds[1]); CLOSE(fromfds[0]); if (stderrp) CLOSE(errfds[0]); - sigaction(SIGINT, &oint_act, (struct sigaction *)0); - S_error("process", "cannot fork subprocess"); - /*NOTREACHED*/ - } else { - ifd = fromfds[0]; - ofd = tofds[1]; - if (stderrp) efd = errfds[0]; - sigaction(SIGINT, &oint_act, (struct sigaction *)0); - S_register_child_process(child); - } - } -#endif /* WIN32 */ - - if (stderrp) - return LIST4(FIX(ifd), FIX(efd), FIX(ofd), FIX(child)); - else - return LIST3(FIX(ifd), FIX(ofd), FIX(child)); -} - -static I32 s_chdir(const char *inpath) { - char *path; - I32 status; - - path = S_malloc_pathname(inpath); -#ifdef EINTR - while ((status = CHDIR(path)) != 0 && errno == EINTR) ; -#else /* EINTR */ - status = CHDIR(path); -#endif /* EINTR */ - free(path); - return status; -} - -#ifdef GETWD -static char *s_getwd() { - return GETWD((char *)&BVIT(S_bytevector(PATH_MAX), 0)); -} -#endif /* GETWD */ - -static ptr s_set_code_byte(ptr p, ptr n, ptr x) { - I8 *a; - - a = (I8 *)((uptr)p + UNFIX(n)); - *a = (I8)UNFIX(x); - return Svoid; -} - -static ptr s_set_code_word(ptr p, ptr n, ptr x) { - I16 *a; - - a = (I16 *)((uptr)p + UNFIX(n)); - *a = (I16)UNFIX(x); - return Svoid; -} - -static ptr s_set_code_long(ptr p, ptr n, ptr x) { - I32 *a; - - a = (I32 *)((uptr)p + UNFIX(n)); - *a = (I32)(Sfixnump(x) ? UNFIX(x) : Sinteger_value(x)); - return Svoid; -} - -static void s_set_code_long2(ptr p, ptr n, ptr h, ptr l) { - I32 *a; - - a = (I32 *)((uptr)p + UNFIX(n)); - *a = (I32)((UNFIX(h) << 16) + UNFIX(l)); -} - -static ptr s_set_code_quad(ptr p, ptr n, ptr x) { - I64 *a; - - a = (I64 *)((uptr)p + UNFIX(n)); - *a = Sfixnump(x) ? UNFIX(x) : S_int64_value("\\#set-code-quad!", x); - return Svoid; -} - -static ptr s_set_reloc(ptr p, ptr n, ptr e) { - iptr *a; - - a = (iptr *)(&RELOCIT(CODERELOC(p), UNFIX(n))); - *a = Sfixnump(e) ? UNFIX(e) : Sinteger_value(e); - return e; -} - -static ptr s_flush_instruction_cache(void) { - tc_mutex_acquire() - S_flush_instruction_cache(get_thread_context()); - tc_mutex_release() - return Svoid; -} - -static ptr s_make_code(flags, free, name, arity_mark, n, info, pinfos) - iptr flags, free, n; ptr name, arity_mark, info, pinfos; { - ptr co; - - tc_mutex_acquire() - co = S_code(get_thread_context(), type_code | (flags << code_flags_offset), n); - tc_mutex_release() - CODEFREE(co) = free; - CODENAME(co) = name; - CODEARITYMASK(co) = arity_mark; - CODEINFO(co) = info; - CODEPINFOS(co) = pinfos; - if (pinfos != Snil) { - S_G.profile_counters = Scons(S_weak_cons(co, pinfos), S_G.profile_counters); - } - return co; -} - -static ptr s_make_reloc_table(ptr codeobj, ptr n) { - CODERELOC(codeobj) = S_relocation_table(UNFIX(n)); - RELOCCODE(CODERELOC(codeobj)) = codeobj; - return Svoid; -} - -static ptr s_make_closure(ptr offset, ptr codeobj) { - - return S_closure((ptr)((iptr)codeobj + UNFIX(offset)), 0); -} - -/* the random formula is based on Knuth. It returns a random fixnum - * between 0 and n-1. - */ -static ptr s_fxrandom(ptr p) { - ptr tc = get_thread_context(); - uptr t, n = UNFIX(p); - - t = (RANDOMSEED(tc) = RANDOMSEED(tc) * 72931 + 90763387) >> 16; - t = t | ((RANDOMSEED(tc) = RANDOMSEED(tc) * 72931 + 90763387) & 0xffff0000); - if (n <= 0xffffffff) /* trivially true if sizeof(ptr) <= sizeof(U32) */ - return FIX(t % n); - else { - t = (t << 16) | ((RANDOMSEED(tc) = RANDOMSEED(tc) * 72931 + 90763387) >> 16); - t = (t << 16) | ((RANDOMSEED(tc) = RANDOMSEED(tc) * 72931 + 90763387) >> 16); - return FIX(t % n); - } -} - -static ptr s_flrandom(ptr x) { - ptr tc = get_thread_context(); - U32 t1, t2, t3, t4; - - t1 = RANDOMSEED(tc) = RANDOMSEED(tc) * 72931 + 90763387; - t2 = RANDOMSEED(tc) = RANDOMSEED(tc) * 72931 + 90763387; - t3 = RANDOMSEED(tc) = RANDOMSEED(tc) * 72931 + 90763387; - t4 = RANDOMSEED(tc) = RANDOMSEED(tc) * 72931 + 90763387; - return Sflonum(S_random_double(t1, t2, t3, t4, FLODAT(x))); -} - -static U32 s_random_seed() { - ptr tc = get_thread_context(); - return RANDOMSEED(tc); -} - -static void s_set_random_seed(U32 x) { - ptr tc = get_thread_context(); - RANDOMSEED(tc) = x; -} - -static ptr s_intern(ptr x) { - require(Sstringp(x),"string->symbol","~s is not a string",x); - - return S_intern_sc(&STRIT(x, 0), Sstring_length(x), x); -} - -static ptr s_intern2(ptr x, ptr n) { - return S_intern_sc(&STRIT(x, 0), UNFIX(n), Sfalse); -} - -/* first n chars str are pretty name; remaining m-n are unique name */ -static ptr s_intern3(ptr x, ptr n, ptr m) { - iptr plen = UNFIX(n); - return S_intern3(&STRIT(x, 0), plen, &STRIT(x, plen), UNFIX(m) - plen, Sfalse, Sfalse); -} - -static ptr s_strings_to_gensym(ptr pname_str, ptr uname_str) { - return S_intern3(&STRIT(pname_str, 0), Sstring_length(pname_str), - &STRIT(uname_str, 0), Sstring_length(uname_str), - pname_str, uname_str); -} - -static ptr s_mkdir(const char *inpath, INT mode) { - INT status; ptr res; char *path; - - path = S_malloc_pathname(inpath); -#ifdef WIN32 - status = S_windows_mkdir(path); -#else /* WIN32 */ - status = mkdir(path, mode); -#endif /* WIN32 */ - - res = status == 0 ? Strue : S_strerror(errno); - free(path); - return res; -} - -static ptr s_delete_file(const char *inpath) { - ptr res; char *path; - - path = S_malloc_pathname(inpath); - res = UNLINK(path) == 0 ? Strue : S_strerror(errno); - free(path); - return res; -} - -static ptr s_delete_directory(const char *inpath) { - ptr res; char *path; - - path = S_malloc_pathname(inpath); - res = RMDIR(path) == 0 ? Strue : S_strerror(errno); - free(path); - return res; -} - -static ptr s_rename_file(const char *inpath1, const char *inpath2) { - ptr res; char *path1, *path2; - - path1 = S_malloc_pathname(inpath1); - path2 = S_malloc_pathname(inpath2); - res = RENAME(path1, path2) == 0 ? Strue : S_strerror(errno); - free(path1); - free(path2); - return res; -} - -static ptr s_chmod(const char *inpath, INT mode) { - ptr res; INT status; char *path; - - path = S_malloc_pathname(inpath); -#ifdef WIN32 - /* pathetic approximation: (a) only handles user permissions, (b) doesn't - handle execute permissions, (c) windows won't make file not readable */ - status = CHMOD(path, - (mode & 0400 ? S_IREAD : 0) | - (mode & 0200 ? S_IWRITE : 0)); -#else /* WIN32 */ - status = CHMOD(path, mode); -#endif /* WIN32 */ - res = status == 0 ? Strue : S_strerror(errno); - free(path); - return res; -} - -static ptr s_getmod(const char *inpath, IBOOL followp) { - ptr res; char *path; struct STATBUF statbuf; - - path = S_malloc_pathname(inpath); - - /* according to msdn, user read/write bits are set according to the file's - permission mode, and user execute bits are set according to the - filename extension. it says nothing about group and other execute bits. */ - - if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) { - res = S_strerror(errno); - } else { - res = FIX(statbuf.st_mode & 07777); - } - free(path); - return res; -} - -static ptr s_path_atime(const char *inpath, IBOOL followp) { -#ifdef WIN32 - ptr res; - wchar_t *wpath; - WIN32_FILE_ATTRIBUTE_DATA filedata; - __int64 total, sec; int nsec; - - if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { - res = S_LastErrorString(); - } else if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) { - DWORD err = GetLastError(); - res = err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ? - Sstring("no such file or directory") : - S_LastErrorString(); - } else { - total = filedata.ftLastAccessTime.dwHighDateTime; - total <<= 32; - total |= filedata.ftLastAccessTime.dwLowDateTime; - sec = total / 10000000 - 11644473600L; - nsec = (total % 10000000) * 100; - res = Scons(Sinteger64(sec), Sinteger32(nsec)); - } - free(wpath); - return res; -#else /* WIN32 */ - ptr res; - char *path; - struct STATBUF statbuf; - - path = S_malloc_pathname(inpath); - if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) { - res = S_strerror(errno); - } else { - res = Scons(Sinteger64(SECATIME(statbuf)), Sinteger32(NSECATIME(statbuf))); - } - free(path); - return res; -#endif /* WIN32 */ -} - -static ptr s_path_ctime(const char *inpath, IBOOL followp) { -#ifdef WIN32 - ptr res; - wchar_t *wpath; - WIN32_FILE_ATTRIBUTE_DATA filedata; - __int64 total, sec; int nsec; - - if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { - res = S_LastErrorString(); - } else if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) { - DWORD err = GetLastError(); - res = err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ? - Sstring("no such file or directory") : - S_LastErrorString(); - } else { - total = filedata.ftLastWriteTime.dwHighDateTime; - total <<= 32; - total |= filedata.ftLastWriteTime.dwLowDateTime; - sec = total / 10000000 - 11644473600L; - nsec = (total % 10000000) * 100; - res = Scons(Sinteger64(sec), Sinteger32(nsec)); - } - free(wpath); - return res; -#else /* WIN32 */ - ptr res; - char *path; - struct STATBUF statbuf; - - path = S_malloc_pathname(inpath); - if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) { - res = S_strerror(errno); - } else { - res = Scons(Sinteger64(SECCTIME(statbuf)), Sinteger32(NSECCTIME(statbuf))); - } - free(path); - return res; -#endif /* WIN32 */ -} - -static ptr s_path_mtime(const char *inpath, IBOOL followp) { -#ifdef WIN32 - ptr res; - wchar_t *wpath; - WIN32_FILE_ATTRIBUTE_DATA filedata; - __int64 total, sec; int nsec; - - if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { - res = S_LastErrorString(); - } else if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) { - DWORD err = GetLastError(); - res = err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ? - Sstring("no such file or directory") : - S_LastErrorString(); - } else { - total = filedata.ftLastWriteTime.dwHighDateTime; - total <<= 32; - total |= filedata.ftLastWriteTime.dwLowDateTime; - sec = total / 10000000 - 11644473600L; - nsec = (total % 10000000) * 100; - res = Scons(Sinteger64(sec), Sinteger32(nsec)); - } - free(wpath); - return res; -#else /* WIN32 */ - ptr res; - char *path; - struct STATBUF statbuf; - - path = S_malloc_pathname(inpath); - if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) { - res = S_strerror(errno); - } else { - res = Scons(Sinteger64(SECMTIME(statbuf)), Sinteger32(NSECMTIME(statbuf))); - } - free(path); - return res; -#endif /* WIN32 */ -} - -static ptr s_fd_atime(INT fd) { - struct STATBUF statbuf; - - if (FSTAT(fd, &statbuf) != 0) return S_strerror(errno); - - return Scons(Sinteger64(SECATIME(statbuf)), Sinteger32(NSECATIME(statbuf))); -} - -static ptr s_fd_ctime(INT fd) { - struct STATBUF statbuf; - - if (FSTAT(fd, &statbuf) != 0) return S_strerror(errno); - - return Scons(Sinteger64(SECCTIME(statbuf)), Sinteger32(NSECCTIME(statbuf))); -} - -static ptr s_fd_mtime(INT fd) { - struct STATBUF statbuf; - - if (FSTAT(fd, &statbuf) != 0) return S_strerror(errno); - - return Scons(Sinteger64(SECMTIME(statbuf)), Sinteger32(NSECMTIME(statbuf))); -} - -static IBOOL s_fd_regularp(INT fd) { - struct STATBUF statbuf; - - if (FSTAT(fd, &statbuf) != 0) return 0; - - return statbuf.st_mode & S_IFREG; -} - -static void s_nanosleep(ptr xsec, ptr xnsec) { - ptr tc = get_thread_context(); - U64 sec = Sunsigned64_value(xsec); - U32 nsec = Sunsigned32_value(xnsec); -#ifdef PTHREADS - if (DISABLECOUNT(tc) == 0) { - deactivate_thread(tc) - } -#endif /* PTHREADS */ - /* give up our lightweight thread "quanta" */ - if (DISABLECOUNT(tc) == 0) { - TRAP(get_thread_context()) = (ptr)1; - } -#ifdef WIN32 - /* round to nearest ms represented by sec and nsec */ - Sleep((DWORD)(sec * 1000 + (nsec + 500000) / 1000000)); -#else /* WIN32 */ - struct timespec rqtp; - rqtp.tv_sec = sec; - rqtp.tv_nsec = nsec; - nanosleep(&rqtp, NULL); -#endif /* WIN32 */ -#ifdef PTHREADS - if (DISABLECOUNT(tc) == 0) { - reactivate_thread(tc) - } -#endif /* PTHREADS */ -} - -static int s_getpid(void) { - return GETPID(); -} - -static ptr s_set_collect_trip_bytes(ptr n) { - S_G.collect_trip_bytes = Sunsigned_value(n); - return Svoid; -} - -static void c_exit(UNUSED I32 status) { - S_abnormal_exit(); -} - -static double s_mod(double x, double y) { return fmod(x, y); } - -static double s_exp(double x) { return exp(x); } - -static double s_log(double x) { return log(x); } - -#if (machine_type == machine_type_i3fb || machine_type == machine_type_ti3fb) -#include -/* freebsd's pow delivers precise results for integer inputs, e.g., - * 10.0^21.0, only with * extended-precision (80-bit) floats */ -static double s_pow(double x, double y) { - fp_prec_t p; - p = fpgetprec(); - if (p != FP_PE) { - double ans; - fpsetprec(FP_PE); - ans = pow(x, y); - fpsetprec(p); - return ans; - } else - return pow(x, y); -} -#elif defined(MACOSX) -/* intel macosx delivers precise results for integer inputs, e.g., - * 10.0^21.0, only with long double version of pow */ -static double s_pow(double x, double y) { return powl(x, y); } -#else /* i3fb/ti3fb */ -static double s_pow(double x, double y) { return pow(x, y); } -#endif /* i3fb/ti3fb */ - -static double s_sqrt(double x) { return sqrt(x); } - -static double s_sin(double x) { return sin(x); } - -static double s_cos(double x) { return cos(x); } - -static double s_tan(double x) { return tan(x); } - -static double s_asin(double x) { return asin(x); } - -static double s_acos(double x) { return acos(x); } - -static double s_atan(double x) { return atan(x); } - -static double s_atan2(double x, double y) { return atan2(x, y); } - -static double s_sinh(double x) { return sinh(x); } - -static double s_cosh(double x) { return cosh(x); } - -static double s_tanh(double x) { return tanh(x); } - -static double s_floor(double x) { return floor(x); } - -static double s_ceil(double x) { return ceil(x); } - -static double s_hypot(double x, double y) { return HYPOT(x, y); } - -#ifdef ARCHYPERBOLIC -static double s_asinh(double x) { return asinh(x); } - -static double s_acosh(double x){ return acosh(x); } - -static double s_atanh(double x) { return atanh(x); } -#endif /* ARCHHYPERBOLIC */ - -#ifdef LOG1P -static double s_log1p(double x) { return log1p(x); } -#endif /* LOG1P */ - -static ptr s_getenv(char *name) { -#ifdef WIN32 - char *s = Sgetenv(name); -#else /* WIN32 */ - char *s = getenv(name); -#endif /* WIN32 */ - if (s == (char *)0) - return Sfalse; - else { - ptr r = Sstring_utf8(s, -1); -#ifdef WIN32 - free(s); -#endif - return r; - } -} - -static void s_putenv(char *name, char *value) { -#ifdef WIN32 - wchar_t* namew; - wchar_t* valuew; - BOOL rc; - namew = Sutf8_to_wide(name); - valuew = Sutf8_to_wide(value); - rc = SetEnvironmentVariableW(namew, valuew); - free(namew); - free(valuew); - if (rc == 0) - S_error1("putenv", "environment extension failed: ~a", S_LastErrorString()); -#else /* WIN32 */ - if (setenv(name, value, 1) != 0) { - ptr msg = S_strerror(errno); - - if (msg != Sfalse) - S_error1("putenv", "environment extension failed: ~a", msg); - else - S_error("putenv", "environment extension failed"); - } -#endif /* WIN32 */ -} - -#ifdef PTHREADS -/* backdoor thread is for testing thread creation by Sactivate_thread */ -#define display(s) { const char *S = (s); if (WRITE(1, S, (unsigned int)strlen(S))) {} } -static s_thread_rv_t s_backdoor_thread_start(void *p) { - display("backdoor thread started\n") - (void) Sactivate_thread(); - display("thread activated\n") - Scall0((ptr)p); - (void) Sdeactivate_thread(); - display("thread deactivated\n") - (void) Sactivate_thread(); - display("thread reactivated\n") - Scall0((ptr)p); - Sdestroy_thread(); - display("thread destroyed\n") - s_thread_return; -} - -static iptr s_backdoor_thread(ptr p) { - display("creating thread\n"); - return s_thread_create(s_backdoor_thread_start, (void *)p); -} - -static ptr s_threads(void) { - return S_threads; -} - -static void s_mutex_acquire(scheme_mutex_t *m) { - ptr tc = get_thread_context(); - - if (m == &S_tc_mutex) { - S_mutex_acquire(m); - return; - } - - if (S_mutex_tryacquire(m) == 0) return; - - if (DISABLECOUNT(tc) == 0) { - deactivate_thread(tc) - } - S_mutex_acquire(m); - if (DISABLECOUNT(tc) == 0) { - reactivate_thread(tc) - } -} - -static ptr s_mutex_acquire_noblock(scheme_mutex_t *m) { - return S_mutex_tryacquire(m) == 0 ? Strue : Sfalse; -} - -static void s_condition_broadcast(s_thread_cond_t *c) { - s_thread_cond_broadcast(c); -} - -static void s_condition_signal(s_thread_cond_t *c) { - s_thread_cond_signal(c); -} -#endif - -static ptr s_profile_counters(void) { - return S_G.profile_counters; -} - -/* s_profile_release_counters assumes and maintains the property that each pair's - tail is not younger than the pair and thereby avoids dirty sets. */ -static ptr s_profile_release_counters(void) { - ptr tossed, *p_keep, *p_toss, ls; - p_keep = &S_G.profile_counters; - p_toss = &tossed; - for (ls = *p_keep; ls != Snil && (MaybeSegInfo(ptr_get_segment(ls)))->generation <= S_G.prcgeneration; ls = Scdr(ls)) { - if (Sbwp_objectp(CAAR(ls))) { - *p_toss = ls; - p_toss = &Scdr(ls); - } else { - *p_keep = ls; - p_keep = &Scdr(ls); - } - } - *p_keep = ls; - *p_toss = Snil; - S_G.prcgeneration = 0; - return tossed; -} - -void S_dump_tc(ptr tc) { - INT i; - - printf("AC0=%p AC1=%p SFP=%p CP=%p\n", AC0(tc), AC1(tc), SFP(tc), CP(tc)); - printf("ESP=%p AP=%p EAP=%p\n", ESP(tc), AP(tc), EAP(tc)); - printf("TRAP=%p XP=%p YP=%p REAL_EAP=%p\n", TRAP(tc), XP(tc), YP(tc), REAL_EAP(tc)); - printf("CCHAIN=%p RANDOMSEED=%ld SCHEMESTACK=%p STACKCACHE=%p\n", CCHAIN(tc), (long)RANDOMSEED(tc), SCHEMESTACK(tc), STACKCACHE(tc)); - printf("STACKLINK=%p SCHEMESTACKSIZE=%ld WINDERS=%p U=%p\n", STACKLINK(tc), (long)SCHEMESTACKSIZE(tc), WINDERS(tc), U(tc)); - printf("V=%p W=%p X=%p Y=%p\n", V(tc), W(tc), X(tc), Y(tc)); - printf("SOMETHING=%p KBDPEND=%p SIGPEND=%p TIMERTICKS=%p\n", SOMETHINGPENDING(tc), KEYBOARDINTERRUPTPENDING(tc), SIGNALINTERRUPTPENDING(tc), TIMERTICKS(tc)); - printf("DISABLECOUNT=%p PARAMETERS=%p\n", DISABLECOUNT(tc), PARAMETERS(tc)); - for (i = 0 ; i < virtual_register_count ; i += 1) { - printf("VIRTREG[%d]=%p", i, VIRTREG(tc, i)); - if ((i & 0x11) == 0x11 || i == virtual_register_count - 1) printf("\n"); - } - fflush(stdout); -} - -void S_prim5_init(void) { - if (!S_boot_time) return; - -#ifdef PTHREADS - Sforeign_symbol("(cs)fork_thread", (void *)S_fork_thread); - Sforeign_symbol("(cs)make_mutex", (void *)S_make_mutex); - Sforeign_symbol("(cs)mutex_free", (void *)S_mutex_free); - Sforeign_symbol("(cs)backdoor_thread", (void *)s_backdoor_thread); - Sforeign_symbol("(cs)threads", (void *)s_threads); - Sforeign_symbol("(cs)mutex_acquire", (void *)s_mutex_acquire); - Sforeign_symbol("(cs)mutex_release", (void *)S_mutex_release); - Sforeign_symbol("(cs)mutex_acquire_noblock", (void *)s_mutex_acquire_noblock); - Sforeign_symbol("(cs)make_condition", (void *)S_make_condition); - Sforeign_symbol("(cs)condition_free", (void *)S_condition_free); - Sforeign_symbol("(cs)condition_broadcast", (void *)s_condition_broadcast); - Sforeign_symbol("(cs)condition_signal", (void *)s_condition_signal); - Sforeign_symbol("(cs)condition_wait", (void *)S_condition_wait); -#endif - Sforeign_symbol("(cs)s_addr_in_heap", (void *)s_addr_in_heap); - Sforeign_symbol("(cs)s_ptr_in_heap", (void *)s_ptr_in_heap); - Sforeign_symbol("(cs)generation", (void *)s_generation); - Sforeign_symbol("(cs)s_fltofx", (void *)s_fltofx); - Sforeign_symbol("(cs)s_weak_cons", (void *)S_weak_cons); - Sforeign_symbol("(cs)s_weak_pairp", (void *)s_weak_pairp); - Sforeign_symbol("(cs)s_ephemeron_cons", (void *)s_ephemeron_cons); - Sforeign_symbol("(cs)s_ephemeron_pairp", (void *)s_ephemeron_pairp); - Sforeign_symbol("(cs)continuation_depth", (void *)S_continuation_depth); - Sforeign_symbol("(cs)single_continuation", (void *)S_single_continuation); - Sforeign_symbol("(cs)c_exit", (void *)c_exit); - Sforeign_symbol("(cs)s_set_collect_trip_bytes", (void *)s_set_collect_trip_bytes); - Sforeign_symbol("(cs)s_oblist", (void *)s_oblist); - Sforeign_symbol("(cs)s_showalloc", (void *)s_showalloc); - Sforeign_symbol("(cs)s_system", (void *)s_system); - Sforeign_symbol("(cs)s_process", (void *)s_process); - Sforeign_symbol("(cs)s_set_code_byte", (void *)s_set_code_byte); - Sforeign_symbol("(cs)s_set_code_word", (void *)s_set_code_word); - Sforeign_symbol("(cs)s_set_code_long", (void *)s_set_code_long); - Sforeign_symbol("(cs)s_set_code_quad", (void *)s_set_code_quad); - Sforeign_symbol("(cs)s_set_reloc", (void *)s_set_reloc); - Sforeign_symbol("(cs)get_code_obj", (void *)S_get_code_obj); - Sforeign_symbol("(cs)s_flush_instruction_cache", (void *)s_flush_instruction_cache); - Sforeign_symbol("(cs)s_make_reloc_table", (void *)s_make_reloc_table); - Sforeign_symbol("(cs)s_make_closure", (void *)s_make_closure); - Sforeign_symbol("(cs)s_intern", (void *)s_intern); - Sforeign_symbol("(cs)s_intern2", (void *)s_intern2); - Sforeign_symbol("(cs)s_intern3", (void *)s_intern3); - Sforeign_symbol("(cs)s_strings_to_gensym", (void *)s_strings_to_gensym); - Sforeign_symbol("(cs)s_intern_gensym", (void *)S_intern_gensym); - Sforeign_symbol("(cs)cputime", (void *)S_cputime); - Sforeign_symbol("(cs)realtime", (void *)S_realtime); - Sforeign_symbol("(cs)clock_gettime", (void *)S_clock_gettime); - Sforeign_symbol("(cs)gmtime", (void *)S_gmtime); - Sforeign_symbol("(cs)asctime", (void *)S_asctime); - Sforeign_symbol("(cs)mktime", (void *)S_mktime); - Sforeign_symbol("(cs)unique_id", (void *)S_unique_id); - Sforeign_symbol("(cs)file_existsp", (void *)S_file_existsp); - Sforeign_symbol("(cs)file_regularp", (void *)S_file_regularp); - Sforeign_symbol("(cs)file_directoryp", (void *)S_file_directoryp); - Sforeign_symbol("(cs)file_symbolic_linkp", (void *)S_file_symbolic_linkp); - Sforeign_symbol("(cs)delete_file", (void *)s_delete_file); - Sforeign_symbol("(cs)delete_directory", (void *)s_delete_directory); - Sforeign_symbol("(cs)rename_file", (void *)s_rename_file); - Sforeign_symbol("(cs)mkdir", (void *)s_mkdir); - Sforeign_symbol("(cs)chmod", (void *)s_chmod); - Sforeign_symbol("(cs)getmod", (void *)s_getmod); - Sforeign_symbol("(cs)path_atime", (void *)s_path_atime); - Sforeign_symbol("(cs)path_ctime", (void *)s_path_ctime); - Sforeign_symbol("(cs)path_mtime", (void *)s_path_mtime); - Sforeign_symbol("(cs)fd_atime", (void *)s_fd_atime); - Sforeign_symbol("(cs)fd_ctime", (void *)s_fd_ctime); - Sforeign_symbol("(cs)fd_mtime", (void *)s_fd_mtime); - Sforeign_symbol("(cs)fd_regularp", (void *)s_fd_regularp); - Sforeign_symbol("(cs)nanosleep", (void *)s_nanosleep); - Sforeign_symbol("(cs)getpid", (void *)s_getpid); - Sforeign_symbol("(cs)fasl_read", (void *)S_fasl_read); - Sforeign_symbol("(cs)bv_fasl_read", (void *)S_bv_fasl_read); - Sforeign_symbol("(cs)s_decode_float", (void *)s_decode_float); - - Sforeign_symbol("(cs)new_open_input_fd", (void *)S_new_open_input_fd); - Sforeign_symbol("(cs)new_open_output_fd", (void *)S_new_open_output_fd); - Sforeign_symbol("(cs)new_open_input_output_fd", (void *)S_new_open_input_output_fd); - Sforeign_symbol("(cs)close_fd", (void *)S_close_fd); - Sforeign_symbol("(cs)gzxfile_fd", (void *)S_gzxfile_fd); - Sforeign_symbol("(cs)compress_input_fd", (void *)S_compress_input_fd); - Sforeign_symbol("(cs)compress_output_fd", (void *)S_compress_output_fd); - - Sforeign_symbol("(cs)bytevector_read", (void*)S_bytevector_read); - Sforeign_symbol("(cs)bytevector_read_nb", (void*)S_bytevector_read_nb); - Sforeign_symbol("(cs)bytevector_write", (void*)S_bytevector_write); - Sforeign_symbol("(cs)put_byte", (void*)S_put_byte); - Sforeign_symbol("(cs)get_fd_pos", (void*)S_get_fd_pos); - Sforeign_symbol("(cs)set_fd_pos", (void*)S_set_fd_pos); - Sforeign_symbol("(cs)get_fd_non_blocking", (void*)S_get_fd_non_blocking); - Sforeign_symbol("(cs)set_fd_non_blocking", (void*)S_set_fd_non_blocking); - Sforeign_symbol("(cs)get_fd_length", (void*)S_get_fd_length); - Sforeign_symbol("(cs)set_fd_length", (void*)S_set_fd_length); - - Sforeign_symbol("(cs)bytevector_compress_size", (void*)S_bytevector_compress_size); - Sforeign_symbol("(cs)bytevector_compress", (void*)S_bytevector_compress); - Sforeign_symbol("(cs)bytevector_uncompress", (void*)S_bytevector_uncompress); - - Sforeign_symbol("(cs)logand", (void *)S_logand); - Sforeign_symbol("(cs)logbitp", (void *)S_logbitp); - Sforeign_symbol("(cs)logbit0", (void *)S_logbit0); - Sforeign_symbol("(cs)logbit1", (void *)S_logbit1); - Sforeign_symbol("(cs)logtest", (void *)S_logtest); - Sforeign_symbol("(cs)logor", (void *)S_logor); - Sforeign_symbol("(cs)logxor", (void *)S_logxor); - Sforeign_symbol("(cs)lognot", (void *)S_lognot); - Sforeign_symbol("(cs)fxmul", (void *)s_fxmul); - Sforeign_symbol("(cs)fxdiv", (void *)s_fxdiv); - Sforeign_symbol("(cs)s_big_negate", (void *)S_big_negate); - Sforeign_symbol("(cs)add", (void *)S_add); - Sforeign_symbol("(cs)gcd", (void *)S_gcd); - Sforeign_symbol("(cs)mul", (void *)S_mul); - Sforeign_symbol("(cs)s_ash", (void *)S_ash); - Sforeign_symbol("(cs)s_big_positive_bit_field", (void *)S_big_positive_bit_field); - Sforeign_symbol("(cs)s_big_eq", (void *)S_big_eq); - Sforeign_symbol("(cs)s_big_lt", (void *)S_big_lt); - Sforeign_symbol("(cs)s_bigoddp", (void *)s_bigoddp); - Sforeign_symbol("(cs)s_div", (void *)S_div); - Sforeign_symbol("(cs)s_float", (void *)s_float); - Sforeign_symbol("(cs)s_flrandom", (void *)s_flrandom); - Sforeign_symbol("(cs)s_fxrandom", (void *)s_fxrandom); - Sforeign_symbol("(cs)s_integer_length", (void *)S_integer_length); - Sforeign_symbol("(cs)s_big_first_bit_set", (void *)S_big_first_bit_set); - Sforeign_symbol("(cs)s_make_code", (void *)s_make_code); - Sforeign_symbol("(cs)s_random_seed", (void *)s_random_seed); - Sforeign_symbol("(cs)s_set_code_long2", (void *)s_set_code_long2); - Sforeign_symbol("(cs)s_set_random_seed", (void *)s_set_random_seed); - Sforeign_symbol("(cs)ss_trunc", (void *)S_trunc); - Sforeign_symbol("(cs)ss_trunc_rem", (void *)s_trunc_rem); - Sforeign_symbol("(cs)sub", (void *)S_sub); - Sforeign_symbol("(cs)rem", (void *)S_rem); -#ifdef GETWD - Sforeign_symbol("(cs)s_getwd", (void *)s_getwd); -#endif - Sforeign_symbol("(cs)s_chdir", (void *)s_chdir); -#ifdef WIN32 - Sforeign_symbol("(cs)find_files", (void *)S_find_files); -#else - Sforeign_symbol("(cs)directory_list", (void *)S_directory_list); -#endif - Sforeign_symbol("(cs)dequeue_scheme_signals", (void *)S_dequeue_scheme_signals); - Sforeign_symbol("(cs)register_scheme_signal", (void *)S_register_scheme_signal); - - Sforeign_symbol("(cs)mod", (void *)s_mod); - Sforeign_symbol("(cs)exp", (void *)s_exp); - Sforeign_symbol("(cs)log", (void *)s_log); - Sforeign_symbol("(cs)pow", (void *)s_pow); - Sforeign_symbol("(cs)sqrt", (void *)s_sqrt); - Sforeign_symbol("(cs)sin", (void *)s_sin); - Sforeign_symbol("(cs)cos", (void *)s_cos); - Sforeign_symbol("(cs)tan", (void *)s_tan); - Sforeign_symbol("(cs)asin", (void *)s_asin); - Sforeign_symbol("(cs)acos", (void *)s_acos); - Sforeign_symbol("(cs)atan", (void *)s_atan); - Sforeign_symbol("(cs)atan2", (void *)s_atan2); - Sforeign_symbol("(cs)sinh", (void *)s_sinh); - Sforeign_symbol("(cs)cosh", (void *)s_cosh); - Sforeign_symbol("(cs)tanh", (void *)s_tanh); - Sforeign_symbol("(cs)floor", (void *)s_floor); - Sforeign_symbol("(cs)ceil", (void *)s_ceil); - Sforeign_symbol("(cs)hypot", (void *)s_hypot); - -#ifdef ARCHYPERBOLIC - Sforeign_symbol("(cs)asinh", (void *)s_asinh); - Sforeign_symbol("(cs)acosh", (void *)s_acosh); - Sforeign_symbol("(cs)atanh", (void *)s_atanh); -#endif /* ARCHHYPERBOLIC */ - -#ifdef LOG1P - Sforeign_symbol("(cs)log1p", (void *)s_log1p); -#endif /* LOG1P */ - - Sforeign_symbol("(cs)s_get_reloc", (void *)s_get_reloc); - Sforeign_symbol("(cs)getenv", (void *)s_getenv); - Sforeign_symbol("(cs)putenv", (void *)s_putenv); - Sforeign_symbol("(cs)byte-copy", (void *)s_byte_copy); - Sforeign_symbol("(cs)ptr-copy", (void *)s_ptr_copy); - Sforeign_symbol("(cs)boot-error", (void *)S_boot_error); - Sforeign_symbol("(cs)s_tlv", (void *)s_tlv); - Sforeign_symbol("(cs)s_stlv", (void *)s_stlv); - Sforeign_symbol("(cs)s_test_schlib", (void *)s_test_schlib); - Sforeign_symbol("(cs)Sinteger_value", (void *)Sinteger_value); - Sforeign_symbol("(cs)Sinteger32_value", (void *)Sinteger32_value); - Sforeign_symbol("(cs)Sinteger64_value", (void *)Sinteger64_value); - Sforeign_symbol("(cs)s_breakhere", (void *)s_breakhere); - Sforeign_symbol("(cs)s_interactivep", (void *)s_interactivep); - Sforeign_symbol("(cs)same_devicep", (void *)s_same_devicep); - Sforeign_symbol("(cs)malloc", (void *)s_malloc); - Sforeign_symbol("(cs)free", (void *)s_free); -#ifdef FEATURE_ICONV - Sforeign_symbol("(cs)s_iconv_open", (void *)s_iconv_open); - Sforeign_symbol("(cs)s_iconv_close", (void *)s_iconv_close); - Sforeign_symbol("(cs)s_iconv_from_string", (void *)s_iconv_from_string); - Sforeign_symbol("(cs)s_iconv_to_string", (void *)s_iconv_to_string); -#endif - Sforeign_symbol("(cs)s_strerror", (void *)S_strerror); - Sforeign_symbol("(cs)s_errno", (void *)s_errno); -#ifdef WIN32 - Sforeign_symbol("(cs)s_multibytetowidechar", (void *)s_multibytetowidechar); - Sforeign_symbol("(cs)s_widechartomultibyte", (void *)s_widechartomultibyte); -#endif - Sforeign_symbol("(cs)s_profile_counters", (void *)s_profile_counters); - Sforeign_symbol("(cs)s_profile_release_counters", (void *)s_profile_release_counters); -} - -static ptr s_get_reloc(ptr co) { - ptr t, ls; uptr a, m, n; - - require(Scodep(co),"s_get_reloc","~s is not a code object",co); - ls = Snil; - t = CODERELOC(co); - m = RELOCSIZE(t); - a = 0; - n = 0; - while (n < m) { - uptr entry, item_off, code_off; ptr obj; - entry = RELOCIT(t, n); n += 1; - if (RELOC_EXTENDED_FORMAT(entry)) { - item_off = RELOCIT(t, n); n += 1; - code_off = RELOCIT(t, n); n += 1; - } else { - item_off = RELOC_ITEM_OFFSET(entry); - code_off = RELOC_CODE_OFFSET(entry); - } - a += code_off; - obj = S_get_code_obj(RELOC_TYPE(entry), co, a, item_off); - if (!Sfixnump(obj)) { - ptr x; - for (x = ls; ; x = Scdr(x)) { - if (x == Snil) { - ls = Scons(obj,ls); - break; - } else if (Scar(x) == obj) - break; - } - } - } - return ls; -} - -static void s_byte_copy(ptr src, iptr srcoff, ptr dst, iptr dstoff, iptr cnt) { - void *srcaddr = (void *)((iptr)src + srcoff); - void *dstaddr = (void *)((iptr)dst + dstoff); - if (dst != src) - memcpy(dstaddr, srcaddr, cnt); - else - memmove(dstaddr, srcaddr, cnt); -} - -static void s_ptr_copy(ptr src, iptr srcoff, ptr dst, iptr dstoff, iptr cnt) { - void *srcaddr = (void *)((iptr)src + srcoff); - void *dstaddr = (void *)((iptr)dst + dstoff); - cnt = cnt << log2_ptr_bytes; - if (dst != src) - memcpy(dstaddr, srcaddr, cnt); - else - memmove(dstaddr, srcaddr, cnt); -} - -/* these are used only for testing */ -static ptr s_tlv(ptr x) { - return Stop_level_value(x); -} - -static void s_stlv(ptr x, ptr v) { - Sset_top_level_value(x, v); -} - -#define SCHLIBTEST(expr) {\ - test += 1;\ - if (!(expr)) S_error1("s_test_schlib", "test ~s failed", FIX(test));\ -} - -static void s_test_schlib(void) { - INT test = 0; - I32 n1 = 0x73215609; - I64 n2 = n1 * 37; - I32 n3 = (I32)1<<31; - I64 n4 = (I64)1<<63; - I32 n5 = -1; - - SCHLIBTEST(Sinteger_value(Sinteger(n1)) == n1) - SCHLIBTEST(Sinteger_value(Sinteger(-n1)) == -n1) - SCHLIBTEST(Sinteger_value(Sunsigned(n1)) == n1) - SCHLIBTEST(Sinteger_value(Sunsigned(-n1)) == -n1) - SCHLIBTEST(Sinteger32_value(Sinteger32(n1)) == n1) - SCHLIBTEST(Sinteger32_value(Sinteger32(-n1)) == -n1) - SCHLIBTEST(Sinteger32_value(Sunsigned32(n1)) == n1) - SCHLIBTEST(Sinteger32_value(Sunsigned32(-n1)) == -n1) - SCHLIBTEST(Sinteger64_value(Sinteger64(n1)) == n1) - SCHLIBTEST(Sinteger64_value(Sinteger64(-n1)) == -n1) - SCHLIBTEST(Sinteger64_value(Sunsigned64(n1)) == n1) - SCHLIBTEST(Sinteger64_value(Sunsigned64(-n1)) == -n1) -#if (ptr_bits == 64) - SCHLIBTEST(Sinteger_value(Sinteger(n2)) == n2) - SCHLIBTEST(Sinteger_value(Sinteger(-n2)) == -n2) - SCHLIBTEST(Sinteger_value(Sunsigned(n2)) == n2) - SCHLIBTEST(Sinteger_value(Sunsigned(-n2)) == -n2) -#endif - SCHLIBTEST(Sinteger64_value(Sinteger64(n2)) == n2) - SCHLIBTEST(Sinteger64_value(Sinteger64(-n2)) == -n2) - SCHLIBTEST(Sinteger64_value(Sunsigned64(n2)) == n2) - SCHLIBTEST(Sinteger64_value(Sunsigned64(-n2)) == -n2) - - SCHLIBTEST(Sinteger_value(Sinteger(n3)) == n3) - SCHLIBTEST(Sinteger_value(Sunsigned(n3)) == n3) - SCHLIBTEST(Sinteger32_value(Sinteger32(n3)) == n3) - SCHLIBTEST(Sinteger32_value(Sunsigned32(n3)) == n3) - SCHLIBTEST(Sinteger64_value(Sinteger64(n3)) == n3) - SCHLIBTEST(Sinteger64_value(Sunsigned64(n3)) == n3) -#if (ptr_bits == 64) - SCHLIBTEST(Sinteger_value(Sunsigned(n4)) == n4) - SCHLIBTEST(Sinteger_value(Sinteger(n4)) == n4) - SCHLIBTEST(Sinteger_value(Sunsigned(n4)) == n4) -#endif - SCHLIBTEST(Sinteger64_value(Sinteger64(n4)) == n4) - SCHLIBTEST(Sinteger64_value(Sunsigned64(n4)) == n4) - - SCHLIBTEST(Sinteger_value(Sinteger(n5)) == n5) - SCHLIBTEST(Sinteger_value(Sinteger(-n5)) == -n5) - SCHLIBTEST(Sinteger_value(Sunsigned(n5)) == n5) - SCHLIBTEST(Sinteger_value(Sunsigned(-n5)) == -n5) - SCHLIBTEST(Sinteger32_value(Sinteger32(n5)) == n5) - SCHLIBTEST(Sinteger32_value(Sinteger32(-n5)) == -n5) - SCHLIBTEST(Sinteger32_value(Sunsigned32(n5)) == n5) - SCHLIBTEST(Sinteger32_value(Sunsigned32(-n5)) == -n5) - SCHLIBTEST(Sinteger64_value(Sinteger64(n5)) == n5) - SCHLIBTEST(Sinteger64_value(Sinteger64(-n5)) == -n5) - SCHLIBTEST(Sinteger64_value(Sunsigned64(n5)) == n5) - SCHLIBTEST(Sinteger64_value(Sunsigned64(-n5)) == -n5) -} - -/* place to break when debugging */ -static void s_breakhere(UNUSED ptr x) { - return; -} - -static IBOOL s_interactivep(void) { - static INT interactivep = -1; - if (interactivep == -1) { -#ifdef WIN32 - HANDLE hStdout, hStdin; - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - DWORD InMode, OutMode; - interactivep = - (hStdin = GetStdHandle(STD_INPUT_HANDLE)) != INVALID_HANDLE_VALUE - && (hStdout = GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE - && GetConsoleScreenBufferInfo(hStdout, &csbiInfo) - && GetConsoleMode(hStdin, &InMode) - && GetConsoleMode(hStdout, &OutMode); -#else /* WIN32 */ - interactivep = isatty(0) && isatty(1); -#endif /* WIN32 */ - } - return interactivep; -} - -static IBOOL s_same_devicep(INT fd1, INT fd2) { -#ifdef WIN32 - HANDLE h1, h2; DWORD mode1, mode2; - if ((h1 = (HANDLE)_get_osfhandle(fd1)) != INVALID_HANDLE_VALUE) - if ((h2 = (HANDLE)_get_osfhandle(fd2)) != INVALID_HANDLE_VALUE) - switch (GetFileType(h1)) { - case FILE_TYPE_CHAR: - if (GetFileType(h2) == FILE_TYPE_CHAR) - return GetConsoleMode(h1, &mode1) && GetConsoleMode(h2, &mode2); - break; - case FILE_TYPE_DISK: - if (GetFileType(h2) == FILE_TYPE_DISK) { - BY_HANDLE_FILE_INFORMATION info1, info2; - if (GetFileInformationByHandle(h1, &info1) && GetFileInformationByHandle(h1, &info2)) - return info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber - && info1.nFileIndexHigh == info2.nFileIndexHigh - && info1.nFileIndexLow == info2.nFileIndexLow; - } - break; - case FILE_TYPE_PIPE: - /* no clue */ - break; - default: break; - } -#else /* WIN32 */ - struct STATBUF statbuf1, statbuf2; - if (FSTAT(fd1, &statbuf1) == 0 && FSTAT(fd2, &statbuf2) == 0) - return statbuf1.st_ino == statbuf2.st_ino; -#endif /* WIN32 */ - - return 0; -} - -static uptr s_malloc(iptr n) { - void *p; - if ((p = malloc((size_t)n)) == NULL) { - ptr msg = S_strerror(errno); - - if (msg != Sfalse) - S_error1("foreign-alloc", "~a", msg); - else - S_error("foreign-alloc", "malloc failed"); - } - return (uptr)p; -} - -static void s_free(uptr addr) { - free((void *)addr); -} - -#ifdef FEATURE_ICONV -#ifdef WIN32 -typedef void *iconv_t; -typedef __declspec(dllimport) iconv_t (*iconv_open_ft)(const char *tocode, const char *fromcode); -typedef __declspec(dllimport) size_t (*iconv_ft)(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); -typedef __declspec(dllimport) int (*iconv_close_ft)(iconv_t cd); - -static iconv_open_ft iconv_open_f = (iconv_open_ft)0; -static iconv_ft iconv_f = (iconv_ft)0; -static iconv_close_ft iconv_close_f = (iconv_close_ft)0; -#define ICONV_OPEN iconv_open_f -#define ICONV iconv_f -#define ICONV_CLOSE iconv_close_f -#else -#include -#define ICONV_OPEN iconv_open -#define ICONV iconv -#define ICONV_CLOSE iconv_close -#endif - -#ifdef WIN32 -static ptr s_iconv_trouble(HMODULE h, const char *what) { - wchar_t dllw[PATH_MAX]; - char *dll; - size_t n; - char *msg; - ptr r; - if (0 != GetModuleFileNameW(h, dllw, PATH_MAX)) - dll = Swide_to_utf8(dllw); - else - dll = NULL; - FreeLibrary(h); - n = strlen(what) + strlen(dll) + 17; - msg = (char *)malloc(n); - sprintf_s(msg, n, "cannot find %s in %s", what, dll); - free(dll); - r = Sstring_utf8(msg, -1); - free(msg); - return r; -} -#endif /* WIN32 */ - -static ptr s_iconv_open(const char *tocode, const char *fromcode) { - iconv_t cd; -#ifdef WIN32 - static int iconv_is_loaded = 0; - if (!iconv_is_loaded) { - HMODULE h = LoadLibraryW(L"iconv.dll"); - if (h == NULL) h = LoadLibraryW(L"libiconv.dll"); - if (h == NULL) h = LoadLibraryW(L"libiconv-2.dll"); - if (h == NULL) h = LoadLibraryW(L".\\iconv.dll"); - if (h == NULL) h = LoadLibraryW(L".\\libiconv.dll"); - if (h == NULL) h = LoadLibraryW(L".\\libiconv-2.dll"); - if (h == NULL) return Sstring("cannot load iconv.dll, libiconv.dll, or libiconv-2.dll"); - if ((iconv_open_f = (iconv_open_ft)GetProcAddress(h, "iconv_open")) == NULL && - (iconv_open_f = (iconv_open_ft)GetProcAddress(h, "libiconv_open")) == NULL) - return s_iconv_trouble(h, "iconv_open or libiconv_open"); - if ((iconv_f = (iconv_ft)GetProcAddress(h, "iconv")) == NULL && - (iconv_f = (iconv_ft)GetProcAddress(h, "libiconv")) == NULL) - return s_iconv_trouble(h, "iconv or libiconv"); - if ((iconv_close_f = (iconv_close_ft)GetProcAddress(h, "iconv_close")) == NULL && - (iconv_close_f = (iconv_close_ft)GetProcAddress(h, "libiconv_close")) == NULL) - return s_iconv_trouble(h, "iconv_close or libiconv_close"); - iconv_is_loaded = 1; - } -#endif /* WIN32 */ - - if ((cd = ICONV_OPEN(tocode, fromcode)) == (iconv_t)-1) return Sfalse; - - /* have to be able to cast to int, since iconv_open can return (iconv_t)-1 */ - return Sunsigned((uptr)cd); -} - -static void s_iconv_close(uptr cd) { - ICONV_CLOSE((iconv_t)cd); -} - -#define ICONV_BUFSIZ 400 - -static ptr s_iconv_from_string(uptr cd, ptr in, uptr i, uptr iend, ptr out, uptr o, uptr oend) { - U32 buf[ICONV_BUFSIZ]; - char *inbuf, *outbuf; - size_t inbytesleft, outbytesleft; - uptr inmax, k, new_i, new_o; - - outbuf = (char *)&BVIT(out, o); - outbytesleft = oend - o; - - inmax = iend - i; - if (inmax > ICONV_BUFSIZ) inmax = ICONV_BUFSIZ; - if (inmax > outbytesleft) inmax = outbytesleft; - for (k = 0; k < inmax; k += 1) buf[k] = Sstring_ref(in, i + k); - - inbuf = (char *)buf; - inbytesleft = inmax * sizeof(string_char); - - /* we ignore the iconv return value because we consider success to be the consumption - of input or production of output. we set errno to 0 before calling iconv, even though - it should be set properly if neither input is consumed nor output is produced, because, - under Windows, the iconv dll might have been linked against a different C runtime - and might therefore set a different errno */ - errno = 0; - ICONV((iconv_t)cd, (ICONV_INBUF_TYPE)&inbuf, &inbytesleft, &outbuf, &outbytesleft); - new_i = i + inmax - inbytesleft / sizeof(string_char); - new_o = oend - outbytesleft; - if (new_i != i || new_o != o) return Scons(Sinteger(new_i), Sinteger(new_o)); - - switch (errno) { - case EILSEQ: return FIX(SICONV_INVALID); - case EINVAL: return FIX(SICONV_INCOMPLETE); - case E2BIG: return FIX(SICONV_NOROOM); - default: return FIX(SICONV_DUNNO); - } -} - -static ptr s_iconv_to_string(uptr cd, ptr in, uptr i, uptr iend, ptr out, uptr o, uptr oend) { - U32 buf[ICONV_BUFSIZ]; - char *inbuf, *outbuf; - size_t inbytesleft, outbytesleft; - uptr outmax, k, new_i, new_o; - - inbuf = (char *)&BVIT(in, i); - inbytesleft = iend - i; - - outmax = oend - o; - if (outmax > ICONV_BUFSIZ) outmax = ICONV_BUFSIZ; - if (outmax > inbytesleft) outmax = inbytesleft; - - outbuf = (char *)buf; - outbytesleft = outmax * sizeof(string_char); - - /* see the comment about the iconv return value and errno in s_iconv_from_string */ - errno = 0; - ICONV((iconv_t)cd, (ICONV_INBUF_TYPE)&inbuf, &inbytesleft, &outbuf, &outbytesleft); - - outmax -= outbytesleft / sizeof(string_char); - for (k = 0; k < outmax; k += 1) Sstring_set(out, o + k, buf[k]); - new_i = iend - inbytesleft; - new_o = o + outmax; - if (new_i != i || new_o != o) return Scons(Sinteger(new_i), Sinteger(new_o)); - - switch (errno) { - case EILSEQ: return FIX(SICONV_INVALID); - case EINVAL: return FIX(SICONV_INCOMPLETE); - case E2BIG: return FIX(SICONV_NOROOM); - default: return FIX(SICONV_DUNNO); - } -} -#endif /* FEATURE_ICONV */ - -#ifdef WIN32 -static ptr s_multibytetowidechar(unsigned cp, ptr inbv) { - uptr inbytes; int outwords; ptr outbv; - - inbytes = Sbytevector_length(inbv); - -#if (ptr_bits > int_bits) - if ((int)inbytes != inbytes) S_error1("multibyte->string", "input size ~s is beyond MultiByteToWideChar's limit", Sinteger(inbytes)); -#endif - - if ((outwords = MultiByteToWideChar(cp, 0, &BVIT(inbv,0), (int)inbytes, NULL, 0)) == 0) - S_error1("multibyte->string", "conversion failed: ~a", S_LastErrorString()); - - outbv = S_bytevector(outwords * 2); - - if (MultiByteToWideChar(cp, 0, &BVIT(inbv,0), (int)inbytes, (wchar_t *)&BVIT(outbv, 0), outwords) == 0) - S_error1("multibyte->string", "conversion failed: ~a", S_LastErrorString()); - - return outbv; -} - -static ptr s_widechartomultibyte(unsigned cp, ptr inbv) { - uptr inwords; int outbytes; ptr outbv; - - inwords = Sbytevector_length(inbv) / 2; - -#if (ptr_bits > int_bits) - if ((int)inwords != inwords) S_error1("multibyte->string", "input size ~s is beyond WideCharToMultiByte's limit", Sinteger(inwords)); -#endif - - if ((outbytes = WideCharToMultiByte(cp, 0, (wchar_t *)&BVIT(inbv,0), (int)inwords, NULL, 0, NULL, NULL)) == 0) - S_error1("string->multibyte", "conversion failed: ~a", S_LastErrorString()); - - outbv = S_bytevector(outbytes); - - if (WideCharToMultiByte(cp, 0, (wchar_t *)&BVIT(inbv,0), (int)inwords, &BVIT(outbv, 0), outbytes, NULL, NULL) == 0) - S_error1("string->multibyte", "conversion failed: ~a", S_LastErrorString()); - - return outbv; -} -#endif /* WIN32 */ diff --git a/ta6ob/c/prim5.o b/ta6ob/c/prim5.o deleted file mode 100644 index 986db6b..0000000 Binary files a/ta6ob/c/prim5.o and /dev/null differ diff --git a/ta6ob/c/print.c b/ta6ob/c/print.c deleted file mode 100644 index 2b7cac4..0000000 --- a/ta6ob/c/print.c +++ /dev/null @@ -1,288 +0,0 @@ -/* print.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" - -/* locally defined functions */ -static void pimmediate(ptr x); -static void pbox(ptr x); -static void pclo(ptr x); -static void pcode(ptr x); -static void pcons(ptr x); -static void pfile(ptr x); -static void pinexactnum(ptr x); -static IBOOL exact_real_negativep(ptr x); -static void pexactnum(ptr x); -static void prat(ptr x); -static void pchar(ptr x); -static void pstr(ptr x); -static void psym(ptr x); -static void pvec(ptr x); -static void pfxvector(ptr x); -static void pbytevector(ptr x); -static void pflonum(ptr x); -static void pfixnum(ptr x); -static void pbignum(ptr x); -static void wrint(ptr x); - -void S_print_init(void) {} - -void S_prin1(ptr x) { - if (Simmediatep(x)) pimmediate(x); - else if (Spairp(x)) pcons(x); - else if (Ssymbolp(x)) psym(x); - else if (Sfixnump(x)) pfixnum(x); - else if (Sbignump(x)) pbignum(x); - else if (Sstringp(x)) pstr(x); - else if (Sratnump(x)) prat(x); - else if (Sflonump(x)) (void) pflonum(x); - else if (Sinexactnump(x)) pinexactnum(x); - else if (Sexactnump(x)) pexactnum(x); - else if (Svectorp(x)) pvec(x); - else if (Sfxvectorp(x)) pfxvector(x); - else if (Sbytevectorp(x)) pbytevector(x); - else if (Sboxp(x)) pbox(x); - else if (Sprocedurep(x)) pclo(x); - else if (Scodep(x)) pcode(x); - else if (Sportp(x)) pfile(x); - else if (Srecordp(x)) printf("#"); - else printf("#"); - fflush(stdout); -} - - -static void pimmediate(ptr x) { - if (Scharp(x)) pchar(x); - else if (x == Snil) printf("()"); - else if (x == Strue) printf("#t"); - else if (x == Sfalse) printf("#f"); - else if (x == Seof_object) printf("#!eof"); - else if (x == Sbwp_object) printf("#!bwp"); - else if (x == sunbound) printf("#"); - else if (x == Svoid) printf("#"); - else printf("#"); -} - -static void pbox(ptr x) { - printf("#&"); - S_prin1(Sunbox(x)); -} - -static void pclo(UNUSED ptr x) { - if (CODETYPE(CLOSCODE(x)) & (code_flag_continuation << code_flags_offset)) - printf("#"); - else - printf("#"); -} - -static void pcode(UNUSED ptr x) { - printf("#"); -} - -static void pcons(ptr x) { - putchar('('); - while (1) { - S_prin1(Scar(x)); - x = Scdr(x); - if (!Spairp(x)) break; - putchar(' '); - } - if (x!=Snil) { - printf(" . "); - S_prin1(x); - } - putchar(')'); -} - - -static void pfile(UNUSED ptr x) { - printf("#"); -} - -static void pinexactnum(ptr x) { - S_prin1(TYPE(&INEXACTNUM_REAL_PART(x),type_flonum)); - if (INEXACTNUM_IMAG_PART(x) >= 0.0) putchar('+'); - S_prin1(TYPE(&INEXACTNUM_IMAG_PART(x),type_flonum)); - putchar('i'); -} - -static IBOOL exact_real_negativep(ptr x) { - if (Sratnump(x)) x = RATNUM(x); - return Sfixnump(x) ? UNFIX(x) < 0 : BIGSIGN(x); -} - -static void pexactnum(ptr x) { - S_prin1(EXACTNUM_REAL_PART(x)); - if (!exact_real_negativep(EXACTNUM_IMAG_PART(x))) putchar('+'); - S_prin1(EXACTNUM_IMAG_PART(x)); - putchar('i'); -} - -static void prat(ptr x) { - wrint(RATNUM(x)); - putchar('/'); - wrint(RATDEN(x)); -} - -static void pchar(ptr x) { - int k = Schar_value(x); - if (k >= 256) k = '?'; - printf("#\\"); - putchar(k); -} - -static void pstr(ptr x) { - iptr i, n = Sstring_length(x); - - putchar('"'); - for (i = 0; i < n; i += 1) { - int k = Sstring_ref(x, i); - if (k >= 256) k = '?'; - if ((k == '\\') || (k == '"')) putchar('\\'); - putchar(k); - } - putchar('"'); -} - -static void display_string(ptr x) { - iptr i, n = Sstring_length(x); - - for (i = 0; i < n; i += 1) { - int k = Sstring_ref(x, i); - if (k >= 256) k = '?'; - putchar(k); - } -} - -static void psym(ptr x) { - ptr name = SYMNAME(x); - if (Sstringp(name)) { - display_string(name); - } else if (Spairp(name)) { - if (Scar(name) != Sfalse) { - printf("#{"); - display_string(Scdr(name)); - printf(" "); - display_string(Scar(name)); - printf("}"); - } else { - printf("#"); - } - } else { - printf("#"); - } -} - -static void pvec(ptr x) { - iptr n; - - putchar('#'); - n = Svector_length(x); - wrint(FIX(n)); - putchar('('); - if (n != 0) { - iptr i = 0; - - while (1) { - S_prin1(Svector_ref(x, i)); - if (++i == n) break; - putchar(' '); - } - } - putchar(')'); -} - -static void pfxvector(ptr x) { - iptr n; - - putchar('#'); - n = Sfxvector_length(x); - wrint(FIX(n)); - printf("vfx("); - if (n != 0) { - iptr i = 0; - - while (1) { - pfixnum(Sfxvector_ref(x, i)); - if (++i == n) break; - putchar(' '); - } - } - putchar(')'); -} - -static void pbytevector(ptr x) { - iptr n; - - putchar('#'); - n = Sbytevector_length(x); - wrint(FIX(n)); - printf("vu8("); - if (n != 0) { - iptr i = 0; - - while (1) { - pfixnum(FIX(Sbytevector_u8_ref(x, i))); - if (++i == n) break; - putchar(' '); - } - } - putchar(')'); -} - -static void pflonum(ptr x) { - char buf[256], *s; - - /* use snprintf to get it in a string */ - (void) snprintf(buf, 256, "%.16g",FLODAT(x)); - - /* print the silly thing */ - printf("%s", buf); - - /* add .0 if it looks like an integer */ - s = buf; - while (*s != 'E' && *s != 'e' && *s != '.') - if (*s++ == 0) { - printf(".0"); - break; - } -} - -static void pfixnum(ptr x) { - if (UNFIX(x) < 0) { - putchar('-'); - x = S_sub(FIX(0), x); - } - wrint(x); -} - -static void pbignum(ptr x) { - if (BIGSIGN(x)) { - putchar('-'); - x = S_sub(FIX(0), x); - } - wrint(x); -} - -static void wrint(ptr x) { - ptr q, r; - - S_trunc_rem(get_thread_context(), x, FIX(10), &q, &r); - if (q != 0) wrint(q); - putchar((INT)UNFIX(r) + '0'); -} diff --git a/ta6ob/c/print.o b/ta6ob/c/print.o deleted file mode 100644 index bce2820..0000000 Binary files a/ta6ob/c/print.o and /dev/null differ diff --git a/ta6ob/c/scheme.c b/ta6ob/c/scheme.c deleted file mode 100644 index 04f4c03..0000000 --- a/ta6ob/c/scheme.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* scheme.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" -#include "config.h" -#include -#include -#ifdef WIN32 -#include -#else -#include -#endif -#include -#include - -#ifndef O_BINARY -#define O_BINARY 0 -#endif /* O_BINARY */ - -static INT boot_count; -static IBOOL verbose; - -typedef enum { UNINITIALIZED, BOOTING, RUNNING, DEINITIALIZED } heap_state; -static heap_state current_state = UNINITIALIZED; - -/***************************************************************************/ -/* INITIALIZATION SUPPORT */ - -/* locally defined functions */ -static void main_init(void); -static void idiot_checks(void); -static INT run_script(const char *who, const char *scriptfile, INT argc, const char *argv[], IBOOL programp); - -extern void scheme_include(void); - -static void main_init(void) { - ptr tc = get_thread_context(); - ptr p; - INT i; - - /* create dependency for linker */ - scheme_statics(); - - /* force thread inline allocation to go through find_room until ready */ - AP(tc) = (ptr)0; - EAP(tc) = (ptr)0; - REAL_EAP(tc) = (ptr)0; - /* set up dummy CP so locking in read/write/Scall won't choke */ - CP(tc) = Svoid; - CODERANGESTOFLUSH(tc) = Snil; - - if (S_boot_time) S_G.protect_next = 0; - - S_segment_init(); - S_alloc_init(); - S_thread_init(); - S_intern_init(); - S_gc_init(); - S_number_init(); - S_schsig_init(); - S_new_io_init(); - S_print_init(); - S_stats_init(); - S_foreign_init(); - S_prim_init(); - S_prim5_init(); - S_fasl_init(); - S_machine_init(); - S_flushcache_init(); /* must come after S_machine_init(); */ -#ifdef FEATURE_EXPEDITOR - S_expeditor_init(); -#endif /* FEATURE_EXPEDITOR */ - - if (!S_boot_time) return; - - S_protect(&S_G.profile_counters); - S_G.profile_counters = Snil; - - FXLENGTHBV(tc) = p = S_bytevector(256); - for (i = 0; i < 256; i += 1) { - BVIT(p, i) = - (iptr)FIX(i & 0x80 ? 8 : i & 0x40 ? 7 : i & 0x20 ? 6 : i & 0x10 ? 5 : - i & 0x08 ? 4 : i & 0x04 ? 3 : i & 0x02 ? 2 : i & 0x01 ? 1 : 0); - } - - FXFIRSTBITSETBV(tc) = p = S_bytevector(256); - for (i = 0; i < 256; i += 1) { - BVIT(p, i) = - (iptr)FIX(i & 0x01 ? 0 : i & 0x02 ? 1 : i & 0x04 ? 2 : i & 0x08 ? 3 : - i & 0x10 ? 4 : i & 0x20 ? 5 : i & 0x40 ? 6 : i & 0x80 ? 7 : 0); - } - - NULLIMMUTABLEVECTOR(tc) = S_null_immutable_vector(); - NULLIMMUTABLEFXVECTOR(tc) = S_null_immutable_fxvector(); - NULLIMMUTABLEBYTEVECTOR(tc) = S_null_immutable_bytevector(); - NULLIMMUTABLESTRING(tc) = S_null_immutable_string(); - - PARAMETERS(tc) = S_G.null_vector; - for (i = 0 ; i < virtual_register_count ; i += 1) { - VIRTREG(tc, i) = FIX(0); - } - - p = S_code(tc, type_code, size_rp_header); - CODERELOC(p) = S_relocation_table(0); - CODENAME(p) = Sfalse; - CODEARITYMASK(p) = FIX(0); - CODEFREE(p) = 0; - CODEINFO(p) = Sfalse; - CODEPINFOS(p) = Snil; - RPHEADERFRAMESIZE(&CODEIT(p, 0)) = 0; - RPHEADERLIVEMASK(&CODEIT(p, 0)) = 0; - RPHEADERTOPLINK(&CODEIT(p, 0)) = - (uptr)&RPHEADERTOPLINK(&CODEIT(p, 0)) - (uptr)p; - S_protect(&S_G.dummy_code_object); - S_G.dummy_code_object = p; - - S_protect(&S_G.error_invoke_code_object); - S_G.error_invoke_code_object = Snil; - S_protect(&S_G.invoke_code_object); - S_G.invoke_code_object = Snil; - - S_protect(&S_G.active_threads_id); - S_G.active_threads_id = S_intern((const unsigned char *)"$active-threads"); - S_set_symbol_value(S_G.active_threads_id, FIX(0)); - - S_protect(&S_G.heap_reserve_ratio_id); - S_G.heap_reserve_ratio_id = S_intern((const unsigned char *)"$heap-reserve-ratio"); - SETSYMVAL(S_G.heap_reserve_ratio_id, Sflonum(default_heap_reserve_ratio)); - - S_protect(&S_G.scheme_version_id); - S_G.scheme_version_id = S_intern((const unsigned char *)"$scheme-version"); - S_protect(&S_G.make_load_binary_id); - S_G.make_load_binary_id = S_intern((const unsigned char *)"$make-load-binary"); - S_protect(&S_G.load_binary); - S_G.load_binary = Sfalse; -} - -static ptr fixtest = FIX(-1); - -static void idiot_checks(void) { - IBOOL oops = 0; - - if (bytes_per_segment < S_pagesize) { - fprintf(stderr, "bytes_per_segment (%x) < S_pagesize (%lx)\n", - bytes_per_segment, (long)S_pagesize); - oops = 1; - } - if (sizeof(iptr) != sizeof(ptr)) { - fprintf(stderr, "sizeof(iptr) [%ld] != sizeof(ptr) [%ld]\n", - (long)sizeof(iptr), (long)sizeof(ptr)); - oops = 1; - } - if (sizeof(uptr) != sizeof(ptr)) { - fprintf(stderr, "sizeof(uptr) [%ld] != sizeof(ptr) [%ld]\n", - (long)sizeof(uptr), (long)sizeof(ptr)); - oops = 1; - } - if (sizeof(ptr) * 8 != ptr_bits) { - fprintf(stderr, "sizeof(ptr) * 8 [%ld] != ptr_bits [%d]\n", - (long)sizeof(ptr), ptr_bits); - oops = 1; - } - if (sizeof(int) * 8 != int_bits) { - fprintf(stderr, "sizeof(int) * 8 [%ld] != int_bits [%d]\n", - (long)sizeof(int), int_bits); - oops = 1; - } - if (sizeof(short) * 8 != short_bits) { - fprintf(stderr, "sizeof(short) * 8 [%ld] != short_bits [%d]\n", - (long)sizeof(short), short_bits); - oops = 1; - } - if (sizeof(long) * 8 != long_bits) { - fprintf(stderr, "sizeof(long) * 8 [%ld] != long_bits [%d]\n", - (long)sizeof(long), long_bits); - oops = 1; - } -#ifndef WIN32 - if (sizeof(long long) * 8 != long_long_bits) { - fprintf(stderr, "sizeof(long long) * 8 [%ld] != long_long_bits [%d]\n", - (long)sizeof(long long), long_long_bits); - oops = 1; - } -#endif - if (sizeof(wchar_t) * 8 != wchar_bits) { - fprintf(stderr, "sizeof(wchar_t) * 8 [%ld] != wchar_bits [%d]\n", - (long)sizeof(wchar_t), wchar_bits); - oops = 1; - } - if (sizeof(size_t) * 8 != size_t_bits) { - fprintf(stderr, "sizeof(size_t) * 8 [%ld] != size_t_bits [%d]\n", - (long)sizeof(size_t), size_t_bits); - oops = 1; - } -#ifndef WIN32 - if (sizeof(ssize_t) * 8 != size_t_bits) { - fprintf(stderr, "sizeof(ssize_t) * 8 [%ld] != size_t_bits [%d]\n", - (long)sizeof(ssize_t), size_t_bits); - oops = 1; - } -#endif - if (sizeof(ptrdiff_t) * 8 != ptrdiff_t_bits) { - fprintf(stderr, "sizeof(ptrdiff_t) * 8 [%ld] != ptrdiff_t_bits [%d]\n", - (long)sizeof(ptrdiff_t), ptrdiff_t_bits); - oops = 1; - } - if (sizeof(time_t) * 8 != time_t_bits) { - fprintf(stderr, "sizeof(time_t) * 8 [%ld] != time_t_bits [%d]\n", - (long)sizeof(time_t), time_t_bits); - oops = 1; - } - if (sizeof(bigit) * 8 != bigit_bits) { - fprintf(stderr, "sizeof(bigit) * 8 [%ld] != bigit_bits [%d]\n", - (long)sizeof(bigit), bigit_bits); - oops = 1; - } - if (sizeof(bigitbigit) != 2 * sizeof(bigit)) { - fprintf(stderr, "sizeof(bigitbigit) [%ld] != sizeof(bigit) [%ld] * 2\n", - (long)sizeof(bigitbigit), (long)sizeof(bigit)); - oops = 1; - } - if (sizeof(char) != 1) { - fprintf(stderr, "sizeof(char) [%ld] != 1\n", (long)sizeof(char)); - oops = 1; - } - if (sizeof(I8) != 1) { - fprintf(stderr, "sizeof(I8) [%ld] != 1\n", (long)sizeof(I8)); - oops = 1; - } - if (sizeof(U8) != 1) { - fprintf(stderr, "sizeof(U8) [%ld] != 1\n", (long)sizeof(U8)); - oops = 1; - } - if (sizeof(I16) != 2) { - fprintf(stderr, "sizeof(I16) [%ld] != 2\n", (long)sizeof(I16)); - oops = 1; - } - if (sizeof(U16) != 2) { - fprintf(stderr, "sizeof(U16) [%ld] != 2\n", (long)sizeof(U16)); - oops = 1; - } - if (sizeof(I32) != 4) { - fprintf(stderr, "sizeof(I32) [%ld] != 4\n", (long)sizeof(I32)); - oops = 1; - } - if (sizeof(U32) != 4) { - fprintf(stderr, "sizeof(U32) [%ld] != 4\n", (long)sizeof(U32)); - oops = 1; - } - if (sizeof(I64) != 8) { - fprintf(stderr, "sizeof(I64) [%ld] != 8\n", (long)sizeof(I64)); - oops = 1; - } - if (sizeof(U64) != 8) { - fprintf(stderr, "sizeof(U64) [%ld] != 8\n", (long)sizeof(U64)); - oops = 1; - } - if (sizeof(string_char) != string_char_bytes) { - fprintf(stderr, "sizeof(string_char) [%ld] != string_char_bytes [%d]\n", (long)sizeof(string_char), string_char_bytes); - oops = 1; - } - if (UNFIX(fixtest) != -1) { - fprintf(stderr, "UNFIX operation failed\n"); - oops = 1; - } - if (strlen(VERSION)+1 > HEAP_VERSION_LENGTH) { - fprintf(stderr, "insufficient space for version in heap header\n"); - oops = 1; - } - if (strlen(MACHINE_TYPE)+1 > HEAP_MACHID_LENGTH) { - fprintf(stderr, "insufficient space for machine id in heap header\n"); - oops = 1; - } -#define big 0 -#define little 1 - if (native_endianness == big) { - uptr x[1]; - *x = 1; - if (*(char *)x != 0) { - fprintf(stderr, "endianness claimed to be big, appears to be little\n"); - oops = 1; - } - } else { - uptr x[1]; - *x = 1; - if (*(char *)x == 0) { - fprintf(stderr, "endianness claimed to be little, appears to be big\n"); - oops = 1; - } - } - - if (sizeof(bucket_pointer_list) != sizeof(bucket_list)) { - /* gc repurposes bucket_lists for bucket_pointer lists, so they'd better have the same size */ - fprintf(stderr, "bucket_pointer_list and bucket_list have different sizes\n"); - oops = 1; - } - - if ((cards_per_segment & (sizeof(iptr) - 1)) != 0) { - /* gc sometimes processes dirty bytes sizeof(iptr) bytes at a time */ - fprintf(stderr, "cards_per_segment is not a multiple of sizeof(iptr)\n"); - oops = 1; - } - if (((uptr)(&((seginfo *)0)->dirty_bytes[0]) & (sizeof(iptr) - 1)) != 0) { - /* gc sometimes processes dirty bytes sizeof(iptr) bytes at a time */ - fprintf(stderr, "dirty_bytes[0] is not iptr-aligned wrt to seginfo struct\n"); - oops = 1; - } - if (!Sfixnump(type_vector | ~mask_vector)) { - /* gc counts on vector type/length looking like a fixnum, so it can put vectors in space_impure */ - fprintf(stderr, "vector type/length field does not look like a fixnum\n"); - oops = 1; - } - - if (oops) S_abnormal_exit(); -} - -/***************************************************************************/ -/* SUPPORT FOR CALLING INTO SCHEME */ - -/* locally defined functions */ -static ptr boot_call(ptr tc, ptr p, INT n); -static void check_ap(ptr tc); - -/* arguments and ac0 set up */ -static ptr boot_call(ptr tc, ptr p, INT n) { - AC1(tc) = p; - CP(tc) = Svoid; /* don't have calling code object */ - - AC0(tc) = (ptr)(uptr)n; - S_call_help(tc, 0, 0); - check_ap(tc); - - CP(tc) = Svoid; /* leave clean so direct Scall won't choke */ - - switch ((iptr)AC1(tc)) { - case 1: - p = AC0(tc); - break; - case 0: - p = Svoid; - break; - default: - p = S_get_scheme_arg(tc, 1); - break; - } - return p; -} - -static void check_ap(ptr tc) { - if ((uptr)AP(tc) & (byte_alignment - 1)) { - (void) fprintf(stderr, "ap is not double word aligned\n"); - S_abnormal_exit(); - } - if ((ptr *)AP(tc) > (ptr *)EAP(tc)) { - (void) fprintf(stderr, "ap is greater than eap\n"); - S_abnormal_exit(); - } -} - -void S_generic_invoke(ptr tc, ptr code) { -#if defined(PPCAIX) - struct {caddr_t entry, toc, static_link;} hdr; - hdr.entry = (caddr_t)&CODEIT(code,0); - hdr.toc = (caddr_t)0; - hdr.static_link = (caddr_t)0; - (*((void (*)(ptr))(void *)&hdr))(tc); -#elif defined(PPCNT) - /* under NT, function headers contain no static link */ - struct {I32 entry, toc;} hdr; - typedef void (*ugly)(ptr); - ugly p; - hdr.entry = (I32)&CODEIT(code,0); - hdr.toc = (I32)0; - /* MSVC++ bombs with internal compiler error if we don't split this up */ - p = (ugly)&hdr; - p(tc); -#elif defined(PARISC) - struct {I32 entry, env;} hdr; - typedef void (*ugly)(ptr); - ugly p; - hdr.entry = (I32)&CODEIT(code,0); - hdr.env = (I32)0; - p = (ugly)((I32)&hdr + 2); - p(tc); -#elif defined(WIN32) && !defined(__MINGW32__) - __try { - (*((void (*)(ptr))(void *)&CODEIT(code,0)))(tc); - } - __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? - EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) - { - if (S_pants_down) - S_error_abort("nonrecoverable invalid memory reference"); - else - S_error_reset("invalid memory reference"); - } -#else - (*((void (*)(ptr))(void *)&CODEIT(code,0)))(tc); -#endif -} - -/***************************************************************************/ -/* MISCELLANEOUS HELPERS */ - -/* locally defined functions */ -static IBOOL next_path(char *path, const char *name, const char *ext, const char **sp, const char **dsp); -static const char *path_last(const char *path); -static char *get_defaultheapdirs(void); - -static const char *path_last(p) const char *p; { - const char *s; -#ifdef WIN32 - char c; - - if ((c = *p) >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') - if (*(p + 1) == ':') - p += 2; -#endif - - for (s = p; *s != 0; s += 1) - if (DIRMARKERP(*s)) p = ++s; - return p; -} - -#ifdef WIN32 -#ifndef DEFAULT_HEAP_PATH -/* by default, look in executable directory or in parallel boot directory */ -#define DEFAULT_HEAP_PATH "%x;%x\\..\\..\\boot\\%m" -#endif -#define SEARCHPATHSEP ';' -#define PATHSEP '\\' - -static char *get_defaultheapdirs() { - char *result; - wchar_t buf[PATH_MAX]; - DWORD len = sizeof(buf); - if (ERROR_SUCCESS != RegGetValueW(HKEY_LOCAL_MACHINE, L"Software\\Chez Scheme\\csv" VERSION, L"HeapSearchPath", RRF_RT_REG_SZ, NULL, buf, &len)) - return DEFAULT_HEAP_PATH; - else if ((result = Swide_to_utf8(buf))) - return result; - else - return DEFAULT_HEAP_PATH; -} -#else /* not WIN32: */ -#define SEARCHPATHSEP ':' -#define PATHSEP '/' -#ifndef DEFAULT_HEAP_PATH -#define DEFAULT_HEAP_PATH "/usr/lib/csv%v/%m:/usr/local/lib/csv%v/%m" -#endif - -static char *get_defaultheapdirs() { - return DEFAULT_HEAP_PATH; -} -#endif /* WIN32 */ - -/* next_path isolates the next entry in the two-part search path sp/dsp, - * leaving the full path with name affixed in path and *sp / *dsp pointing - * past the current entry. it returns 1 on success and 0 if at the end of - * the search path. path should be a pointer to an unoccupied buffer - * PATH_MAX characters long. either or both of sp/dsp may be empty, - * but neither may be null, i.e., (char *)0. */ -static IBOOL next_path(char *path, const char *name, const char *ext, - const char **sp, const char **dsp) { - char *p; - const char *s, *t; - -#define setp(c) if (p >= path + PATH_MAX) { fprintf(stderr, "search path entry too long\n"); S_abnormal_exit(); } else *p++ = (c) - for (;;) { - s = *sp; - p = path; - /* copy first searchpath entry into path, substituting MACHINE_TYPE for %m, - * VERSION for %v, % for %%, and : (; windows) for %: (%; windows) */ - while (*s != 0 && *s != SEARCHPATHSEP) { - switch (*s) { - case '%': - s += 1; - switch (*s) { -#ifdef WIN32 - case 'x': { - wchar_t exepath[PATH_MAX]; DWORD n; - s += 1; - n = GetModuleFileNameW(NULL, exepath, PATH_MAX); - if (n == 0 || (n == PATH_MAX && GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { - fprintf(stderr, "warning: executable path is too long; ignoring %%x\n"); - } else { - char *tstart; - const char *tend; - tstart = Swide_to_utf8(exepath); - t = tstart; - tend = path_last(t); - if (tend != t) tend -= 1; /* back up to directory separator */ - while (t != tend) setp(*t++); - free(tstart); - } - break; - } -#endif - case 'm': - s += 1; - t = MACHINE_TYPE; - while (*t != 0) setp(*t++); - break; - case 'v': - s += 1; - t = VERSION; - while (*t != 0) setp(*t++); - break; - case '%': - case SEARCHPATHSEP: - setp(*s++); - break; - default: - fprintf(stderr, "warning: ignoring extra %% in search path\n"); - break; - } - break; - default: - setp(*s++); - break; - } - } - - /* unless entry was null, append name and ext onto path and return true with - * updated path, sp, and possibly dsp */ - if (s != *sp) { - if ((p > path) && !DIRMARKERP(*(p - 1))) { setp(PATHSEP); } - t = name; - while (*t != 0) setp(*t++); - t = ext; - while (*t != 0) setp(*t++); - setp(0); - *sp = s; - return 1; - } - - /* if current segment is empty, move to next segment. if next segment - * is empty, return false */ - if (*s == 0) { - if (*(*sp = *dsp) == 0) return 0; - *dsp = ""; - } else { - *sp = s + 1; - } - } -#undef setp -} - -/***************************************************************************/ -/* BOOT FILES */ - -typedef struct { - INT fd; - char path[PATH_MAX]; -} boot_desc; - -#define MAX_BOOT_FILES 10 -static boot_desc bd[MAX_BOOT_FILES]; - -/* locally defined functions */ -static char get_u8(INT fd); -static uptr get_uptr(INT fd, uptr *pn); -static INT get_string(INT fd, char *s, iptr max, INT *c); -static IBOOL find_boot(const char *name, const char *ext, int fd, IBOOL errorp); -static void load(ptr tc, iptr n, IBOOL base); -static void check_boot_file_state(const char *who); - -static IBOOL find_boot(const char *name, const char *ext, int fd, IBOOL errorp) { - char pathbuf[PATH_MAX], buf[PATH_MAX]; - uptr n = 0; - INT c; - const char *path; - char *expandedpath; - - if ((fd != -1) || S_fixedpathp(name)) { - if (strlen(name) >= PATH_MAX) { - fprintf(stderr, "boot-file path is too long %s\n", name); - S_abnormal_exit(); - } - - path = name; - - if (fd == -1) { - expandedpath = S_malloc_pathname(path); - fd = OPEN(expandedpath, O_BINARY|O_RDONLY, 0); - free(expandedpath); - } - - if (fd == -1) { - if (errorp) { - fprintf(stderr, "cannot open boot file %s\n", path); - S_abnormal_exit(); - } else { - if (verbose) fprintf(stderr, "trying %s...cannot open\n", path); - return 0; - } - } - if (verbose) fprintf(stderr, "trying %s...opened\n", path); - - /* check for magic number */ - if (get_u8(fd) != fasl_type_header || - get_u8(fd) != 0 || - get_u8(fd) != 0 || - get_u8(fd) != 0 || - get_u8(fd) != 'c' || - get_u8(fd) != 'h' || - get_u8(fd) != 'e' || - get_u8(fd) != 'z') { - fprintf(stderr, "malformed fasl-object header in %s\n", path); - S_abnormal_exit(); - } - - /* check version */ - if (get_uptr(fd, &n) != 0) { - fprintf(stderr, "unexpected end of file on %s\n", path); - CLOSE(fd); - S_abnormal_exit(); - } - - if (n != scheme_version) { - fprintf(stderr, "%s is for Version %s; ", path, S_format_scheme_version(n)); - /* use separate fprintf since S_format_scheme_version returns static string */ - fprintf(stderr, "need Version %s\n", S_format_scheme_version(scheme_version)); - CLOSE(fd); - S_abnormal_exit(); - } - - /* check machine type */ - if (get_uptr(fd, &n) != 0) { - fprintf(stderr, "unexpected end of file on %s\n", path); - CLOSE(fd); - S_abnormal_exit(); - } - - if (n != machine_type) { - fprintf(stderr, "%s is for machine-type %s; need machine-type %s\n", path, - S_lookup_machine_type(n), S_lookup_machine_type(machine_type)); - CLOSE(fd); - S_abnormal_exit(); - } - } else { - const char *sp = Sschemeheapdirs; - const char *dsp = Sdefaultheapdirs; - - path = pathbuf; - for (;;) { - if (!next_path(pathbuf, name, ext, &sp, &dsp)) { - if (errorp) { - fprintf(stderr, "cannot find compatible boot file %s%s in search path:\n \"%s%s\"\n", - name, ext, - Sschemeheapdirs, Sdefaultheapdirs); - S_abnormal_exit(); - } else { - if (verbose) fprintf(stderr, "no compatible %s%s found\n", name, ext); - return 0; - } - } - - expandedpath = S_malloc_pathname(path); - fd = OPEN(expandedpath, O_BINARY|O_RDONLY, 0); - free(expandedpath); - if (fd == -1) { - if (verbose) fprintf(stderr, "trying %s...cannot open\n", path); - continue; - } - - if (verbose) fprintf(stderr, "trying %s...opened\n", path); - - /* check for magic number */ - if (get_u8(fd) != fasl_type_header || - get_u8(fd) != 0 || - get_u8(fd) != 0 || - get_u8(fd) != 0 || - get_u8(fd) != 'c' || - get_u8(fd) != 'h' || - get_u8(fd) != 'e' || - get_u8(fd) != 'z') { - if (verbose) fprintf(stderr, "malformed fasl-object header in %s\n", path); - CLOSE(fd); - continue; - } - - /* check version */ - if (get_uptr(fd, &n) != 0) { - if (verbose) fprintf(stderr, "unexpected end of file on %s\n", path); - CLOSE(fd); - continue; - } - - if (n != scheme_version) { - if (verbose) { - fprintf(stderr, "%s is for Version %s; ", path, S_format_scheme_version(n)); - /* use separate fprintf since S_format_scheme_version returns static string */ - fprintf(stderr, "need Version %s\n", S_format_scheme_version(scheme_version)); - } - CLOSE(fd); - continue; - } - - /* check machine type */ - if (get_uptr(fd, &n) != 0) { - if (verbose) fprintf(stderr, "unexpected end of file on %s\n", path); - CLOSE(fd); - continue; - } - - if (n != machine_type) { - if (verbose) - fprintf(stderr, "%s is for machine-type %s; need machine-type %s\n", path, - S_lookup_machine_type(n), S_lookup_machine_type(machine_type)); - CLOSE(fd); - continue; - } - - break; - } - } - - if (verbose) fprintf(stderr, "version and machine type check\n"); - - if (get_u8(fd) != '(') { /* ) */ - fprintf(stderr, "malformed boot file %s\n", path); - CLOSE(fd); - S_abnormal_exit(); - } - - /* ( */ - if ((c = get_u8(fd)) == ')') { - if (boot_count != 0) { - fprintf(stderr, "base boot file %s must come before other boot files\n", path); - CLOSE(fd); - S_abnormal_exit(); - } - } else { - if (boot_count == 0) { - for (;;) { - /* try to load heap or boot file this boot file requires */ - if (get_string(fd, buf, PATH_MAX, &c) != 0) { - fprintf(stderr, "unexpected end of file on %s\n", path); - CLOSE(fd); - S_abnormal_exit(); - } - if (find_boot(buf, ".boot", -1, 0)) break; - if (c == ')') { - char *sep; char *wastebuf[8]; - fprintf(stderr, "cannot find subordinate boot file"); - if (LSEEK(fd, 0, SEEK_SET) != 0 || READ(fd, wastebuf, 8) != 8) { /* attempt to rewind and read magic number */ - fprintf(stderr, "---retry with verbose flag for more information\n"); - CLOSE(fd); - S_abnormal_exit(); - } - (void) get_uptr(fd, &n); /* version */ - (void) get_uptr(fd, &n); /* machine type */ - (void) get_u8(fd); /* open paren */ - c = get_u8(fd); - for (sep = " "; ; sep = "or ") { - if (c == ')') break; - (void) get_string(fd, buf, PATH_MAX, &c); - fprintf(stderr, "%s%s.boot ", sep, buf); - } - fprintf(stderr, "required by %s\n", path); - CLOSE(fd); - S_abnormal_exit(); - } - } - } - - /* skip to end of header */ - while (c != ')') { - if (c < 0) { - fprintf(stderr, "malformed boot file %s\n", path); - CLOSE(fd); - S_abnormal_exit(); - } - c = get_u8(fd); - } - } - - if (boot_count >= MAX_BOOT_FILES) { - fprintf(stderr, "exceeded maximum number of boot files (%d)\n", MAX_BOOT_FILES); - S_abnormal_exit(); - } - - bd[boot_count].fd = fd; - strcpy(bd[boot_count].path, path); - boot_count += 1; - - return 1; -} - -static char get_u8(INT fd) { - char buf[1]; - if (READ(fd, &buf, 1) != 1) return -1; - return buf[0]; -} - -static uptr get_uptr(INT fd, uptr *pn) { - uptr n, m; int c; octet k; - - if ((c = get_u8(fd)) < 0) return -1; - k = (octet)c; - n = k >> 1; - while (k & 1) { - if ((c = get_u8(fd)) < 0) return -1; - k = (octet)c; - m = n << 7; - if (m >> 7 != n) return -1; - n = m | (k >> 1); - } - *pn = n; - return 0; -} - -static INT get_string(INT fd, char *s, iptr max, INT *c) { - while (max-- > 0) { - if (*c < 0) return -1; - if (*c == ' ' || *c == ')') { - if (*c == ' ') *c = get_u8(fd); - *s = 0; - return 0; - } - *s++ = *c; - *c = get_u8(fd); - } - return -1; -} - -static IBOOL loadecho = 0; -#define LOADSKIP 0 - -static int set_load_binary(iptr n) { - if (!Ssymbolp(SYMVAL(S_G.scheme_version_id))) return 0; // set by back.ss - ptr make_load_binary = SYMVAL(S_G.make_load_binary_id); - if (Sprocedurep(make_load_binary)) { - S_G.load_binary = Scall1(make_load_binary, Sstring_utf8(bd[n].path, -1)); - return 1; - } - return 0; -} - -static void load(ptr tc, iptr n, IBOOL base) { - ptr x; iptr i; - - if (base) { - S_G.error_invoke_code_object = S_boot_read(bd[n].fd, bd[n].path); - if (!Scodep(S_G.error_invoke_code_object)) { - (void) fprintf(stderr, "first object on boot file not code object\n"); - S_abnormal_exit(); - } - - S_G.invoke_code_object = S_boot_read(bd[n].fd, bd[n].path); - if (!Scodep(S_G.invoke_code_object)) { - (void) fprintf(stderr, "second object on boot file not code object\n"); - S_abnormal_exit(); - } - S_G.base_rtd = S_boot_read(bd[n].fd, bd[n].path); - if (!Srecordp(S_G.base_rtd)) { - S_abnormal_exit(); - } - } - - i = 0; - while (i++ < LOADSKIP && S_boot_read(bd[n].fd, bd[n].path) != Seof_object); - - while ((x = S_boot_read(bd[n].fd, bd[n].path)) != Seof_object) { - if (loadecho) { - printf("%ld: ", (long)i); - fflush(stdout); - } - if (Sprocedurep(x)) { - S_initframe(tc, 0); - x = boot_call(tc, x, 0); - } else if (Sprocedurep(S_G.load_binary) || set_load_binary(n)) { - S_initframe(tc, 1); - S_put_arg(tc, 1, x); - x = boot_call(tc, S_G.load_binary, 1); - } - if (loadecho) { - S_prin1(x); - putchar('\n'); - fflush(stdout); - } - i += 1; - } - - S_G.load_binary = Sfalse; - CLOSE(bd[n].fd); -} - -/***************************************************************************/ -/* HEAP FILES */ - -#ifdef DEBUG -#define debug(x) {x} -#else -#define debug(x) -#endif - -#include -#include - -#ifdef WIN32 -#include -#endif /* WIN32 */ - -#ifdef MMAP_HEAP -#include -#endif - -#ifndef O_BINARY -#define O_BINARY 0 -#endif /* O_BINARY */ - -#define check(expr,path) {if ((INT)(expr) < 0) {perror(path); S_abnormal_exit();}} - -/***************************************************************************/ -/* EXPORTED ROUTINES */ - -const char *Skernel_version(void) { - return VERSION; -} - -extern void Sset_verbose(INT v) { - verbose = v; -} - -extern void Sretain_static_relocation(void) { - S_G.retain_static_relocation = 1; -} - -#if defined(CHECK_FOR_ROSETTA) -#include -int is_rosetta = 0; -static void init_rosetta_check(void) { - int val = 0; - size_t size = sizeof(val); - if (sysctlbyname("sysctl.proc_translated", &val, &size, NULL, 0) != 0) { - if (errno == ENOENT) { - is_rosetta = 0; - } else { - perror("checking to see if running under Rosetta"); - // if for some reason we can't tell whether we are running under Rosetta or not, - // default to the safer choice. It doesn't impact correctness to do the Rosetta - // workarounds when they are not needed. - is_rosetta = 1; - } - } - is_rosetta = val; -} -#endif - -#ifdef ITEST -#include "itest.c" -#endif - -static void default_abnormal_exit(void) { - exit(1); -} - -extern void Sscheme_init(void (*abnormal_exit)(void)) { - S_abnormal_exit_proc = abnormal_exit ? abnormal_exit : default_abnormal_exit; - S_errors_to_console = 1; - - /* set before idiot checks */ - S_pagesize = GETPAGESIZE(); - - idiot_checks(); -#if defined(CHECK_FOR_ROSETTA) - init_rosetta_check(); -#endif - - switch (current_state) { - case RUNNING: - fprintf(stderr, "error (Sscheme_init): call Sscheme_deinit first to terminate\n"); - S_abnormal_exit(); - case BOOTING: - fprintf(stderr, "error (Sscheme_init): already initialized\n"); - S_abnormal_exit(); - case UNINITIALIZED: - case DEINITIALIZED: - break; - } - current_state = BOOTING; - - S_G.retain_static_relocation = 0; - S_G.enable_object_counts = 0; - - boot_count = 0; - -#ifdef WIN32 - Sschemeheapdirs = Sgetenv("SCHEMEHEAPDIRS"); -#else - Sschemeheapdirs = getenv("SCHEMEHEAPDIRS"); -#endif - if (Sschemeheapdirs == (char *)0) { - Sschemeheapdirs = ""; - if ((Sdefaultheapdirs = get_defaultheapdirs()) == (char *)0) Sdefaultheapdirs = ""; - } else if (*Sschemeheapdirs != 0 && Sschemeheapdirs[strlen(Sschemeheapdirs)-1] == SEARCHPATHSEP) { - if ((Sdefaultheapdirs = get_defaultheapdirs()) == (char *)0) Sdefaultheapdirs = ""; - } else { - Sdefaultheapdirs = ""; - } - -#ifdef PTHREADS - { - int status; - if ((status = s_thread_key_create(&S_tc_key)) != 0) - S_error_abort(strerror(status)); - s_thread_setspecific(S_tc_key, S_G.thread_context); - } -#endif - -#ifdef ITEST - S_boot_time = 1; - main_init(); - - bignum_test(); - exit(0); -#endif -} - -static void check_boot_file_state(const char *who) { - switch (current_state) { - case UNINITIALIZED: - case DEINITIALIZED: - fprintf(stderr, "error (%s): uninitialized; call Sscheme_init first\n", who); - if (current_state == UNINITIALIZED) exit(1); else S_abnormal_exit(); - case RUNNING: - fprintf(stderr, "error (%s): already running\n", who); - S_abnormal_exit(); - case BOOTING: - break; - } -} - -extern void Sregister_boot_file(const char *name) { - check_boot_file_state("Sregister_boot_file"); - find_boot(name, "", -1, 1); -} - -extern void Sregister_boot_file_fd(const char *name, int fd) { - check_boot_file_state("Sregister_boot_file_fd"); - find_boot(name, "", fd, 1); -} - -extern void Sregister_heap_file(UNUSED const char *path) { - fprintf(stderr, "Sregister_heap_file: saved heap files are not presently supported\n"); - S_abnormal_exit(); -} - -extern void Sbuild_heap(const char *kernel, void (*custom_init)(void)) { - ptr tc = Svoid; /* initialize to make gcc happy */ - ptr p; - - switch (current_state) { - case UNINITIALIZED: - case DEINITIALIZED: - fprintf(stderr, "error (Sbuild_heap): uninitialized; call Sscheme_init first\n"); - if (current_state == UNINITIALIZED) exit(1); else S_abnormal_exit(); - case RUNNING: - fprintf(stderr, "error (Sbuild_heap): already running\n"); - S_abnormal_exit(); - case BOOTING: - break; - } - current_state = RUNNING; - - S_boot_time = 1; - - if (boot_count == 0) { - const char *name; - - if (!kernel) { - fprintf(stderr, "no boot file or executable name specified\n"); - S_abnormal_exit(); - } - - name = path_last(kernel); - if (strlen(name) >= PATH_MAX) { - fprintf(stderr, "executable name too long: %s\n", name); - S_abnormal_exit(); - } - -#ifdef WIN32 - { /* strip off trailing .exe, if any */ - static char buf[PATH_MAX]; - iptr n; - - n = strlen(name) - 4; - if (n >= 0 && (_stricmp(name + n, ".exe") == 0)) { - strcpy(buf, name); - buf[n] = 0; - name = buf; - } - } -#endif - - if (!find_boot(name, ".boot", -1, 0)) { - fprintf(stderr, "cannot find compatible %s.boot in search path\n \"%s%s\"\n", - name, - Sschemeheapdirs, Sdefaultheapdirs); - S_abnormal_exit(); - } - } - - if (boot_count != 0) { - INT i = 0; - - main_init(); - if (custom_init) custom_init(); - - S_threads = Snil; - S_nthreads = 0; - S_set_symbol_value(S_G.active_threads_id, FIX(0)); - /* pass a parent tc of Svoid, since this call establishes the initial - * thread context and hence there is no parent thread context. */ - tc = (ptr)THREADTC(S_create_thread_object("startup", tc)); -#ifdef PTHREADS - s_thread_setspecific(S_tc_key, tc); -#endif - - /* #scheme-init enables interrupts */ - TRAP(tc) = (ptr)most_positive_fixnum; - DISABLECOUNT(tc) = Sfixnum(1); - COMPRESSFORMAT(tc) = FIX(COMPRESS_LZ4); - COMPRESSLEVEL(tc) = FIX(COMPRESS_MEDIUM); - - load(tc, i++, 1); - S_boot_time = 0; - - while (i < boot_count) load(tc, i++, 0); - } - - if (boot_count != 0) Scompact_heap(); - - /* complete the initialization on the Scheme side */ - p = S_symbol_value(S_intern((const unsigned char *)"$scheme-init")); - if (!Sprocedurep(p)) { - (void) fprintf(stderr,"\n$scheme-init is not bound to a procedure\n"); - S_abnormal_exit(); - } - - S_initframe(tc, 0); - (void)boot_call(tc, p, 0); - - /* should be okay to invoke Scheme's error handler now */ - S_errors_to_console = 0; -} - -extern void Senable_expeditor(const char *history_file) { - Scall1(S_symbol_value(Sstring_to_symbol("$enable-expeditor")), Strue); - if (history_file != (const char *)0) - Scall1(S_symbol_value(Sstring_to_symbol("$expeditor-history-file")), - Sstring_utf8(history_file, -1)); -} - -extern INT Sscheme_start(INT argc, const char *argv[]) { - ptr tc = get_thread_context(); - ptr arglist, p; INT i; - - switch (current_state) { - case UNINITIALIZED: - case DEINITIALIZED: - fprintf(stderr, "error (Sscheme_start): uninitialized; call Sscheme_init and Sbuild_heap first\n"); - if (current_state == UNINITIALIZED) exit(1); else S_abnormal_exit(); - case BOOTING: - fprintf(stderr, "error (Sscheme_start): no heap built yet; call Sbuild_heap first\n"); - S_abnormal_exit(); - case RUNNING: - break; - } - - arglist = Snil; - for (i = argc - 1; i > 0; i -= 1) - arglist = Scons(Sstring_utf8(argv[i], -1), arglist); - - p = S_symbol_value(S_intern((const unsigned char *)"$scheme")); - if (!Sprocedurep(p)) { - (void) fprintf(stderr,"\n$scheme is not bound to a procedure\n"); - S_abnormal_exit(); - } - - S_initframe(tc, 1); - S_put_arg(tc, 1, arglist); - p = boot_call(tc, p, 1); - - if (S_integer_valuep(p)) return (INT)Sinteger_value(p); - return p == Svoid ? 0 : 1; -} - -static INT run_script(const char *who, const char *scriptfile, INT argc, const char *argv[], IBOOL programp) { - ptr tc = get_thread_context(); - ptr arglist, p; INT i; - - switch (current_state) { - case UNINITIALIZED: - case DEINITIALIZED: - fprintf(stderr, "error (%s): uninitialized; call Sscheme_init and Sbuild_heap first\n", who); - if (current_state == UNINITIALIZED) exit(1); else S_abnormal_exit(); - case BOOTING: - fprintf(stderr, "error (%s): no heap built yet; call Sbuild_heap first\n", who); - S_abnormal_exit(); - case RUNNING: - break; - } - - arglist = Snil; - for (i = argc - 1; i > 0; i -= 1) - arglist = Scons(Sstring_utf8(argv[i], -1), arglist); - - p = S_symbol_value(S_intern((const unsigned char *)"$script")); - if (!Sprocedurep(p)) { - (void) fprintf(stderr,"\n$script is not bound to a procedure\n"); - S_abnormal_exit(); - } - - S_initframe(tc, 3); - S_put_arg(tc, 1, Sboolean(programp)); - S_put_arg(tc, 2, Sstring_utf8(scriptfile, -1)); - S_put_arg(tc, 3, arglist); - p = boot_call(tc, p, 3); - - if (S_integer_valuep(p)) return (INT)Sinteger_value(p); - return p == Svoid ? 0 : 1; -} - -extern INT Sscheme_script(const char *scriptfile, INT argc, const char *argv[]) { - return run_script("Sscheme_script", scriptfile, argc, argv, 0); -} - -extern INT Sscheme_program(const char *programfile, INT argc, const char *argv[]) { - return run_script("Sscheme_program", programfile, argc, argv, 1); -} - -extern void Ssave_heap(UNUSED const char *path, UNUSED INT level) { - fprintf(stderr, "Ssave_heap: saved heap files are not presently supported\n"); - S_abnormal_exit(); -} - -extern void Sscheme_deinit(void) { - ptr p, tc = get_thread_context(); - - switch (current_state) { - case UNINITIALIZED: - case DEINITIALIZED: - fprintf(stderr, "error (Sscheme_deinit): not yet initialized or running\n"); - if (current_state == UNINITIALIZED) exit(1); else S_abnormal_exit(); - case BOOTING: - fprintf(stderr, "error (Sscheme_deinit): not yet running\n"); - S_abnormal_exit(); - case RUNNING: - break; - } - - p = S_symbol_value(S_intern((const unsigned char *)"$close-files")); - S_initframe(tc, 0); - boot_call(tc, p, 0); - - S_errors_to_console = 1; - current_state = DEINITIALIZED; -} diff --git a/ta6ob/c/scheme.o b/ta6ob/c/scheme.o deleted file mode 100644 index 16dfc65..0000000 Binary files a/ta6ob/c/scheme.o and /dev/null differ diff --git a/ta6ob/c/schlib.c b/ta6ob/c/schlib.c deleted file mode 100644 index e958964..0000000 --- a/ta6ob/c/schlib.c +++ /dev/null @@ -1,307 +0,0 @@ -/* schlib.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" - -/* locally defined functions */ -static ptr S_call(ptr tc, ptr cp, iptr argcnt); - -/* Sinteger_value is in number.c */ - -/* Sinteger32_value is in number.c */ - -/* Sinteger64_value is in number.c */ - -void Sset_box(ptr x, ptr y) { - SETBOXREF(x, y); -} - -void Sset_car(ptr x, ptr y) { - SETCAR(x, y); -} - -void Sset_cdr(ptr x, ptr y) { - SETCDR(x, y); -} - -void Svector_set(ptr x, iptr i, ptr y) { - SETVECTIT(x, i, y); -} - -/* Scons is in alloc.c */ - -ptr Sstring_to_symbol(const char *s) { - return S_intern((const unsigned char *)s); -} - -ptr Ssymbol_to_string(ptr x) { - ptr name = SYMNAME(x); - if (Sstringp(name)) - return name; - else if (Spairp(name)) - return Scdr(name); - else - /* don't have access to prefix or count, and can't handle arbitrary - prefixes anyway, so always punt */ - return S_string("gensym", -1); -} - -/* Sflonum is in alloc.c */ - -ptr Smake_vector(iptr n, ptr x) { - ptr p; iptr i; - - p = S_vector(n); - for (i = 0; i < n; i += 1) INITVECTIT(p, i) = x; - return p; -} - -ptr Smake_fxvector(iptr n, ptr x) { - ptr p; iptr i; - - p = S_fxvector(n); - for (i = 0; i < n; i += 1) Sfxvector_set(p, i, x); - return p; -} - -ptr Smake_bytevector(iptr n, int x) { - ptr p; iptr i; - - p = S_bytevector(n); - for (i = 0; i < n; i += 1) Sbytevector_u8_set(p, i, (octet)x); - return p; -} - -ptr Smake_string(iptr n, int c) { - ptr p; iptr i; - - p = S_string((char *)NULL, n); - for (i = 0; i < n; i += 1) Sstring_set(p, i, c); - return p; -} - -ptr Smake_uninitialized_string(iptr n) { - return S_string((char *)NULL, n); -} - -ptr Sstring(const char *s) { - return S_string(s, -1); -} - -ptr Sstring_of_length(const char *s, iptr n) { - return S_string(s, n); -} - -/* Sstring_utf8 is in alloc.c */ - -/* Sbox is in alloc.c */ - -/* Sinteger is in number.c */ - -/* Sunsigned is in number.c */ - -/* Sunsigned32 is in number.c */ - -/* Sunsigned64 is in number.c */ - -ptr Stop_level_value(ptr x) { - ptr tc = get_thread_context(); - IBOOL enabled = (DISABLECOUNT(tc) == 0); - if (enabled) DISABLECOUNT(tc) = FIX(UNFIX(DISABLECOUNT(tc)) + 1); - x = Scall1(S_symbol_value(Sstring_to_symbol("$c-tlv")), x); - if (enabled) DISABLECOUNT(tc) = FIX(UNFIX(DISABLECOUNT(tc)) - 1); - return x; -} - -void Sset_top_level_value(ptr x, ptr y) { - ptr tc = get_thread_context(); - IBOOL enabled = (DISABLECOUNT(tc) == 0); - if (enabled) DISABLECOUNT(tc) = FIX(UNFIX(DISABLECOUNT(tc)) + 1); - Scall2(S_symbol_value(Sstring_to_symbol("$c-stlv!")), x, y); - if (enabled) DISABLECOUNT(tc) = FIX(UNFIX(DISABLECOUNT(tc)) - 1); -} - -#include - -/* consider rewriting these to avoid multiple calls to get_thread_context */ -ptr Scall0(ptr cp) { - ptr tc = get_thread_context(); - S_initframe(tc,0); - return S_call(tc, cp, 0); -} - -ptr Scall1(ptr cp, ptr x1) { - ptr tc = get_thread_context(); - S_initframe(tc, 1); - S_put_arg(tc, 1, x1); - return S_call(tc, cp, 1); -} - -ptr Scall2(ptr cp, ptr x1, ptr x2) { - ptr tc = get_thread_context(); - S_initframe(tc, 2); - S_put_arg(tc, 1, x1); - S_put_arg(tc, 2, x2); - return S_call(tc, cp, 2); -} - -ptr Scall3(ptr cp, ptr x1, ptr x2, ptr x3) { - ptr tc = get_thread_context(); - S_initframe(tc, 3); - S_put_arg(tc, 1, x1); - S_put_arg(tc, 2, x2); - S_put_arg(tc, 3, x3); - return S_call(tc, cp, 3); -} - -void Sinitframe(iptr n) { - ptr tc = get_thread_context(); - S_initframe(tc, n); -} - -void S_initframe(ptr tc, iptr n) { - /* check for and handle stack overflow */ - if ((ptr *)SFP(tc) + n + 2 > (ptr *)ESP(tc)) - S_overflow(tc, (n+2)*sizeof(ptr)); - - /* intermediate frame contains old RA + cchain */; - SFP(tc) = (ptr)((ptr *)SFP(tc) + 2); -} - -void Sput_arg(iptr i, ptr x) { - ptr tc = get_thread_context(); - S_put_arg(tc, i, x); -} - -void S_put_arg(ptr tc, iptr i, ptr x) { - if (i <= asm_arg_reg_cnt) - REGARG(tc, i) = x; - else - FRAME(tc, i - asm_arg_reg_cnt) = x; -} - -ptr Scall(ptr cp, iptr argcnt) { - ptr tc = get_thread_context(); - return S_call(tc, cp, argcnt); -} - -static ptr S_call(ptr tc, ptr cp, iptr argcnt) { - AC0(tc) = (ptr)argcnt; - AC1(tc) = cp; - S_call_help(tc, 1, 0); - return AC0(tc); -} - -/* args are set up, argcnt in ac0, closure in ac1 */ -void S_call_help(ptr tc_in, IBOOL singlep, IBOOL lock_ts) { - /* declaring code and tc volatile should be unnecessary, but it quiets gcc - and avoids occasional invalid memory violations on Windows */ - void *jb; volatile ptr code; - volatile ptr tc = tc_in; - - /* lock caller's code object, since his return address is sitting in - the C stack and we may end up in a garbage collection */ - code = CP(tc); - if (Sprocedurep(code)) code = CLOSCODE(code); - if (!IMMEDIATE(code) && !Scodep(code)) - S_error_abort("S_call_help: invalid code pointer"); - Slock_object(code); - - CP(tc) = AC1(tc); - - jb = CREATEJMPBUF(); - if (jb == NULL) - S_error_abort("unable to allocate memory for jump buffer"); - if (lock_ts) { - /* Lock a code object passed in TS, which is a more immediate - caller whose return address is on the C stack */ - Slock_object(TS(tc)); - CCHAIN(tc) = Scons(Scons(jb, Scons(code,TS(tc))), CCHAIN(tc)); - } else { - CCHAIN(tc) = Scons(Scons(jb, Scons(code,Sfalse)), CCHAIN(tc)); - } - - FRAME(tc, -1) = CCHAIN(tc); - - switch (SETJMP(jb)) { - case 0: /* first time */ - S_generic_invoke(tc, S_G.invoke_code_object); - S_error_abort("S_generic_invoke return"); - break; - case -1: /* error */ - S_generic_invoke(tc, S_G.error_invoke_code_object); - S_error_abort("S_generic_invoke return"); - break; - case 1: { /* normal return */ - ptr yp = CCHAIN(tc); - FREEJMPBUF(CAAR(yp)); - CCHAIN(tc) = Scdr(yp); - break; - } - default: - S_error_abort("unexpected SETJMP return value"); - break; - } - - /* verify single return value */ - if (singlep && (iptr)AC1(tc) != 1) - S_error1("", "returned ~s values to single value return context", - FIX((iptr)AC1(tc))); - - /* restore caller to cp so that we can lock it again another day. we - restore the code object rather than the original closure, as the - closure may have been relocated or reclaimed by now */ - CP(tc) = code; -} - -void S_call_one_result(void) { - ptr tc = get_thread_context(); - S_call_help(tc, 1, 1); -} - -void S_call_any_results(void) { - ptr tc = get_thread_context(); - S_call_help(tc, 0, 1); -} - -/* cchain = ((jb . (co . maybe-co)) ...) */ -void S_return(void) { - ptr tc = get_thread_context(); - ptr xp, yp; - - SFP(tc) = (ptr)((ptr *)SFP(tc) - 2); - - /* grab saved cchain */ - yp = FRAME(tc, 1); - - /* verify saved cchain is sublist of current cchain */ - for (xp = CCHAIN(tc); xp != yp; xp = Scdr(xp)) - if (xp == Snil) - S_error("", "attempt to return to stale foreign context"); - - /* error checks are done; now unlock affected code objects */ - for (xp = CCHAIN(tc); ; xp = Scdr(xp)) { - ptr p = CDAR(xp); - Sunlock_object(Scar(p)); - if (Scdr(p) != Sfalse) Sunlock_object(Scdr(p)); - if (xp == yp) break; - FREEJMPBUF(CAAR(xp)); - } - - /* reset cchain and return via longjmp */ - CCHAIN(tc) = yp; - LONGJMP(CAAR(yp), 1); -} diff --git a/ta6ob/c/schlib.o b/ta6ob/c/schlib.o deleted file mode 100644 index 893573c..0000000 Binary files a/ta6ob/c/schlib.o and /dev/null differ diff --git a/ta6ob/c/schsig.c b/ta6ob/c/schsig.c deleted file mode 100644 index 5776bb6..0000000 --- a/ta6ob/c/schsig.c +++ /dev/null @@ -1,783 +0,0 @@ -/* schsig.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" -#include - -/* locally defined functions */ -static void S_promote_to_multishot(ptr k); -static void split(ptr k, ptr *s); -static void reset_scheme(void); -static NORETURN void do_error(iptr type, const char *who, const char *s, ptr args); -static void handle_call_error(ptr tc, iptr type, ptr x); -static void init_signal_handlers(void); -static void keyboard_interrupt(ptr tc); - -ptr S_get_scheme_arg(ptr tc, iptr n) { - - if (n <= asm_arg_reg_cnt) return REGARG(tc, n); - else return FRAME(tc, n - asm_arg_reg_cnt); -} - -void S_put_scheme_arg(ptr tc, iptr n, ptr x) { - - if (n <= asm_arg_reg_cnt) REGARG(tc, n) = x; - else FRAME(tc, n - asm_arg_reg_cnt) = x; -} - -static void S_promote_to_multishot(ptr k) { - while (CONTLENGTH(k) != CONTCLENGTH(k)) { - CONTLENGTH(k) = CONTCLENGTH(k); - k = CONTLINK(k); - } -} - -/* k must be is a multi-shot continuation, and s (the split point) - * must be strictly between the base and end of k's stack segment. */ -static void split(ptr k, ptr *s) { - iptr m, n; - seginfo *si; - - tc_mutex_acquire() - /* set m to size of lower piece, n to size of upper piece */ - m = (uptr)s - (uptr)CONTSTACK(k); - n = CONTCLENGTH(k) - m; - - si = SegInfo(ptr_get_segment(k)); - /* insert a new continuation between k and link(k) */ - CONTLINK(k) = S_mkcontinuation(si->space, - si->generation, - CLOSENTRY(k), - CONTSTACK(k), - m, m, - CONTLINK(k), - *s, - Snil); - CONTLENGTH(k) = CONTCLENGTH(k) = n; - CONTSTACK(k) = (ptr)s; - *s = (ptr)DOUNDERFLOW; - tc_mutex_release() -} - -/* We may come in to S_split_and_resize with a multi-shot continuation whose - * stack segment exceeds the copy bound or is too large to fit along - * with the return values in the current stack. We may also come in to - * S_split_and_resize with a one-shot continuation for which all of the - * above is true and for which there is insufficient space between the - * top frame and the end of the stack. If we have to split a 1-shot, we - * promote it to multi-shot; doing otherwise is too much trouble. */ -void S_split_and_resize(void) { - ptr tc = get_thread_context(); - ptr k; iptr value_count; iptr n; - - /* cp = continuation, ac0 = return value count */ - k = CP(tc); - value_count = (iptr)AC0(tc); - - if (CONTCLENGTH(k) > underflow_limit) { - iptr frame_size; - ptr *front_stack_ptr, *end_stack_ptr, *split_point, *guard; - - front_stack_ptr = (ptr *)CONTSTACK(k); - end_stack_ptr = (ptr *)((uptr)front_stack_ptr + CONTCLENGTH(k)); - - guard = (ptr *)((uptr)end_stack_ptr - underflow_limit); - - /* set split point to base of top frame */ - frame_size = ENTRYFRAMESIZE(CONTRET(k)); - split_point = (ptr *)((uptr)end_stack_ptr - frame_size); - - /* split only if we have more than one frame */ - if (split_point != front_stack_ptr) { - /* walk the stack to set split_point at first frame above guard */ - /* note that first frame may have put us below the guard already */ - for (;;) { - ptr *p; - frame_size = ENTRYFRAMESIZE(*split_point); - p = (ptr *)((uptr)split_point - frame_size); - if (p < guard) break; - split_point = p; - } - - /* promote to multi-shot if necessary */ - S_promote_to_multishot(k); - - /* split */ - split(k, split_point); - } - } - - /* make sure the stack is big enough to hold continuation - * this is conservative: really need stack-base + clength <= esp - * and clength + size(values) < stack-size; also, size may include - * argument register values */ - n = CONTCLENGTH(k) + (value_count * sizeof(ptr)) + stack_slop; - if (n >= SCHEMESTACKSIZE(tc)) { - tc_mutex_acquire() - S_reset_scheme_stack(tc, n); - tc_mutex_release() - } -} - -iptr S_continuation_depth(ptr k) { - iptr n, frame_size; ptr *stack_base, *stack_ptr; - - n = 0; - /* terminate on shot 1-shot, which could be null_continuation */ - while (CONTLENGTH(k) != scaled_shot_1_shot_flag) { - stack_base = (ptr *)CONTSTACK(k); - frame_size = ENTRYFRAMESIZE(CONTRET(k)); - stack_ptr = (ptr *)((uptr)stack_base + CONTCLENGTH(k)); - for (;;) { - stack_ptr = (ptr *)((uptr)stack_ptr - frame_size); - n += 1; - if (stack_ptr == stack_base) break; - frame_size = ENTRYFRAMESIZE(*stack_ptr); - } - k = CONTLINK(k); - } - return n; -} - -ptr S_single_continuation(ptr k, iptr n) { - iptr frame_size; ptr *stack_base, *stack_top, *stack_ptr; - - /* bug out on shot 1-shots, which could be null_continuation */ - while (CONTLENGTH(k) != scaled_shot_1_shot_flag) { - stack_base = (ptr *)CONTSTACK(k); - stack_top = (ptr *)((uptr)stack_base + CONTCLENGTH(k)); - stack_ptr = stack_top; - frame_size = ENTRYFRAMESIZE(CONTRET(k)); - for (;;) { - if (n == 0) { - /* promote to multi-shot if necessary, even if we don't end - * up in split, since inspector assumes multi-shot */ - S_promote_to_multishot(k); - - if (stack_ptr != stack_top) { - split(k, stack_ptr); - k = CONTLINK(k); - } - - stack_ptr = (ptr *)((uptr)stack_ptr - frame_size); - if (stack_ptr != stack_base) - split(k, stack_ptr); - - return k; - } else { - n -= 1; - stack_ptr = (ptr *)((uptr)stack_ptr - frame_size); - if (stack_ptr == stack_base) break; - frame_size = ENTRYFRAMESIZE(*stack_ptr); - } - } - k = CONTLINK(k); - } - - return Sfalse; -} - -void S_handle_overflow(void) { - ptr tc = get_thread_context(); - - /* default frame size is enough */ - S_overflow(tc, 0); -} - -void S_handle_overflood(void) { - ptr tc = get_thread_context(); - - /* xp points to where esp needs to be */ - S_overflow(tc, ((ptr *)XP(tc) - (ptr *)SFP(tc))*sizeof(ptr)); -} - -void S_handle_apply_overflood(void) { - ptr tc = get_thread_context(); - - /* ac0 contains the argument count for the called procedure */ - /* could reduce request by default frame size and number of arg registers */ - /* the "+ 1" is for the return address slot */ - S_overflow(tc, ((iptr)AC0(tc) + 1) * sizeof(ptr)); -} - -/* allocates a new stack - * --the old stack below the sfp is turned into a continuation - * --the old stack above the sfp is copied to the new stack - * --return address must be in first frame location - * --scheme registers are preserved or reset - * frame_request is how much (in bytes) to increase the default frame size - */ -void S_overflow(ptr tc, iptr frame_request) { - ptr *sfp; - iptr above_split_size, sfp_offset; - ptr *split_point, *guard, *other_guard; - iptr split_stack_length, split_stack_clength; - ptr nuate; - - sfp = (ptr *)SFP(tc); - nuate = SYMVAL(S_G.nuate_id); - if (!Scodep(nuate)) { - S_error_abort("overflow: nuate not yet defined"); - } - - guard = (ptr *)((uptr)sfp - underflow_limit); - /* leave at least stack_slop headroom in the old stack to reduce the need for return-point overflow checks */ - other_guard = (ptr *)((uptr)SCHEMESTACK(tc) + (uptr)SCHEMESTACKSIZE(tc) - (uptr)stack_slop); - if ((uptr)other_guard < (uptr)guard) guard = other_guard; - - /* split only if old stack contains more than underflow_limit bytes */ - if (guard > (ptr *)SCHEMESTACK(tc)) { - iptr frame_size; - - /* set split point to base of the frame below the current one */ - frame_size = ENTRYFRAMESIZE(*sfp); - split_point = (ptr *)((uptr)sfp - frame_size); - - /* split only if we have more than one frame */ - if (split_point != (ptr *)SCHEMESTACK(tc)) { - /* walk the stack to set split_point at first frame above guard */ - /* note that first frame may have put us below the guard already */ - for (;;) { - ptr *p; - - frame_size = ENTRYFRAMESIZE(*split_point); - p = (ptr *)((uptr)split_point - frame_size); - if (p < guard) break; - split_point = p; - } - - split_stack_clength = (uptr)split_point - (uptr)SCHEMESTACK(tc); - - /* promote to multi-shot if current stack is shrimpy */ - if (SCHEMESTACKSIZE(tc) < default_stack_size / 4) { - split_stack_length = split_stack_clength; - S_promote_to_multishot(STACKLINK(tc)); - } else { - split_stack_length = SCHEMESTACKSIZE(tc); - } - - /* create a continuation */ - tc_mutex_acquire() - STACKLINK(tc) = S_mkcontinuation(space_new, - 0, - CODEENTRYPOINT(nuate), - SCHEMESTACK(tc), - split_stack_length, - split_stack_clength, - STACKLINK(tc), - *split_point, - Snil); - tc_mutex_release() - - /* overwrite old return address with dounderflow */ - *split_point = (ptr)DOUNDERFLOW; - } - } else { - split_point = (ptr *)SCHEMESTACK(tc); - } - - above_split_size = SCHEMESTACKSIZE(tc) - ((uptr)split_point - (uptr)SCHEMESTACK(tc)); - - /* allocate a new stack, retaining same relative sfp */ - sfp_offset = (uptr)sfp - (uptr)split_point; - tc_mutex_acquire() - S_reset_scheme_stack(tc, above_split_size + frame_request); - tc_mutex_release() - SFP(tc) = (ptr)((uptr)SCHEMESTACK(tc) + sfp_offset); - - /* copy up everything above the split point. we don't know where the - current frame ends, so we copy through the end of the old stack */ - {ptr *p, *q; iptr n; - p = (ptr *)SCHEMESTACK(tc); - q = split_point; - for (n = above_split_size; n != 0; n -= sizeof(ptr)) *p++ = *q++; - } -} - -void S_error_abort(const char *s) { - fprintf(stderr, "%s\n", s); - S_abnormal_exit(); -} - -void S_abnormal_exit(void) { - S_abnormal_exit_proc(); - fprintf(stderr, "abnormal_exit procedure did not exit\n"); - exit(1); -} - -static void reset_scheme(void) { - ptr tc = get_thread_context(); - - tc_mutex_acquire() - /* eap should always be up-to-date now that we write-through to the tc - when making any changes to eap when eap is a real register */ - S_scan_dirty((ptr **)EAP(tc), (ptr **)REAL_EAP(tc)); - S_reset_allocation_pointer(tc); - S_reset_scheme_stack(tc, stack_slop); - FRAME(tc,0) = (ptr)DOUNDERFLOW; - tc_mutex_release() -} - -/* error_resets occur with the system in an unknown state, - * thus we must reset with no opportunity for debugging - */ - -void S_error_reset(const char *s) { - - if (!S_errors_to_console) reset_scheme(); - do_error(ERROR_RESET, "", s, Snil); -} - -void S_error(const char *who, const char *s) { - do_error(ERROR_OTHER, who, s, Snil); -} - -void S_error1(const char *who, const char *s, ptr x) { - do_error(ERROR_OTHER, who, s, LIST1(x)); -} - -void S_error2(const char *who, const char *s, ptr x, ptr y) { - do_error(ERROR_OTHER, who, s, LIST2(x,y)); -} - -void S_error3(const char *who, const char *s, ptr x, ptr y, ptr z) { - do_error(ERROR_OTHER, who, s, LIST3(x,y,z)); -} - -void S_boot_error(ptr who, ptr msg, ptr args) { - printf("error caught before error-handing subsystem initialized\n"); - printf("who: "); - S_prin1(who); - printf("\nmsg: "); - S_prin1(msg); - printf("\nargs: "); - S_prin1(args); - printf("\n"); - fflush(stdout); - S_abnormal_exit(); -} - -static void do_error(iptr type, const char *who, const char *s, ptr args) { - ptr tc = get_thread_context(); - - if (S_errors_to_console || tc == (ptr)0 || CCHAIN(tc) == Snil) { - if (strlen(who) == 0) - printf("Error: %s\n", s); - else - printf("Error in %s: %s\n", who, s); - S_prin1(args); putchar('\n'); - fflush(stdout); - S_abnormal_exit(); - } - - args = Scons(FIX(type), - Scons((strlen(who) == 0 ? Sfalse : Sstring_utf8(who,-1)), - Scons(Sstring_utf8(s, -1), args))); - -#ifdef PTHREADS - while (S_tc_mutex_depth > 0) { - S_mutex_release(&S_tc_mutex); - S_tc_mutex_depth -= 1; - } -#endif /* PTHREADS */ - - TRAP(tc) = (ptr)1; - AC0(tc) = (ptr)1; - CP(tc) = S_symbol_value(S_G.error_id); - S_put_scheme_arg(tc, 1, args); - LONGJMP(CAAR(CCHAIN(tc)), -1); -} - -static void handle_call_error(ptr tc, iptr type, ptr x) { - ptr p, arg1; - iptr argcnt; - - argcnt = (iptr)AC0(tc); - arg1 = argcnt == 0 ? Snil : S_get_scheme_arg(tc, 1); - p = Scons(FIX(type), Scons(FIX(argcnt), Scons(x, Scons(arg1, Snil)))); - - if (S_errors_to_console) { - printf("Call error: "); - S_prin1(p); putchar('\n'); fflush(stdout); - S_abnormal_exit(); - } - - CP(tc) = S_symbol_value(S_G.error_id); - S_put_scheme_arg(tc, 1, p); - AC0(tc) = (ptr)(argcnt==0 ? 1 : argcnt); - TRAP(tc) = (ptr)1; /* Why is this here? */ -} - -void S_handle_docall_error(void) { - ptr tc = get_thread_context(); - - handle_call_error(tc, ERROR_CALL_NONPROCEDURE, CP(tc)); -} - -void S_handle_arg_error(void) { - ptr tc = get_thread_context(); - - handle_call_error(tc, ERROR_CALL_ARGUMENT_COUNT, CP(tc)); -} - -void S_handle_nonprocedure_symbol(void) { - ptr tc = get_thread_context(); - ptr s; - - s = XP(tc); - handle_call_error(tc, - (SYMVAL(s) == sunbound ? - ERROR_CALL_UNBOUND : - ERROR_CALL_NONPROCEDURE_SYMBOL), - s); -} - -void S_handle_values_error(void) { - ptr tc = get_thread_context(); - - handle_call_error(tc, ERROR_VALUES, Sfalse); -} - -void S_handle_mvlet_error(void) { - ptr tc = get_thread_context(); - - handle_call_error(tc, ERROR_MVLET, Sfalse); -} - -static void keyboard_interrupt(ptr tc) { - KEYBOARDINTERRUPTPENDING(tc) = Strue; - SOMETHINGPENDING(tc) = Strue; -} - -/* used in printf below -static uptr list_length(ptr ls) { - uptr i = 0; - while (ls != Snil) { ls = Scdr(ls); i += 1; } - return i; -} -*/ - -void S_fire_collector(void) { - ptr crp_id = S_G.collect_request_pending_id; - -/* printf("firing collector!\n"); fflush(stdout); */ - - if (!Sboolean_value(S_symbol_value(crp_id))) { - ptr ls; - -/* printf("really firing collector!\n"); fflush(stdout); */ - - tc_mutex_acquire() - /* check again in case some other thread beat us to the punch */ - if (!Sboolean_value(S_symbol_value(crp_id))) { -/* printf("firing collector nthreads = %d\n", list_length(S_threads)); fflush(stdout); */ - S_set_symbol_value(crp_id, Strue); - for (ls = S_threads; ls != Snil; ls = Scdr(ls)) - SOMETHINGPENDING(THREADTC(Scar(ls))) = Strue; - } - tc_mutex_release() - } -} - -void S_noncontinuable_interrupt(void) { - ptr tc = get_thread_context(); - - reset_scheme(); - KEYBOARDINTERRUPTPENDING(tc) = Sfalse; - do_error(ERROR_NONCONTINUABLE_INTERRUPT,"","",Snil); -} - -#ifdef WIN32 -ptr S_dequeue_scheme_signals(ptr tc) { - return Snil; -} - -ptr S_allocate_scheme_signal_queue(void) { - return (ptr)0; -} - -void S_register_scheme_signal(iptr sig) { - S_error("register_scheme_signal", "unsupported in this version"); -} - -/* code courtesy Bob Burger, burgerrg@sagian.com - We cannot call noncontinuable_interrupt, because we are not allowed - to perform a longjmp inside a signal handler; instead, we don't - handle the signal, which will cause the process to terminate. -*/ - -static BOOL WINAPI handle_signal(DWORD dwCtrlType) { - switch (dwCtrlType) { - case CTRL_C_EVENT: - case CTRL_BREAK_EVENT: { -#ifdef PTHREADS - /* get_thread_context() always returns 0, so assume main thread */ - ptr tc = S_G.thread_context; -#else - ptr tc = get_thread_context(); -#endif - if (!S_pants_down && Sboolean_value(KEYBOARDINTERRUPTPENDING(tc))) - return(FALSE); - keyboard_interrupt(tc); - return(TRUE); - } - } - return(FALSE); -} - -static void init_signal_handlers(void) { - SetConsoleCtrlHandler(handle_signal, TRUE); -} -#else /* WIN32 */ - -#include - -static void handle_signal(INT sig, siginfo_t *si, void *data); -static IBOOL enqueue_scheme_signal(ptr tc, INT sig); -static ptr allocate_scheme_signal_queue(void); -static void forward_signal_to_scheme(INT sig); - -#define RESET_SIGNAL {\ - sigset_t set;\ - sigemptyset(&set);\ - sigaddset(&set, sig);\ - sigprocmask(SIG_UNBLOCK,&set,(sigset_t *)0);\ -} - -/* we buffer up to SIGNALQUEUESIZE - 1 unhandled signals, then start dropping them. */ -#define SIGNALQUEUESIZE 64 -static IBOOL scheme_signals_registered; - -/* we use a simple queue for pending signals. signals are enqueued only by the - C signal handler and dequeued only by the Scheme event handler. since the signal - handler and event handler run in the same thread, there's no need for locks - or write barriers. */ - -struct signal_queue { - INT head; - INT tail; - INT data[SIGNALQUEUESIZE]; -}; - -static IBOOL enqueue_scheme_signal(ptr tc, INT sig) { - struct signal_queue *queue = (struct signal_queue *)(SIGNALINTERRUPTQUEUE(tc)); - /* ignore the signal if we failed to allocate the queue */ - if (queue == NULL) return 0; - INT tail = queue->tail; - INT next_tail = tail + 1; - if (next_tail == SIGNALQUEUESIZE) next_tail = 0; - /* ignore the signal if the queue is full */ - if (next_tail == queue->head) return 0; - queue->data[tail] = sig; - queue->tail = next_tail; - return 1; -} - -ptr S_dequeue_scheme_signals(ptr tc) { - ptr ls = Snil; - struct signal_queue *queue = (struct signal_queue *)(SIGNALINTERRUPTQUEUE(tc)); - if (queue == NULL) return ls; - INT head = queue->head; - INT tail = queue->tail; - INT i = tail; - while (i != head) { - if (i == 0) i = SIGNALQUEUESIZE; - i -= 1; - ls = Scons(Sfixnum(queue->data[i]), ls); - } - queue->head = tail; - return ls; -} - -static void forward_signal_to_scheme(INT sig) { - ptr tc = get_thread_context(); - - if (enqueue_scheme_signal(tc, sig)) { - SIGNALINTERRUPTPENDING(tc) = Strue; - SOMETHINGPENDING(tc) = Strue; - } - RESET_SIGNAL -} - -static ptr allocate_scheme_signal_queue(void) { - /* silently fail to allocate space for signals if malloc returns NULL */ - struct signal_queue *queue = malloc(sizeof(struct signal_queue)); - if (queue != (struct signal_queue *)0) { - queue->head = queue->tail = 0; - } - return (ptr)queue; -} - -ptr S_allocate_scheme_signal_queue(void) { - return scheme_signals_registered ? allocate_scheme_signal_queue() : (ptr)0; -} - -void S_register_scheme_signal(iptr sig) { - struct sigaction act; - - tc_mutex_acquire() - if (!scheme_signals_registered) { - ptr ls; - scheme_signals_registered = 1; - for (ls = S_threads; ls != Snil; ls = Scdr(ls)) { - SIGNALINTERRUPTQUEUE(THREADTC(Scar(ls))) = S_allocate_scheme_signal_queue(); - } - } - tc_mutex_release() - - sigfillset(&act.sa_mask); - act.sa_flags = 0; - act.sa_handler = forward_signal_to_scheme; - sigaction(sig, &act, (struct sigaction *)0); -} - -static void handle_signal(INT sig, UNUSED siginfo_t *si, UNUSED void *data) { -/* printf("handle_signal(%d) for tc %x\n", sig, UNFIX(get_thread_context())); fflush(stdout); */ - /* check for particular signals */ - switch (sig) { - case SIGINT: { - ptr tc = get_thread_context(); - /* disable keyboard interrupts in subordinate threads until we think - of something more clever to do with them */ - if (tc == S_G.thread_context) { - if (!S_pants_down && Sboolean_value(KEYBOARDINTERRUPTPENDING(tc))) { - /* this is a no-no, but the only other options are to ignore - the signal or to kill the process */ - RESET_SIGNAL - S_noncontinuable_interrupt(); - } - keyboard_interrupt(tc); - } - RESET_SIGNAL - break; - } -#ifdef SIGQUIT - case SIGQUIT: - RESET_SIGNAL - S_abnormal_exit(); -#endif /* SIGQUIT */ - case SIGILL: - RESET_SIGNAL - S_error_reset("illegal instruction"); - case SIGFPE: - RESET_SIGNAL - S_error_reset("arithmetic overflow"); -#ifdef SIGBUS - case SIGBUS: -#endif /* SIGBUS */ - case SIGSEGV: - RESET_SIGNAL - if (S_pants_down) - S_error_abort("nonrecoverable invalid memory reference"); - else - S_error_reset("invalid memory reference"); - default: - RESET_SIGNAL - S_error_reset("unexpected signal"); - } -} - -static void init_signal_handlers(void) { - struct sigaction act; - - sigemptyset(&act.sa_mask); - - /* drop pending keyboard interrupts */ - act.sa_flags = 0; - act.sa_handler = SIG_IGN; - sigaction(SIGINT, &act, (struct sigaction *)0); - - /* ignore broken pipe signals */ - act.sa_flags = 0; - act.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &act, (struct sigaction *)0); - - /* set up to catch SIGINT w/no system call restart */ -#ifdef SA_INTERRUPT - act.sa_flags = SA_INTERRUPT|SA_SIGINFO; -#else - act.sa_flags = SA_SIGINFO; -#endif /* SA_INTERRUPT */ - act.sa_sigaction = handle_signal; - sigaction(SIGINT, &act, (struct sigaction *)0); -#ifdef BSDI - siginterrupt(SIGINT, 1); -#endif - - /* set up to catch selected signals */ - act.sa_flags = SA_SIGINFO; - act.sa_sigaction = handle_signal; -#ifdef SA_RESTART - act.sa_flags |= SA_RESTART; -#endif /* SA_RESTART */ -#ifdef SIGQUIT - sigaction(SIGQUIT, &act, (struct sigaction *)0); -#endif /* SIGQUIT */ - sigaction(SIGILL, &act, (struct sigaction *)0); - sigaction(SIGFPE, &act, (struct sigaction *)0); -#ifdef SIGBUS - sigaction(SIGBUS, &act, (struct sigaction *)0); -#endif /* SIGBUS */ - sigaction(SIGSEGV, &act, (struct sigaction *)0); -} - -#endif /* WIN32 */ - -void S_schsig_init(void) { - if (S_boot_time) { - ptr p; - - S_protect(&S_G.nuate_id); - S_G.nuate_id = S_intern((const unsigned char *)"$nuate"); - S_set_symbol_value(S_G.nuate_id, FIX(0)); - - S_protect(&S_G.null_continuation_id); - S_G.null_continuation_id = S_intern((const unsigned char *)"$null-continuation"); - - S_protect(&S_G.collect_request_pending_id); - S_G.collect_request_pending_id = S_intern((const unsigned char *)"$collect-request-pending"); - - p = S_code(get_thread_context(), type_code | (code_flag_continuation << code_flags_offset), 0); - CODERELOC(p) = S_relocation_table(0); - CODENAME(p) = Sfalse; - CODEARITYMASK(p) = FIX(0); - CODEFREE(p) = 0; - CODEINFO(p) = Sfalse; - CODEPINFOS(p) = Snil; - - S_set_symbol_value(S_G.null_continuation_id, - S_mkcontinuation(space_new, - 0, - CODEENTRYPOINT(p), - FIX(0), - scaled_shot_1_shot_flag, scaled_shot_1_shot_flag, - FIX(0), - FIX(0), - Snil)); - - S_protect(&S_G.error_id); - S_G.error_id = S_intern((const unsigned char *)"$c-error"); -#ifndef WIN32 - scheme_signals_registered = 0; -#endif - } - - - S_pants_down = 0; - S_set_symbol_value(S_G.collect_request_pending_id, Sfalse); - - init_signal_handlers(); -} diff --git a/ta6ob/c/schsig.o b/ta6ob/c/schsig.o deleted file mode 100644 index 921d9e2..0000000 Binary files a/ta6ob/c/schsig.o and /dev/null differ diff --git a/ta6ob/c/segment.c b/ta6ob/c/segment.c deleted file mode 100644 index 24fb377..0000000 --- a/ta6ob/c/segment.c +++ /dev/null @@ -1,503 +0,0 @@ -/* segment.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* -Low-level Memory management strategy: - * use getmem-allocated multiple-segment chunks of memory - * maintain getmem-allocated list of chunks - * maintain getmem-allocated segment info and dirty vector tables - * after each collection, run through the list of chunks. If all - segments in a chunk are empty, the chunk is a candidate for return - to the O/S. Return (freemem) as many chunks as possible without going - below a user-defined threshold of empty segments (determined as a - multiple of the occupied nonstatic segments). Bias return to the - most recently allocated chunks. - * getmem/freemem may be implemented with malloc/free; we use them - relatively infrequently so performance isn't an issue. -*/ - -#define debug(x) ; -/* #define debug(x) {x; fflush(stdout);} */ - -#include "system.h" -#include "sort.h" -#include - -static void out_of_memory(void); -static void initialize_seginfo(seginfo *si, ISPC s, IGEN g); -static seginfo *allocate_segments(uptr nreq); -static void expand_segment_table(uptr base, uptr end, seginfo *si); -static void contract_segment_table(uptr base, uptr end); -static void add_to_chunk_list(chunkinfo *chunk, chunkinfo **pchunk_list); -static seginfo *sort_seginfo(seginfo *si, uptr n); -static seginfo *merge_seginfo(seginfo *si1, seginfo *si2); - -void S_segment_init(void) { - IGEN g; ISPC s; int i; - - if (!S_boot_time) return; - - S_chunks_full = NULL; - for (i = PARTIAL_CHUNK_POOLS; i >= 0; i -= 1) S_chunks[i] = NULL; - for (g = 0; g <= static_generation; g++) { - for (s = 0; s <= max_real_space; s++) { - S_G.occupied_segments[g][s] = NULL; - } - } - S_G.number_of_nonstatic_segments = 0; - S_G.number_of_empty_segments = 0; -} - -static uptr membytes = 0; -static uptr maxmembytes = 0; - -static void out_of_memory(void) { - (void) fprintf(stderr,"out of memory\n"); - S_abnormal_exit(); -} - -#if defined(USE_MALLOC) -void *S_getmem(iptr bytes, IBOOL zerofill) { - void *addr; - - if ((addr = malloc(bytes)) == (void *)0) out_of_memory(); - - debug(printf("getmem(%p) -> %p\n", bytes, addr)) - if ((membytes += bytes) > maxmembytes) maxmembytes = membytes; - if (zerofill) memset(addr, 0, bytes); - return addr; -} - -void S_freemem(void *addr, iptr bytes) { - debug(printf("freemem(%p, %p)\n", addr, bytes)) - free(addr); - membytes -= bytes; -} -#endif - -#if defined(USE_VIRTUAL_ALLOC) -#include -void *S_getmem(iptr bytes, IBOOL zerofill) { - void *addr; - - if ((uptr)bytes < S_pagesize) { - if ((addr = malloc(bytes)) == (void *)0) out_of_memory(); - debug(printf("getmem malloc(%p) -> %p\n", bytes, addr)) - if ((membytes += bytes) > maxmembytes) maxmembytes = membytes; - if (zerofill) memset(addr, 0, bytes); - } else { - uptr n = S_pagesize - 1; iptr p_bytes = (iptr)(((uptr)bytes + n) & ~n); - if ((addr = VirtualAlloc((void *)0, (SIZE_T)p_bytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == (void *)0) out_of_memory(); - if ((membytes += p_bytes) > maxmembytes) maxmembytes = membytes; - debug(printf("getmem VirtualAlloc(%p => %p) -> %p\n", bytes, p_bytes, addr)) - } - - return addr; -} - -void S_freemem(void *addr, iptr bytes) { - if ((uptr)bytes < S_pagesize) { - debug(printf("freemem free(%p, %p)\n", addr, bytes)) - membytes -= bytes; - free(addr); - } else { - uptr n = S_pagesize - 1; iptr p_bytes = (iptr)(((uptr)bytes + n) & ~n); - debug(printf("freemem VirtualFree(%p, %p => %p)\n", addr, bytes, p_bytes)) - membytes -= p_bytes; - VirtualFree(addr, 0, MEM_RELEASE); - } -} -#endif - -#if defined(USE_MMAP) -#include -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif -void *S_getmem(iptr bytes, IBOOL zerofill) { - void *addr; - - if ((uptr)bytes < S_pagesize) { - if ((addr = malloc(bytes)) == (void *)0) out_of_memory(); - debug(printf("getmem malloc(%p) -> %p\n", bytes, addr)) - if ((membytes += bytes) > maxmembytes) maxmembytes = membytes; - if (zerofill) memset(addr, 0, bytes); - } else { - uptr n = S_pagesize - 1; iptr p_bytes = (iptr)(((uptr)bytes + n) & ~n); -#ifdef MAP_32BIT - /* try for first 2GB of the memory space first of x86_64 so that we have a - better chance of having short jump instructions */ - if ((addr = mmap(NULL, p_bytes, PROT_EXEC|PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0)) == (void *)-1) { -#endif - if ((addr = mmap(NULL, p_bytes, PROT_EXEC|PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)) == (void *)-1) { - out_of_memory(); - debug(printf("getmem mmap(%p) -> %p\n", bytes, addr)) - } -#ifdef MAP_32BIT - } -#endif - if ((membytes += p_bytes) > maxmembytes) maxmembytes = membytes; - debug(printf("getmem mmap(%p => %p) -> %p\n", bytes, p_bytes, addr)) - } - - return addr; -} - -void S_freemem(void *addr, iptr bytes) { - if ((uptr)bytes < S_pagesize) { - debug(printf("freemem free(%p, %p)\n", addr, bytes)) - free(addr); - membytes -= bytes; - } else { - uptr n = S_pagesize - 1; iptr p_bytes = (iptr)(((uptr)bytes + n) & ~n); - debug(printf("freemem munmap(%p, %p => %p)\n", addr, bytes, p_bytes)) - munmap(addr, p_bytes); - membytes -= p_bytes; - } -} -#endif - -void S_move_to_chunk_list(chunkinfo *chunk, chunkinfo **pchunk_list) { - if ((*chunk->prev = chunk->next) != NULL) chunk->next->prev = chunk->prev; - add_to_chunk_list(chunk, pchunk_list); -} - -static void add_to_chunk_list(chunkinfo *chunk, chunkinfo **pchunk_list) { - if ((chunk->next = *pchunk_list) != NULL) (*pchunk_list)->prev = &chunk->next; - chunk->prev = pchunk_list; - *pchunk_list = chunk; -} - -#define SEGLT(x, y) ((x)->number < (y)->number) -#define SEGCDR(x) ((x)->next) -mkmergesort(sort_seginfo, merge_seginfo, seginfo *, NULL, SEGLT, SEGCDR) - -static void sort_chunk_unused_segments(chunkinfo *chunk) { - seginfo *si, *nextsi, *sorted, *unsorted; uptr n; - - /* bail out early if we find the unused segments list is already sorted */ - if ((unsorted = chunk->unused_segs)->sorted) return; - - /* find the sorted tail so we can just sort in the unsorted ones */ - si = unsorted; - n = 1; - for (;;) { - si->sorted = 1; - if ((nextsi = si->next) == NULL || nextsi->sorted) { - sorted = nextsi; - si->next = NULL; - break; - } - si = nextsi; - n += 1; - } - - sorted = merge_seginfo(sort_seginfo(unsorted, n), sorted); - - chunk->unused_segs = sorted; -} - -static INT find_index(iptr n) { - INT index = (INT)((n >> 2) + 1); - - return (index < PARTIAL_CHUNK_POOLS-1) ? index : PARTIAL_CHUNK_POOLS-1; -} - -static void initialize_seginfo(seginfo *si, ISPC s, IGEN g) { - INT d; - - si->space = s; - si->generation = g; - si->sorted = 0; - si->min_dirty_byte = 0xff; - si->trigger_ephemerons = NULL; - for (d = 0; d < cards_per_segment; d += sizeof(ptr)) { - iptr *dp = (iptr *)(si->dirty_bytes + d); - /* fill sizeof(iptr) bytes at a time with 0xff */ - *dp = -1; - } -} - -iptr S_find_segments(ISPC s, IGEN g, iptr n) { - chunkinfo *chunk, *nextchunk; - seginfo *si, *nextsi, **prevsi; - iptr nunused_segs, j; - INT i, loser_index; - - if (g != static_generation) S_G.number_of_nonstatic_segments += n; - - debug(printf("attempting to find %d segments for space %d, generation %d\n", n, s, g)) - - if (n == 1) { - for (i = 0; i <= PARTIAL_CHUNK_POOLS; i++) { - chunk = S_chunks[i]; - if (chunk != NULL) { - si = chunk->unused_segs; - chunk->unused_segs = si->next; - - if (chunk->unused_segs == NULL) { - S_move_to_chunk_list(chunk, &S_chunks_full); - } else if (i == PARTIAL_CHUNK_POOLS) { - S_move_to_chunk_list(chunk, &S_chunks[PARTIAL_CHUNK_POOLS-1]); - } - - chunk->nused_segs += 1; - initialize_seginfo(si, s, g); - si->next = S_G.occupied_segments[g][s]; - S_G.occupied_segments[g][s] = si; - S_G.number_of_empty_segments -= 1; - return si->number; - } - } - } else { - loser_index = (n == 2) ? 0 : find_index(n-1); - for (i = find_index(n); i <= PARTIAL_CHUNK_POOLS; i += 1) { - chunk = S_chunks[i]; - while (chunk != NULL) { - if (n < (nunused_segs = (chunk->segs - chunk->nused_segs))) { - sort_chunk_unused_segments(chunk); - si = chunk->unused_segs; - prevsi = &chunk->unused_segs; - while (nunused_segs >= n) { - nextsi = si; - j = n - 1; - for (;;) { - nunused_segs -= 1; - if (nextsi->number + 1 != nextsi->next->number) { - si = nextsi->next; - prevsi = &nextsi->next; - break; - } - nextsi = nextsi->next; - if (--j == 0) { - *prevsi = nextsi->next; - if (chunk->unused_segs == NULL) { - S_move_to_chunk_list(chunk, &S_chunks_full); - } else if (i == PARTIAL_CHUNK_POOLS) { - S_move_to_chunk_list(chunk, &S_chunks[PARTIAL_CHUNK_POOLS-1]); - } - chunk->nused_segs += n; - nextsi->next = S_G.occupied_segments[g][s]; - S_G.occupied_segments[g][s] = si; - for (j = n, nextsi = si; j > 0; j -= 1, nextsi = nextsi->next) { - initialize_seginfo(nextsi, s, g); - } - S_G.number_of_empty_segments -= n; - return si->number; - } - } - } - } - nextchunk = chunk->next; - if (i != loser_index && i != PARTIAL_CHUNK_POOLS) { - S_move_to_chunk_list(chunk, &S_chunks[loser_index]); - } - chunk = nextchunk; - } - } - } - - /* we couldn't find space, so ask for more */ - si = allocate_segments(n); - for (nextsi = si; n > 0; n -= 1, nextsi += 1) { - initialize_seginfo(nextsi, s, g); - /* add segment to appropriate list of occupied segments */ - nextsi->next = S_G.occupied_segments[g][s]; - S_G.occupied_segments[g][s] = nextsi; - } - return si->number; -} - -/* allocate_segments(n) - * allocates a group of n contiguous fresh segments, returning the - * segment number of the first segment of the group. - */ -static seginfo *allocate_segments(nreq) uptr nreq; { - uptr nact, bytes, base; void *addr; - iptr i; - chunkinfo *chunk; seginfo *si; - - nact = nreq < minimum_segment_request ? minimum_segment_request : nreq; - - bytes = (nact + 1) * bytes_per_segment; - addr = S_getmem(bytes, 0); - debug(printf("allocate_segments addr = %p\n", addr)) - - base = addr_get_segment((uptr)addr + bytes_per_segment - 1); - /* if the base of the first segment is the same as the base of the chunk, and - the last segment isn't the last segment in memory (which could cause 'next' and 'end' - pointers to wrap), we've actually got nact + 1 usable segments in this chunk */ - if (build_ptr(base, 0) == addr && base + nact != ((uptr)1 << (ptr_bits - segment_offset_bits)) - 1) - nact += 1; - - chunk = S_getmem(sizeof(chunkinfo) + sizeof(seginfo) * nact, 0); - debug(printf("allocate_segments chunk = %p\n", chunk)) - chunk->addr = addr; - chunk->base = base; - chunk->bytes = bytes; - chunk->segs = nact; - chunk->nused_segs = nreq; - chunk->unused_segs = NULL; - - expand_segment_table(base, base + nact, &chunk->sis[0]); - - /* initialize seginfos */ - for (i = nact - 1; i >= 0; i -= 1) { - si = &chunk->sis[i]; - si->chunk = chunk; - si->number = i + base; - if (i >= (iptr)nreq) { - si->space = space_empty; - si->generation = 0; - si->sorted = 1; /* inserting in reverse order, so emptys are always sorted */ - si->next = chunk->unused_segs; - chunk->unused_segs = si; - } - } - - /* account for trailing empty segments */ - if (nact > nreq) { - S_G.number_of_empty_segments += nact - nreq; - add_to_chunk_list(chunk, &S_chunks[PARTIAL_CHUNK_POOLS-1]); - } else { - add_to_chunk_list(chunk, &S_chunks_full); - } - - return &chunk->sis[0]; -} - -void S_free_chunk(chunkinfo *chunk) { - chunkinfo *nextchunk = chunk->next; - contract_segment_table(chunk->base, chunk->base + chunk->segs); - S_G.number_of_empty_segments -= chunk->segs; - *chunk->prev = nextchunk; - if (nextchunk != NULL) nextchunk->prev = chunk->prev; - S_freemem(chunk->addr, chunk->bytes); - S_freemem(chunk, sizeof(chunkinfo) + sizeof(seginfo) * chunk->segs); -} - -/* retain approximately heap-reserve-ratio segments for every - * nonempty nonstatic segment. */ -void S_free_chunks(void) { - iptr ntofree; - chunkinfo *chunk, *nextchunk; - - ntofree = S_G.number_of_empty_segments - - (iptr)(Sflonum_value(SYMVAL(S_G.heap_reserve_ratio_id)) * S_G.number_of_nonstatic_segments); - - for (chunk = S_chunks[PARTIAL_CHUNK_POOLS]; ntofree > 0 && chunk != NULL; chunk = nextchunk) { - nextchunk = chunk->next; - ntofree -= chunk->segs; - S_free_chunk(chunk); - } -} - -uptr S_curmembytes(void) { - return membytes; -} - -uptr S_maxmembytes(void) { - return maxmembytes; -} - -void S_resetmaxmembytes(void) { - maxmembytes = membytes; -} - -static void expand_segment_table(uptr base, uptr end, seginfo *si) { -#ifdef segment_t2_bits -#ifdef segment_t3_bits - t2table *t2i; -#endif - t1table **t2, *t1i; uptr n; -#endif - seginfo **t1, **t1end; - -#ifdef segment_t2_bits - while (base != end) { -#ifdef segment_t3_bits - if ((t2i = S_segment_info[SEGMENT_T3_IDX(base)]) == NULL) { - S_segment_info[SEGMENT_T3_IDX(base)] = t2i = (t2table *)S_getmem(sizeof(t2table), 1); - } - t2 = t2i->t2; -#else - t2 = S_segment_info; -#endif - if ((t1i = t2[SEGMENT_T2_IDX(base)]) == NULL) { - t2[SEGMENT_T2_IDX(base)] = t1i = (t1table *)S_getmem(sizeof(t1table), 1); -#ifdef segment_t3_bits - t2i->refcount += 1; -#endif - } - t1 = t1i->t1 + SEGMENT_T1_IDX(base); - t1end = t1 + end - base < t1i->t1 + SEGMENT_T1_SIZE ? t1 + end - base : t1i->t1 + SEGMENT_T1_SIZE; - n = t1end - t1; - t1i->refcount += n; - - while (t1 < t1end) *t1++ = si++; - base += n; - } -#else - t1 = S_segment_info + SEGMENT_T1_IDX(base); - t1end = t1 + end - base; - while (t1 < t1end) *t1++ = si++; -#endif -} - -static void contract_segment_table(uptr base, uptr end) { -#ifdef segment_t2_bits -#ifdef segment_t3_bits - t2table *t2i; -#endif - t1table **t2, *t1i; uptr n; -#endif - seginfo **t1, **t1end; - -#ifdef segment_t2_bits - while (base != end) { -#ifdef segment_t3_bits - t2i = S_segment_info[SEGMENT_T3_IDX(base)]; - t2 = t2i->t2; -#else - t2 = S_segment_info; -#endif - t1i = t2[SEGMENT_T2_IDX(base)]; - t1 = t1i->t1 + SEGMENT_T1_IDX(base); - t1end = t1 + end - base < t1i->t1 + SEGMENT_T1_SIZE ? t1 + end - base : t1i->t1 + SEGMENT_T1_SIZE; - n = t1end - t1; - if ((t1i->refcount -= n) == 0) { - S_freemem((void *)t1i, sizeof(t1table)); -#ifdef segment_t3_bits - if ((t2i->refcount -= 1) == 0) { - S_freemem((void *)t2i, sizeof(t2table)); - S_segment_info[SEGMENT_T3_IDX(base)] = NULL; - } else { - S_segment_info[SEGMENT_T3_IDX(base)]->t2[SEGMENT_T2_IDX(base)] = NULL; - } -#else - S_segment_info[SEGMENT_T2_IDX(base)] = NULL; -#endif - } else { - while (t1 < t1end) *t1++ = NULL; - } - base += n; - } -#else - t1 = S_segment_info + SEGMENT_T1_IDX(base); - t1end = t1 + end - base; - while (t1 < t1end) *t1++ = NULL; -#endif -} diff --git a/ta6ob/c/segment.h b/ta6ob/c/segment.h deleted file mode 100644 index 0d6c3b0..0000000 --- a/ta6ob/c/segment.h +++ /dev/null @@ -1,83 +0,0 @@ -/* segment.h - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef WIN32 -# ifndef __MINGW32__ -# undef FORCEINLINE -# define FORCEINLINE static __forceinline -# endif -#else -#define FORCEINLINE static inline -#endif - -/* segment_info */ - -#define SEGMENT_T1_SIZE (1<>segment_t1_bits)&(SEGMENT_T2_SIZE-1)) -#define SEGMENT_T3_SIZE (1<>(segment_t2_bits+segment_t1_bits)) - -FORCEINLINE seginfo *SegInfo(uptr i) { - return S_segment_info[SEGMENT_T3_IDX(i)]->t2[SEGMENT_T2_IDX(i)]->t1[SEGMENT_T1_IDX(i)]; -} - -FORCEINLINE seginfo *MaybeSegInfo(uptr i) { - t2table *t2i; t1table *t1i; - if ((t2i = S_segment_info[SEGMENT_T3_IDX(i)]) == NULL) return NULL; - if ((t1i = t2i->t2[SEGMENT_T2_IDX(i)]) == NULL) return NULL; - return t1i->t1[SEGMENT_T1_IDX(i)]; -} - -#else /* segment_t3_bits */ -#ifdef segment_t2_bits - -#define SEGMENT_T2_SIZE (1<>segment_t1_bits) -#define SEGMENT_T3_SIZE 0 - -FORCEINLINE seginfo *SegInfo(uptr i) { - return S_segment_info[SEGMENT_T2_IDX(i)]->t1[SEGMENT_T1_IDX(i)]; -} - -FORCEINLINE seginfo *MaybeSegInfo(uptr i) { - t1table *t1i; - if ((t1i = S_segment_info[SEGMENT_T2_IDX(i)]) == NULL) return NULL; - return t1i->t1[SEGMENT_T1_IDX(i)]; -} - -#else /* segment_t2_bits */ - -#define SEGMENT_T2_SIZE 0 -#define SEGMENT_T3_SIZE 0 - -FORCEINLINE seginfo *SegInfo(uptr i) { - return S_segment_info[SEGMENT_T1_IDX(i)]; -} - -FORCEINLINE seginfo *MaybeSegInfo(uptr i) { - return S_segment_info[SEGMENT_T1_IDX(i)]; -} - -#endif /* segment_t2_bits */ -#endif /* segment_t3_bits */ - -#define SegmentSpace(i) (SegInfo(i)->space) -#define SegmentGeneration(i) (SegInfo(i)->generation) diff --git a/ta6ob/c/segment.o b/ta6ob/c/segment.o deleted file mode 100644 index e1b6478..0000000 Binary files a/ta6ob/c/segment.o and /dev/null differ diff --git a/ta6ob/c/sort.h b/ta6ob/c/sort.h deleted file mode 100644 index ae0652b..0000000 --- a/ta6ob/c/sort.h +++ /dev/null @@ -1,40 +0,0 @@ -/* sort.h - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define mkmergesort(sort, merge, type, nil, lt, cdr)\ -type sort(type ls, uptr len) {\ - if (len == 1) {\ - cdr(ls) = nil;\ - return ls;\ - } else {\ - uptr head_len, i; type tail;\ - head_len = len >> 1;\ - for (tail = ls, i = head_len; i != 0; i -= 1) tail = cdr(tail);\ - return merge(sort(ls, head_len), sort(tail, len - head_len));\ - }\ -}\ -type merge(type ls1, type ls2) {\ - type p; type *pp = &p;\ - for (;;) {\ - if (ls1 == nil) { *pp = ls2; break; }\ - if (ls2 == nil) { *pp = ls1; break; }\ - if (lt(ls2, ls1))\ - { *pp = ls2; pp = &cdr(ls2); ls2 = cdr(ls2); }\ - else\ - { *pp = ls1; pp = &cdr(ls1); ls1 = cdr(ls1); }\ - }\ - return p;\ -} diff --git a/ta6ob/c/statics.c b/ta6ob/c/statics.c deleted file mode 100644 index d5618d0..0000000 --- a/ta6ob/c/statics.c +++ /dev/null @@ -1,22 +0,0 @@ -/* statics.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define EXTERN -#include "system.h" - -/* The C linker may require a reference to a function to pull in all - the common declarations. */ -void scheme_statics(void) { } diff --git a/ta6ob/c/statics.o b/ta6ob/c/statics.o deleted file mode 100644 index e135fc2..0000000 Binary files a/ta6ob/c/statics.o and /dev/null differ diff --git a/ta6ob/c/stats.c b/ta6ob/c/stats.c deleted file mode 100644 index 8f7b68a..0000000 --- a/ta6ob/c/stats.c +++ /dev/null @@ -1,528 +0,0 @@ -/* stats.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if defined(SOLARIS) -/* make gmtime_r and localtime_r visible */ -#ifndef _REENTRANT -#define _REENTRANT -#endif -/* make two-argument ctime_r and two-argument asctime_r visible */ -#define _POSIX_PTHREAD_SEMANTICS -#endif /* defined(SOLARIS) */ - -#include "system.h" - -#ifdef WIN32 -#include -#include -#else /* WIN32 */ -#include -#include -#include -#endif - -static struct timespec starting_mono_tp; - -static long adjust_time_zone(ptr dtvec, struct tm *tmxp, ptr given_tzoff); - -/******** unique-id ********/ - -#if (time_t_bits == 32) -#define S_integer_time_t(x) Sinteger32((iptr)(x)) -#elif (time_t_bits == 64) -#define S_integer_time_t(x) Sinteger64(x) -#endif - -#ifdef WIN32 - -#include - -ptr S_unique_id(void) { - union {UUID uuid; U32 foo[4];} u; - u.foo[0] = 0; - u.foo[1] = 0; - u.foo[2] = 0; - u.foo[3] = 0; - UuidCreate(&u.uuid); - return S_add(S_ash(Sunsigned32(u.foo[0]), Sinteger(8*3*sizeof(U32))), - S_add(S_ash(Sunsigned32(u.foo[1]), Sinteger(8*2*sizeof(U32))), - S_add(S_ash(Sunsigned32(u.foo[2]), Sinteger(8*sizeof(U32))), - Sunsigned32(u.foo[3])))); -} - -#elif defined(USE_OSSP_UUID) /* WIN32 */ - -#include - -ptr S_unique_id(void) { - uuid_t *uuid; - U32 bin[4]; - void *bin_ptr = &bin; - size_t bin_len = sizeof(bin); - - uuid_create(&uuid); - uuid_make(uuid, UUID_MAKE_V4); - uuid_export(uuid, UUID_FMT_BIN, &bin_ptr, &bin_len); - uuid_destroy(uuid); - - return S_add(S_ash(Sunsigned32(bin[0]), Sinteger(8*3*sizeof(U32))), - S_add(S_ash(Sunsigned32(bin[1]), Sinteger(8*2*sizeof(U32))), - S_add(S_ash(Sunsigned32(bin[2]), Sinteger(8*sizeof(U32))), - Sunsigned32(bin[3])))); -} - -#elif defined(USE_NETBSD_UUID) /* USE_OSSP_UUID */ - -#include - -ptr S_unique_id(void) { - uuid_t uuid; - uint32_t status; - unsigned char bin[16]; - ptr n; - unsigned int i; - - uuid_create(&uuid, &status); - uuid_enc_le(bin, &uuid); - - n = Sinteger(0); - for (i = 0; i < sizeof(bin); i++) { - n = S_add(n, S_ash(Sinteger(bin[i]), Sinteger(8*i))); - } - - return n; -} - -#else /* USE_NETBSD_UUID */ - -#include - -ptr S_unique_id(void) { - union {uuid_t uuid; U32 foo[4];} u; - u.foo[0] = 0; - u.foo[1] = 0; - u.foo[2] = 0; - u.foo[3] = 0; - uuid_generate(u.uuid); - return S_add(S_ash(Sunsigned32(u.foo[0]), Sinteger(8*3*sizeof(U32))), - S_add(S_ash(Sunsigned32(u.foo[1]), Sinteger(8*2*sizeof(U32))), - S_add(S_ash(Sunsigned32(u.foo[2]), Sinteger(8*sizeof(U32))), - Sunsigned32(u.foo[3])))); -} - -#endif /* WIN32 */ - - -/******** time and date support ********/ - -#ifdef WIN32 - -static __int64 hires_cps = 0; - -typedef void (WINAPI *GetSystemTimeAsFileTime_t)(LPFILETIME lpSystemTimeAsFileTime); - -static GetSystemTimeAsFileTime_t s_GetSystemTimeAsFileTime = GetSystemTimeAsFileTime; - -void S_gettime(INT typeno, struct timespec *tp) { - switch (typeno) { - case time_process: { - FILETIME ftKernel, ftUser, ftDummy; - - if (GetProcessTimes(GetCurrentProcess(), &ftDummy, &ftDummy, - &ftKernel, &ftUser)) { - __int64 kernel, user, total; - kernel = ftKernel.dwHighDateTime; - kernel <<= 32; - kernel |= ftKernel.dwLowDateTime; - user = ftUser.dwHighDateTime; - user <<= 32; - user |= ftUser.dwLowDateTime; - total = user + kernel; - tp->tv_sec = (time_t)(total / 10000000); - tp->tv_nsec = (long)((total % 10000000) * 100); - break; - } else { - clock_t n = clock();; - /* if GetProcessTimes fails, we're probably running Windows 95 */ - tp->tv_sec = (time_t)(n / CLOCKS_PER_SEC); - tp->tv_nsec = (long)((n % CLOCKS_PER_SEC) * (1000000000 / CLOCKS_PER_SEC)); - break; - } - } - - case time_thread: { - FILETIME ftKernel, ftUser, ftDummy; - - if (GetThreadTimes(GetCurrentThread(), &ftDummy, &ftDummy, - &ftKernel, &ftUser)) { - __int64 kernel, user, total; - kernel = ftKernel.dwHighDateTime; - kernel <<= 32; - kernel |= ftKernel.dwLowDateTime; - user = ftUser.dwHighDateTime; - user <<= 32; - user |= ftUser.dwLowDateTime; - total = user + kernel; - tp->tv_sec = (time_t)(total / 10000000); - tp->tv_nsec = (long)((total % 10000000) * 100); - break; - } else { - clock_t n = clock();; - /* if GetThreadTimes fails, we're probably running Windows 95 */ - tp->tv_sec = (time_t)(n / CLOCKS_PER_SEC); - tp->tv_nsec = (long)((n % CLOCKS_PER_SEC) * (1000000000 / CLOCKS_PER_SEC)); - break; - } - } - - case time_duration: - case time_monotonic: { - LARGE_INTEGER count; - - if (hires_cps == 0 && QueryPerformanceFrequency(&count)) - hires_cps = count.QuadPart; - - if (hires_cps && QueryPerformanceCounter(&count)) { - tp->tv_sec = (time_t)(count.QuadPart / hires_cps); - tp->tv_nsec = (long)((count.QuadPart % hires_cps) * (1000000000 / hires_cps)); - break; - } else { - DWORD count = GetTickCount(); - tp->tv_sec = (time_t)(count / 1000); - tp->tv_nsec = (long)((count % 1000) * 1000000); - break; - } - } - - case time_utc: { - FILETIME ft; __int64 total; - - s_GetSystemTimeAsFileTime(&ft); - total = ft.dwHighDateTime; - total <<= 32; - total |= ft.dwLowDateTime; - /* measurement interval is 100 nanoseconds = 1/10 microseconds */ - /* adjust by number of seconds between Windows (1601) and Unix (1970) epochs */ - tp->tv_sec = (time_t)(total / 10000000 - 11644473600L); - tp->tv_nsec = (long)((total % 10000000) * 100); - break; - } - - default: - S_error1("S_gettime", "unexpected typeno ~s", Sinteger(typeno)); - break; - } -} - -static struct tm *gmtime_r(const time_t *timep, struct tm *result) { - return gmtime_s(result, timep) == 0 ? result : NULL; -} - -static struct tm *localtime_r(const time_t *timep, struct tm *result) { - return localtime_s(result, timep) == 0 ? result : NULL; -} - -static char *ctime_r(const time_t *timep, char *buf) { - return ctime_s(buf, 26, timep) == 0 ? buf : NULL; -} - -static char *asctime_r(const struct tm *tm, char *buf) { - return asctime_s(buf, 26, tm) == 0 ? buf : NULL; -} - -#else /* WIN32 */ - -void S_gettime(INT typeno, struct timespec *tp) { - switch (typeno) { - case time_thread: -#ifdef CLOCK_THREAD_CPUTIME_ID - if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, tp) == 0) return; -#endif - /* fall through */ - /* to utc case in case no thread timer */ - case time_process: -#ifdef CLOCK_PROCESS_CPUTIME_ID - if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, tp) == 0) return; -#endif - /* fall back on getrusage if clock_gettime fails */ - { - struct rusage rbuf; - - if (getrusage(RUSAGE_SELF,&rbuf) != 0) - S_error1("S_gettime", "failed: ~s", S_strerror(errno)); - tp->tv_sec = rbuf.ru_utime.tv_sec + rbuf.ru_stime.tv_sec; - tp->tv_nsec = (rbuf.ru_utime.tv_usec + rbuf.ru_stime.tv_usec) * 1000; - if (tp->tv_nsec >= 1000000000) { - tp->tv_sec += 1; - tp->tv_nsec -= 1000000000; - } - return; - } - case time_duration: - case time_monotonic: -#ifdef CLOCK_MONOTONIC_HR - if (clock_gettime(CLOCK_MONOTONIC_HR, tp) == 0) return; -#endif -#ifdef CLOCK_MONOTONIC - if (clock_gettime(CLOCK_MONOTONIC, tp) == 0) return; -#endif -#ifdef CLOCK_HIGHRES - if (clock_gettime(CLOCK_HIGHRES, tp) == 0) return; -#endif - /* fall through */ - /* to utc case in case no monotonic timer */ - case time_utc: -#ifdef CLOCK_REALTIME_HR - if (clock_gettime(CLOCK_REALTIME_HR, tp) == 0) return; -#endif -#ifdef CLOCK_REALTIME - if (clock_gettime(CLOCK_REALTIME, tp) == 0) return; -#endif - /* fall back on gettimeofday if clock_gettime fails */ - { - struct timeval tvtp; - - if (gettimeofday(&tvtp,NULL) != 0) - S_error1("S_gettime", "failed: ~s", S_strerror(errno)); - tp->tv_sec = (time_t)tvtp.tv_sec; - tp->tv_nsec = (long)(tvtp.tv_usec * 1000); - return; - } - default: - S_error1("S_gettime", "unexpected typeno ~s", Sinteger(typeno)); - break; - } -} - -#endif /* WIN32 */ - -ptr S_clock_gettime(I32 typeno) { - struct timespec tp; - time_t sec; I32 nsec; - - S_gettime(typeno, &tp); - - sec = tp.tv_sec; - nsec = tp.tv_nsec; - - if (typeno == time_monotonic || typeno == time_duration) { - sec -= starting_mono_tp.tv_sec; - nsec -= starting_mono_tp.tv_nsec; - if (nsec < 0) { - sec -= 1; - nsec += 1000000000; - } - } - - return Scons(S_integer_time_t(sec), Sinteger(nsec)); -} - -ptr S_gmtime(ptr tzoff, ptr tspair) { - time_t tx; - struct tm tmx; - ptr dtvec = S_vector(dtvec_size); - - if (tspair == Sfalse) { - struct timespec tp; - - S_gettime(time_utc, &tp); - tx = tp.tv_sec; - INITVECTIT(dtvec, dtvec_nsec) = Sinteger(tp.tv_nsec); - } else { - tx = Sinteger_value(Scar(tspair)); - INITVECTIT(dtvec, dtvec_nsec) = Scdr(tspair); - } - - if (tzoff == Sfalse) { - if (localtime_r(&tx, &tmx) == NULL) return Sfalse; - tmx.tm_isdst = -1; /* have mktime determine the DST status */ - if (mktime(&tmx) == (time_t)-1) return Sfalse; - (void) adjust_time_zone(dtvec, &tmx, Sfalse); - } else { - tx += Sinteger_value(tzoff); - if (gmtime_r(&tx, &tmx) == NULL) return Sfalse; - INITVECTIT(dtvec, dtvec_tzoff) = tzoff; - INITVECTIT(dtvec, dtvec_isdst) = Sfalse; - INITVECTIT(dtvec, dtvec_tzname) = Sfalse; - } - - INITVECTIT(dtvec, dtvec_sec) = Sinteger(tmx.tm_sec); - INITVECTIT(dtvec, dtvec_min) = Sinteger(tmx.tm_min); - INITVECTIT(dtvec, dtvec_hour) = Sinteger(tmx.tm_hour); - INITVECTIT(dtvec, dtvec_mday) = Sinteger(tmx.tm_mday); - INITVECTIT(dtvec, dtvec_mon) = Sinteger(tmx.tm_mon + 1); - INITVECTIT(dtvec, dtvec_year) = Sinteger(tmx.tm_year); - INITVECTIT(dtvec, dtvec_wday) = Sinteger(tmx.tm_wday); - INITVECTIT(dtvec, dtvec_yday) = Sinteger(tmx.tm_yday); - - return dtvec; -} - -ptr S_asctime(ptr dtvec) { - char buf[26]; - - if (dtvec == Sfalse) { - time_t tx = time(NULL); - if (ctime_r(&tx, buf) == NULL) return Sfalse; - } else { - struct tm tmx; - tmx.tm_sec = (int)Sinteger_value(Svector_ref(dtvec, dtvec_sec)); - tmx.tm_min = (int)Sinteger_value(Svector_ref(dtvec, dtvec_min)); - tmx.tm_hour = (int)Sinteger_value(Svector_ref(dtvec, dtvec_hour)); - tmx.tm_mday = (int)Sinteger_value(Svector_ref(dtvec, dtvec_mday)); - tmx.tm_mon = (int)Sinteger_value(Svector_ref(dtvec, dtvec_mon)) - 1; - tmx.tm_year = (int)Sinteger_value(Svector_ref(dtvec, dtvec_year)); - tmx.tm_wday = (int)Sinteger_value(Svector_ref(dtvec, dtvec_wday)); - tmx.tm_yday = (int)Sinteger_value(Svector_ref(dtvec, dtvec_yday)); - tmx.tm_isdst = (int)Sboolean_value(Svector_ref(dtvec, dtvec_isdst)); - if (asctime_r(&tmx, buf) == NULL) return Sfalse; - } - - return S_string(buf, 24) /* all but trailing newline */; -} - -ptr S_mktime(ptr dtvec) { - time_t tx; - struct tm tmx; - long orig_tzoff, tzoff; - ptr given_tzoff; - - tmx.tm_sec = (int)Sinteger_value(Svector_ref(dtvec, dtvec_sec)); - tmx.tm_min = (int)Sinteger_value(Svector_ref(dtvec, dtvec_min)); - tmx.tm_hour = (int)Sinteger_value(Svector_ref(dtvec, dtvec_hour)); - tmx.tm_mday = (int)Sinteger_value(Svector_ref(dtvec, dtvec_mday)); - tmx.tm_mon = (int)Sinteger_value(Svector_ref(dtvec, dtvec_mon)) - 1; - tmx.tm_year = (int)Sinteger_value(Svector_ref(dtvec, dtvec_year)); - - given_tzoff = INITVECTIT(dtvec, dtvec_tzoff); - if (given_tzoff == Sfalse) - orig_tzoff = 0; - else - orig_tzoff = (long)UNFIX(given_tzoff); - - tmx.tm_isdst = -1; /* have mktime determine the DST status */ - if ((tx = mktime(&tmx)) == (time_t)-1) return Sfalse; - - /* mktime may have normalized some values, set wday and yday */ - INITVECTIT(dtvec, dtvec_sec) = Sinteger(tmx.tm_sec); - INITVECTIT(dtvec, dtvec_min) = Sinteger(tmx.tm_min); - INITVECTIT(dtvec, dtvec_hour) = Sinteger(tmx.tm_hour); - INITVECTIT(dtvec, dtvec_mday) = Sinteger(tmx.tm_mday); - INITVECTIT(dtvec, dtvec_mon) = Sinteger(tmx.tm_mon + 1); - INITVECTIT(dtvec, dtvec_year) = Sinteger(tmx.tm_year); - INITVECTIT(dtvec, dtvec_wday) = Sinteger(tmx.tm_wday); - INITVECTIT(dtvec, dtvec_yday) = Sinteger(tmx.tm_yday); - - tzoff = adjust_time_zone(dtvec, &tmx, given_tzoff); - - if (tzoff != orig_tzoff) tx = tx - orig_tzoff + tzoff; - - return Scons(S_integer_time_t(tx), Svector_ref(dtvec, dtvec_nsec)); -} - -static long adjust_time_zone(ptr dtvec, struct tm *tmxp, ptr given_tzoff) { - ptr tz_name = Sfalse; - long use_tzoff, tzoff; - -#ifdef WIN32 - { - TIME_ZONE_INFORMATION tz; - wchar_t *w_tzname; - - /* The ...ForYear() function is available on Windows Vista and later: */ - GetTimeZoneInformationForYear(tmxp->tm_year, NULL, &tz); - - if (tmxp->tm_isdst) { - tzoff = (tz.Bias + tz.DaylightBias) * -60; - w_tzname = tz.DaylightName; - } else { - tzoff = (tz.Bias + tz.StandardBias) * -60; - w_tzname = tz.StandardName; - } - - if (given_tzoff == Sfalse) { - char *name = Swide_to_utf8(w_tzname); - tz_name = Sstring_utf8(name, -1); - free(name); - } - } -#else - tzoff = tmxp->tm_gmtoff; - if (given_tzoff == Sfalse) { -# if defined(__linux__) || defined(SOLARIS) - /* Linux and Solaris set `tzname`: */ - tz_name = Sstring_utf8(tzname[tmxp->tm_isdst], -1); -# else - /* BSD variants add `tm_zone` in `struct tm`: */ - tz_name = Sstring_utf8(tmxp->tm_zone, -1); -# endif - } -#endif - - if (given_tzoff == Sfalse) - use_tzoff = tzoff; - else - use_tzoff = (long)UNFIX(given_tzoff); - - INITVECTIT(dtvec, dtvec_isdst) = ((given_tzoff == Sfalse) ? Sboolean(tmxp->tm_isdst) : Sfalse); - INITVECTIT(dtvec, dtvec_tzoff) = FIX(use_tzoff); - INITVECTIT(dtvec, dtvec_tzname) = tz_name; - - return tzoff; -} - -/******** old real-time and cpu-time support ********/ - -ptr S_cputime(void) { - struct timespec tp; - - S_gettime(time_process, &tp); - return S_add(S_mul(S_integer_time_t(tp.tv_sec), FIX(1000)), - Sinteger((tp.tv_nsec + 500000) / 1000000)); -} - -ptr S_realtime(void) { - struct timespec tp; - time_t sec; I32 nsec; - - S_gettime(time_monotonic, &tp); - - sec = tp.tv_sec - starting_mono_tp.tv_sec; - nsec = tp.tv_nsec - starting_mono_tp.tv_nsec; - if (nsec < 0) { - sec -= 1; - nsec += 1000000000; - } - return S_add(S_mul(S_integer_time_t(sec), FIX(1000)), - Sinteger((nsec + 500000) / 1000000)); -} - -/******** initialization ********/ - -void S_stats_init(void) { -#ifdef WIN32 - /* Use GetSystemTimePreciseAsFileTime when available (Windows 8 and later). */ - HMODULE h = LoadLibraryW(L"kernel32.dll"); - if (h != NULL) { - GetSystemTimeAsFileTime_t proc = (GetSystemTimeAsFileTime_t)GetProcAddress(h, "GetSystemTimePreciseAsFileTime"); - if (proc != NULL) - s_GetSystemTimeAsFileTime = proc; - else - FreeLibrary(h); - } -#endif - S_gettime(time_monotonic, &starting_mono_tp); -} diff --git a/ta6ob/c/stats.o b/ta6ob/c/stats.o deleted file mode 100644 index d4dfdeb..0000000 Binary files a/ta6ob/c/stats.o and /dev/null differ diff --git a/ta6ob/c/symbol.c b/ta6ob/c/symbol.c deleted file mode 100644 index 0e1c2c6..0000000 --- a/ta6ob/c/symbol.c +++ /dev/null @@ -1,28 +0,0 @@ -/* symbol.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" - -ptr S_symbol_value(ptr sym) { - if (SYMVAL(sym) == sunbound) - S_error1("","~s is not bound", sym); - return SYMVAL(sym); -} - -void S_set_symbol_value(ptr sym, ptr val) { - SETSYMVAL(sym, val); - SETSYMCODE(sym, Sprocedurep(val) ? CLOSCODE(val) : S_G.nonprocedure_code); -} diff --git a/ta6ob/c/symbol.o b/ta6ob/c/symbol.o deleted file mode 100644 index 7b17dde..0000000 Binary files a/ta6ob/c/symbol.o and /dev/null differ diff --git a/ta6ob/c/system.h b/ta6ob/c/system.h deleted file mode 100644 index 868708b..0000000 --- a/ta6ob/c/system.h +++ /dev/null @@ -1,47 +0,0 @@ -/* system.h - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "scheme.h" -#include "equates.h" -#ifdef FEATURE_WINDOWS -#ifdef __MINGW32__ -# undef WINVER -# undef _WIN32_WINNT -#endif -#define WINVER 0x0601 // Windows 7 -#define _WIN32_WINNT WINVER -#include -#endif - -#include "version.h" -#include -#include - -#include "thread.h" - -#include "types.h" - -#include "compress-io.h" - -#ifndef EXTERN -#define EXTERN extern -#endif -#include "globals.h" - -#include "externs.h" - -#include "segment.h" - diff --git a/ta6ob/c/thread.c b/ta6ob/c/thread.c deleted file mode 100644 index e836aee..0000000 --- a/ta6ob/c/thread.c +++ /dev/null @@ -1,470 +0,0 @@ -/* thread.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "system.h" - -/* locally defined functions */ -#ifdef PTHREADS -static s_thread_rv_t start_thread(void *tc); -static IBOOL destroy_thread(ptr tc); -#endif - -void S_thread_init(void) { - if (S_boot_time) { - S_protect(&S_G.threadno); - S_G.threadno = FIX(0); - -#ifdef PTHREADS - /* this is also reset in scheme.c after heap restoration */ - s_thread_mutex_init(&S_tc_mutex.pmutex); - S_tc_mutex.owner = s_thread_self(); - S_tc_mutex.count = 0; - s_thread_cond_init(&S_collect_cond); - S_tc_mutex_depth = 0; -#endif /* PTHREADS */ - } -} - -/* this needs to be reworked. currently, S_create_thread_object is - called from main to create the base thread, from fork_thread when - there is already an active current thread, and from S_activate_thread - when there is no current thread. we have to avoid thread-local - allocation in at least the latter case, so we call vector_in and - cons_in and arrange for S_thread to use find_room rather than - thread_find_room. scheme.c does part of the initialization of the - base thread (e.g., parameters, current input/output ports) in one - or more places. */ -ptr S_create_thread_object(const char *who, ptr p_tc) { - ptr thread, tc; - INT i; - - tc_mutex_acquire() - - if (S_threads == Snil) { - tc = (ptr)S_G.thread_context; - } else { /* clone parent */ - ptr p_v = PARAMETERS(p_tc); - iptr i, n = Svector_length(p_v); - /* use S_vector_in to avoid thread-local allocation */ - ptr v = S_vector_in(space_new, 0, n); - - tc = (ptr)malloc(size_tc); - if (tc == (ptr)0) - S_error(who, "unable to malloc thread data structure"); - memcpy((void *)tc, (void *)p_tc, size_tc); - - for (i = 0; i < n; i += 1) - INITVECTIT(v, i) = Svector_ref(p_v, i); - - PARAMETERS(tc) = v; - CODERANGESTOFLUSH(tc) = Snil; - } - - /* override nonclonable tc fields */ - THREADNO(tc) = S_G.threadno; - S_G.threadno = S_add(S_G.threadno, FIX(1)); - - CCHAIN(tc) = Snil; - - WINDERS(tc) = Snil; - STACKLINK(tc) = SYMVAL(S_G.null_continuation_id); - STACKCACHE(tc) = Snil; - - /* S_reset_scheme_stack initializes stack, size, esp, and sfp */ - S_reset_scheme_stack(tc, stack_slop); - FRAME(tc,0) = (ptr)&CODEIT(S_G.dummy_code_object,size_rp_header); - - /* S_reset_allocation_pointer initializes ap and eap */ - S_reset_allocation_pointer(tc); - RANDOMSEED(tc) = most_positive_fixnum < 0xffffffff ? most_positive_fixnum : 0xffffffff; - X(tc) = Y(tc) = U(tc) = V(tc) = W(tc) = FIX(0); - - TIMERTICKS(tc) = Sfalse; - DISABLECOUNT(tc) = Sfixnum(0); - SIGNALINTERRUPTPENDING(tc) = Sfalse; - SIGNALINTERRUPTQUEUE(tc) = S_allocate_scheme_signal_queue(); - KEYBOARDINTERRUPTPENDING(tc) = Sfalse; - - TARGETMACHINE(tc) = S_intern((const unsigned char *)MACHINE_TYPE); - - /* choosing not to clone virtual registers */ - for (i = 0 ; i < virtual_register_count ; i += 1) { - VIRTREG(tc, i) = FIX(0); - } - - DSTBV(tc) = SRCBV(tc) = Sfalse; - - /* S_thread had better not do thread-local allocation */ - thread = S_thread(tc); - - /* use S_cons_in to avoid thread-local allocation */ - S_threads = S_cons_in(space_new, 0, thread, S_threads); - S_nthreads += 1; - SETSYMVAL(S_G.active_threads_id, - FIX(UNFIX(SYMVAL(S_G.active_threads_id)) + 1)); - ACTIVE(tc) = 1; - - /* collect request is only thing that can be pending for new thread. - must do this after we're on the thread list in case the cons - adding us onto the thread list set collect-request-pending */ - SOMETHINGPENDING(tc) = SYMVAL(S_G.collect_request_pending_id); - - GUARDIANENTRIES(tc) = Snil; - - LZ4OUTBUFFER(tc) = NULL; - - tc_mutex_release() - - return thread; -} - -#ifdef PTHREADS -IBOOL Sactivate_thread(void) { /* create or reactivate current thread */ - ptr tc = get_thread_context(); - - if (tc == (ptr)0) { /* thread created by someone else */ - ptr thread; - - /* borrow base thread for now */ - thread = S_create_thread_object("Sactivate_thread", S_G.thread_context); - s_thread_setspecific(S_tc_key, (ptr)THREADTC(thread)); - return 1; - } else { - reactivate_thread(tc) - return 0; - } -} - -int S_activate_thread(void) { /* Like Sactivate_thread(), but returns a mode to revert the effect */ - ptr tc = get_thread_context(); - - if (tc == (ptr)0) { - Sactivate_thread(); - return unactivate_mode_destroy; - } else if (!ACTIVE(tc)) { - reactivate_thread(tc); - return unactivate_mode_deactivate; - } else - return unactivate_mode_noop; -} - -void S_unactivate_thread(int mode) { /* Reverts a previous S_activate_thread() effect */ - switch (mode) { - case unactivate_mode_deactivate: - Sdeactivate_thread(); - break; - case unactivate_mode_destroy: - Sdestroy_thread(); - break; - case unactivate_mode_noop: - default: - break; - } -} - -void Sdeactivate_thread(void) { /* deactivate current thread */ - ptr tc = get_thread_context(); - if (tc != (ptr)0) deactivate_thread(tc) -} - -int Sdestroy_thread(void) { /* destroy current thread */ - ptr tc = get_thread_context(); - if (tc != (ptr)0 && destroy_thread(tc)) { - s_thread_setspecific(S_tc_key, 0); - return 1; - } - return 0; -} - -static IBOOL destroy_thread(ptr tc) { - ptr *ls; IBOOL status; - - status = 0; - tc_mutex_acquire() - ls = &S_threads; - while (*ls != Snil) { - ptr thread = Scar(*ls); - if (THREADTC(thread) == (uptr)tc) { - *ls = Scdr(*ls); - S_nthreads -= 1; - - /* process remembered set before dropping allocation area */ - S_scan_dirty((ptr **)EAP(tc), (ptr **)REAL_EAP(tc)); - - /* process guardian entries */ - { - ptr target, ges, obj, next; seginfo *si; - target = S_G.guardians[0]; - for (ges = GUARDIANENTRIES(tc); ges != Snil; ges = next) { - obj = GUARDIANOBJ(ges); - next = GUARDIANNEXT(ges); - if (!IMMEDIATE(obj) && (si = MaybeSegInfo(ptr_get_segment(obj))) != NULL && si->generation != static_generation) { - INITGUARDIANNEXT(ges) = target; - target = ges; - } - } - S_G.guardians[0] = target; - } - - /* deactivate thread */ - if (ACTIVE(tc)) { - SETSYMVAL(S_G.active_threads_id, - FIX(UNFIX(SYMVAL(S_G.active_threads_id)) - 1)); - if (Sboolean_value(SYMVAL(S_G.collect_request_pending_id)) - && SYMVAL(S_G.active_threads_id) == FIX(0)) { - s_thread_cond_signal(&S_collect_cond); - } - } - - if (LZ4OUTBUFFER(tc) != NULL) free(LZ4OUTBUFFER(tc)); - if (SIGNALINTERRUPTQUEUE(tc) != NULL) free(SIGNALINTERRUPTQUEUE(tc)); - - free((void *)tc); - THREADTC(thread) = 0; /* mark it dead */ - status = 1; - break; - } - ls = &Scdr(*ls); - } - tc_mutex_release() - return status; -} - -ptr S_fork_thread(ptr thunk) { - ptr thread; - int status; - - /* pass the current thread's context as the parent thread */ - thread = S_create_thread_object("fork-thread", get_thread_context()); - CP(THREADTC(thread)) = thunk; - - if ((status = s_thread_create(start_thread, (void *)THREADTC(thread))) != 0) { - destroy_thread((ptr)THREADTC(thread)); - S_error1("fork-thread", "failed: ~a", S_strerror(status)); - } - - return thread; -} - -static s_thread_rv_t start_thread(p) void *p; { - ptr tc = (ptr)p; ptr cp; - - s_thread_setspecific(S_tc_key, tc); - - cp = CP(tc); - CP(tc) = Svoid; /* should hold calling code object, which we don't have */ - TRAP(tc) = (ptr)default_timer_ticks; - Scall0(cp); - /* caution: calling into Scheme may result into a collection, so we - can't access any Scheme objects, e.g., cp, after this point. But tc - is static, so we can access it. */ - - /* find and destroy our thread */ - destroy_thread(tc); - s_thread_setspecific(S_tc_key, (ptr)0); - - s_thread_return; -} - - -scheme_mutex_t *S_make_mutex() { - scheme_mutex_t *m; - - m = (scheme_mutex_t *)malloc(sizeof(scheme_mutex_t)); - - if (m == (scheme_mutex_t *)0) - S_error("make-mutex", "unable to malloc mutex"); - s_thread_mutex_init(&m->pmutex); - m->owner = s_thread_self(); - m->count = 0; - - return m; -} - -void S_mutex_free(scheme_mutex_t *m) { - s_thread_mutex_destroy(&m->pmutex); - free(m); -} - -void S_mutex_acquire(scheme_mutex_t *m) { - s_thread_t self = s_thread_self(); - iptr count; - INT status; - - if ((count = m->count) > 0 && s_thread_equal(m->owner, self)) { - if (count == most_positive_fixnum) - S_error1("mutex-acquire", "recursion limit exceeded for ~s", m); - m->count = count + 1; - return; - } - - if ((status = s_thread_mutex_lock(&m->pmutex)) != 0) - S_error1("mutex-acquire", "failed: ~a", S_strerror(status)); - m->owner = self; - m->count = 1; -} - -INT S_mutex_tryacquire(scheme_mutex_t *m) { - s_thread_t self = s_thread_self(); - iptr count; - INT status; - - if ((count = m->count) > 0 && s_thread_equal(m->owner, self)) { - if (count == most_positive_fixnum) - S_error1("mutex-acquire", "recursion limit exceeded for ~s", m); - m->count = count + 1; - return 0; - } - - status = s_thread_mutex_trylock(&m->pmutex); - if (status == 0) { - m->owner = self; - m->count = 1; - } else if (status != EBUSY) { - S_error1("mutex-acquire", "failed: ~a", S_strerror(status)); - } - return status; -} - -void S_mutex_release(scheme_mutex_t *m) { - s_thread_t self = s_thread_self(); - iptr count; - INT status; - - if ((count = m->count) == 0 || !s_thread_equal(m->owner, self)) - S_error1("mutex-release", "thread does not own mutex ~s", m); - - if ((m->count = count - 1) == 0) - if ((status = s_thread_mutex_unlock(&m->pmutex)) != 0) - S_error1("mutex-release", "failed: ~a", S_strerror(status)); -} - -s_thread_cond_t *S_make_condition() { - s_thread_cond_t *c; - - c = (s_thread_cond_t *)malloc(sizeof(s_thread_cond_t)); - if (c == (s_thread_cond_t *)0) - S_error("make-condition", "unable to malloc condition"); - s_thread_cond_init(c); - return c; -} - -void S_condition_free(s_thread_cond_t *c) { - s_thread_cond_destroy(c); - free(c); -} - -#ifdef FEATURE_WINDOWS - -static inline int s_thread_cond_timedwait(s_thread_cond_t *cond, s_thread_mutex_t *mutex, int typeno, I64 sec, long nsec) { - if (typeno == time_utc) { - struct timespec now; - S_gettime(time_utc, &now); - sec -= now.tv_sec; - nsec -= now.tv_nsec; - if (nsec < 0) { - sec -= 1; - nsec += 1000000000; - } - } - if (sec < 0) { - sec = 0; - nsec = 0; - } - if (SleepConditionVariableCS(cond, mutex, (DWORD)(sec*1000 + (nsec+500000)/1000000))) { - return 0; - } else if (GetLastError() == ERROR_TIMEOUT) { - return ETIMEDOUT; - } else { - return EINVAL; - } -} - -#else /* FEATURE_WINDOWS */ - -static inline int s_thread_cond_timedwait(s_thread_cond_t *cond, s_thread_mutex_t *mutex, int typeno, I64 sec, long nsec) { - struct timespec t; - if (typeno == time_duration) { - struct timespec now; - S_gettime(time_utc, &now); - t.tv_sec = (time_t)(now.tv_sec + sec); - t.tv_nsec = now.tv_nsec + nsec; - if (t.tv_nsec >= 1000000000) { - t.tv_sec += 1; - t.tv_nsec -= 1000000000; - } - } else { - t.tv_sec = sec; - t.tv_nsec = nsec; - } - return pthread_cond_timedwait(cond, mutex, &t); -} - -#endif /* FEATURE_WINDOWS */ - -#define Srecord_ref(x,i) (((ptr *)((uptr)(x)+record_data_disp))[i]) - -IBOOL S_condition_wait(s_thread_cond_t *c, scheme_mutex_t *m, ptr t) { - ptr tc = get_thread_context(); - s_thread_t self = s_thread_self(); - iptr count; - INT typeno; - I64 sec; - long nsec; - INT status; - - if ((count = m->count) == 0 || !s_thread_equal(m->owner, self)) - S_error1("condition-wait", "thread does not own mutex ~s", m); - - if (count != 1) - S_error1("condition-wait", "mutex ~s is recursively locked", m); - - if (t != Sfalse) { - /* Keep in sync with ts record in s/date.ss */ - typeno = Sinteger32_value(Srecord_ref(t,0)); - sec = Sinteger64_value(Scar(Srecord_ref(t,1))); - nsec = Sinteger32_value(Scdr(Srecord_ref(t,1))); - } else { - typeno = 0; - sec = 0; - nsec = 0; - } - - if (c == &S_collect_cond || DISABLECOUNT(tc) == 0) { - deactivate_thread(tc) - } - - m->count = 0; - status = (t == Sfalse) ? s_thread_cond_wait(c, &m->pmutex) : - s_thread_cond_timedwait(c, &m->pmutex, typeno, sec, nsec); - m->owner = self; - m->count = 1; - - if (c == &S_collect_cond || DISABLECOUNT(tc) == 0) { - reactivate_thread(tc) - } - - if (status == 0) { - return 1; - } else if (status == ETIMEDOUT) { - return 0; - } else { - S_error1("condition-wait", "failed: ~a", S_strerror(status)); - return 0; - } -} -#endif /* PTHREADS */ - diff --git a/ta6ob/c/thread.h b/ta6ob/c/thread.h deleted file mode 100644 index 1d4515e..0000000 --- a/ta6ob/c/thread.h +++ /dev/null @@ -1,91 +0,0 @@ -/* thread.h - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef FEATURE_PTHREADS -#ifdef FEATURE_WINDOWS - -#include -#include - -/* learned from http://locklessinc.com/articles/pthreads_on_windows/ which - * Windows API types and functions to use to support mutexes and condition - * variables. there's much more information there if we ever need a more - * complete implementation of pthreads functionality. - */ - -typedef DWORD s_thread_t; -typedef DWORD s_thread_key_t; -typedef CRITICAL_SECTION s_thread_mutex_t; -typedef CONDITION_VARIABLE s_thread_cond_t; -typedef void s_thread_rv_t; -#define s_thread_return return -#define s_thread_self() GetCurrentThreadId() -#define s_thread_equal(t1, t2) ((t1) == (t2)) -/* CreateThread description says to use _beginthread if thread uses the C library */ -#define s_thread_create(start_routine, arg) (_beginthread(start_routine, 0, arg) == -1 ? EAGAIN : 0) -#define s_thread_key_create(key) ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES ? EAGAIN : 0) -#define s_thread_key_delete(key) (TlsFree(key) == 0 ? EINVAL : 0) -#define s_thread_getspecific(key) TlsGetValue(key) -#define s_thread_setspecific(key, value) (TlsSetValue(key, (void *)value) == 0 ? EINVAL : 0) -#define s_thread_mutex_init(mutex) InitializeCriticalSection(mutex) -#define s_thread_mutex_lock(mutex) (EnterCriticalSection(mutex), 0) -#define s_thread_mutex_unlock(mutex) (LeaveCriticalSection(mutex), 0) -#define s_thread_mutex_trylock(mutex) (TryEnterCriticalSection(mutex) ? 0 : EBUSY) -#define s_thread_mutex_destroy(mutex) (DeleteCriticalSection(mutex), 0) -#define s_thread_cond_init(cond) InitializeConditionVariable(cond) -#define s_thread_cond_signal(cond) (WakeConditionVariable(cond), 0) -#define s_thread_cond_broadcast(cond) (WakeAllConditionVariable(cond), 0) -#define s_thread_cond_wait(cond, mutex) (SleepConditionVariableCS(cond, mutex, INFINITE) == 0 ? EINVAL : 0) -#define s_thread_cond_destroy(cond) (0) - -#else /* FEATURE_WINDOWS */ - -#include - -typedef pthread_t s_thread_t; -typedef pthread_key_t s_thread_key_t; -typedef pthread_mutex_t s_thread_mutex_t; -typedef pthread_cond_t s_thread_cond_t; -typedef void *s_thread_rv_t; -#define s_thread_return return NULL -#define s_thread_self() pthread_self() -#define s_thread_equal(t1, t2) pthread_equal(t1, t2) -static inline int s_thread_create(void *(* start_routine)(void *), void *arg) { - pthread_attr_t attr; pthread_t thread; int status; - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - status = pthread_create(&thread, &attr, start_routine, arg); - pthread_attr_destroy(&attr); - return status; -} -#define s_thread_key_create(key) pthread_key_create(key, NULL) -#define s_thread_key_delete(key) pthread_key_delete(key) -#define s_thread_getspecific(key) pthread_getspecific(key) -#define s_thread_setspecific(key, value) pthread_setspecific(key, value) -#define s_thread_mutex_init(mutex) pthread_mutex_init(mutex, NULL) -#define s_thread_mutex_lock(mutex) pthread_mutex_lock(mutex) -#define s_thread_mutex_unlock(mutex) pthread_mutex_unlock(mutex) -#define s_thread_mutex_trylock(mutex) pthread_mutex_trylock(mutex) -#define s_thread_mutex_destroy(mutex) pthread_mutex_destroy(mutex) -#define s_thread_cond_init(cond) pthread_cond_init(cond, NULL) -#define s_thread_cond_signal(cond) pthread_cond_signal(cond) -#define s_thread_cond_broadcast(cond) pthread_cond_broadcast(cond) -#define s_thread_cond_wait(cond, mutex) pthread_cond_wait(cond, mutex) -#define s_thread_cond_destroy(cond) pthread_cond_destroy(cond) - -#endif /* FEATURE_WINDOWS */ -#endif /* FEATURE_PTHREADS */ diff --git a/ta6ob/c/thread.o b/ta6ob/c/thread.o deleted file mode 100644 index 8996060..0000000 Binary files a/ta6ob/c/thread.o and /dev/null differ diff --git a/ta6ob/c/types.h b/ta6ob/c/types.h deleted file mode 100644 index 227f6af..0000000 --- a/ta6ob/c/types.h +++ /dev/null @@ -1,381 +0,0 @@ -/* types.h - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* C datatypes (mostly defined in equates.h or scheme.h) - * ptr: scheme object: (void *) on most platforms - * uptr: unsigned integer sizeof(uptr) == sizeof(ptr): typically unsigned long - * iptr: signed integer sizeof(uptr) == sizeof(ptr): typically long - * I8: 8-bit signed integer: typically char - * I16: 16-bit signed integer: typically short - * I32: 32-bit signed integer: typically int - * U32: 32-bit unsigned integer: typically unsigned int - * I64: 64-bit signed integer: typically long long - * U64: 64-bit unsigned integer: typically unsigned long long - * bigit: unsigned integer sizeof(bigit)*8 == bigit_bits - * bigit: unsigned integer sizeof(bigit)*8 == bigit_bits - */ - -#if (bigit_bits == 32) -typedef U32 bigit; -typedef U64 bigitbigit; -typedef I32 ibigit; -typedef I64 ibigitbigit; -#endif - -/* C signed/unsigned conventions: - * signed/unsigned distinction is felt in comparisons with zero, right - * shifts, multiplies, and divides. - * - * general philosophy is to avoid surprises by using signed quantities, - * with a few exceptions. - * - * use unsigned whenever shifting right. ANSI C >> is undefined for - * negative numbers. if arithmetic shift is desired, divide by the - * appropriate power of two and hope that the C compiler generates a - * shift instruction. - * - * cast to uptr for ptr address computations. this is really necessary - * only when shifting addresses, but we do it all the time since - * addresses are inherently unsigned values. - * - * however, use signed (usually iptr) for lengths and array indices. - * this allows base cases like i < 0 when working backward from the end - * to the front of an array. using uptr would give a slightly larger - * range in theory, but not in practice. - */ - -/* documentary names for ints and unsigned ints */ -typedef int INT; /* honest-to-goodness C int */ -typedef unsigned int UINT; /* honest-to-goodness C unsigned int */ -typedef int ITYPE; /* ptr types */ -typedef int ISPC; /* storage manager spaces */ -typedef int IGEN; /* storage manager generations */ -typedef int IDIRTYBYTE; /* storage manager dirty bytes */ -typedef int IBOOL; /* int used exclusively as a boolean */ -typedef int ICHAR; /* int used exclusively as a character */ -typedef int IFASLCODE; /* fasl type codes */ - -#if (BUFSIZ < 4096) -#define SBUFSIZ 4096 -#else -#define SBUFSIZ BUFSIZ -#endif - -/* inline allocation --- mutex required */ -/* find room allocates n bytes in space s and generation g into - * destination x, tagged with ty, punting to find_more_room if - * no space is left in the current segment. n is assumed to be - * an integral multiple of the object alignment. */ -#define find_room(s, g, t, n, x) {\ - ptr X = S_G.next_loc[g][s];\ - S_G.next_loc[g][s] = (ptr)((uptr)X + (n));\ - if ((S_G.bytes_left[g][s] -= (n)) < 0) X = S_find_more_room(s, g, n, X);\ - (x) = TYPE(X, t);\ -} - -/* thread-local inline allocation --- no mutex required */ -/* thread_find_room allocates n bytes in the local allocation area of - * the thread (hence space new, generation zero) into destination x, tagged - * with type t, punting to find_more_room if no space is left in the current - * allocation area. n is assumed to be an integral multiple of the object - * alignment. */ -#define thread_find_room(tc, t, n, x) {\ - ptr _tc = tc;\ - uptr _ap = (uptr)AP(_tc);\ - if ((uptr)n > ((uptr)EAP(_tc) - _ap)) {\ - (x) = S_get_more_room_help(_tc, _ap, t, n);\ - } else {\ - (x) = TYPE(_ap,t);\ - AP(_tc) = (ptr)(_ap + n);\ - }\ -} - -/* size of protected array used to store roots for the garbage collector */ -#define max_protected 100 - -#define build_ptr(s,o) ((ptr)(((uptr)(s) << segment_offset_bits) | (uptr)(o))) -#define addr_get_segment(p) ((uptr)(p) >> segment_offset_bits) -#define ptr_get_segment(p) (((uptr)(p) + typemod - 1) >> segment_offset_bits) - -#define SPACE(p) SegmentSpace(ptr_get_segment(p)) -#define GENERATION(p) SegmentGeneration(ptr_get_segment(p)) - -#define ptr_align(size) (((size)+byte_alignment-1) & ~(byte_alignment-1)) - -typedef struct _seginfo { - unsigned char space; /* space the segment is in */ - unsigned char generation; /* generation the segment is in */ - unsigned char sorted; /* sorted indicator---possibly to be incorporated into space flags? */ - octet min_dirty_byte; /* dirty byte for full segment, effectively min(dirty_bytes) */ - uptr number; /* the segment number */ - struct _chunkinfo *chunk; /* the chunk this segment belongs to */ - struct _seginfo *next; /* pointer to the next seginfo (used in occupied_segments and unused_segs */ - struct _seginfo **dirty_prev; /* pointer to the next pointer on the previous seginfo in the DirtySegments list */ - struct _seginfo *dirty_next; /* pointer to the next seginfo on the DirtySegments list */ - ptr trigger_ephemerons; /* ephemerons to re-check if object in segment is copied out */ - octet dirty_bytes[cards_per_segment]; /* one dirty byte per card */ -} seginfo; - -typedef struct _chunkinfo { - void *addr; /* chunk starting address */ - iptr base; /* first segment */ - iptr bytes; /* size in bytes */ - iptr segs; /* size in segments */ - iptr nused_segs; /* number of segments currently in used use */ - struct _chunkinfo **prev; /* pointer to previous chunk's next */ - struct _chunkinfo *next; /* next chunk */ - struct _seginfo *unused_segs; /* list of unused segments */ - struct _seginfo sis[0]; /* one seginfo per segment */ -} chunkinfo; - -#ifdef segment_t2_bits -typedef struct _t1table { - seginfo *t1[1<>1)+to_g) -#define DIRTY_SEGMENT_LISTS DIRTY_SEGMENT_INDEX(static_generation, static_generation) - -#define DirtySegments(from_g, to_g) S_G.dirty_segments[DIRTY_SEGMENT_INDEX(from_g, to_g)] - -/* oblist */ - -typedef struct _bucket { - ptr sym; - struct _bucket *next; -} bucket; - -typedef struct _bucket_list { - struct _bucket *car; - struct _bucket_list *cdr; -} bucket_list; - -typedef struct _bucket_pointer_list { - struct _bucket **car; - struct _bucket_pointer_list *cdr; -} bucket_pointer_list; - -/* size macros for variable-sized objects */ - -#define size_vector(n) ptr_align(header_size_vector + (n)*ptr_bytes) -#define size_closure(n) ptr_align(header_size_closure + (n)*ptr_bytes) -#define size_string(n) ptr_align(header_size_string + (n)*string_char_bytes) -#define size_fxvector(n) ptr_align(header_size_fxvector + (n)*ptr_bytes) -#define size_bytevector(n) ptr_align(header_size_bytevector + (n)) -#define size_bignum(n) ptr_align(header_size_bignum + (n)*bigit_bytes) -#define size_code(n) ptr_align(header_size_code + (n)) -#define size_reloc_table(n) ptr_align(header_size_reloc_table + (n)*ptr_bytes) -#define size_record_inst(n) ptr_align(n) -#define unaligned_size_record_inst(n) (n) - -/* type tagging macros */ - -#define TYPE(x,type) ((ptr)((iptr)(x) - typemod + (type))) -#define UNTYPE(x,type) ((ptr)((iptr)(x) + typemod - (type))) -#define UNTYPE_ANY(x) ((ptr)(((iptr)(x) + (typemod - 1)) & ~(typemod - 1))) -#define TYPEBITS(x) ((iptr)(x) & (typemod - 1)) -#define TYPEFIELD(x) (*(ptr *)UNTYPE(x, type_typed_object)) - -#define FIX(x) Sfixnum(x) -#define UNFIX(x) Sfixnum_value(x) - -#define TYPEP(x,mask,type) (((iptr)(x) & (mask)) == (type)) - -/* reloc fields */ -#define RELOC_EXTENDED_FORMAT(x) ((x)&reloc_extended_format) -#define RELOC_TYPE(x) (((x)>>reloc_type_offset)&reloc_type_mask) -#define RELOC_CODE_OFFSET(x) (((x)>>reloc_code_offset_offset)&reloc_code_offset_mask) -#define RELOC_ITEM_OFFSET(x) (((x)>>reloc_item_offset_offset)&reloc_item_offset_mask) -#define MAKE_SHORT_RELOC(ty,co,io) (((ty)< -#define MAKE_NAN(x) { x = sqrt(-1.0); } -#ifndef PATH_MAX -# define PATH_MAX _MAX_PATH -#endif -typedef char *memcpy_t; -struct timespec; -#ifndef __MINGW32__ -# define _setjmp setjmp -# define _longjmp longjmp -# define ftruncate _chsize_s -#endif -#define LOCK_SH 1 -#define LOCK_EX 2 -#define LOCK_NB 4 -#define LOCK_UN 8 -#define FLOCK S_windows_flock -#define DIRMARKERP(c) ((c) == '/' || (c) == '\\') -#define CHDIR S_windows_chdir -#define CHMOD S_windows_chmod -#define CLOSE _close -#define DUP _dup -#define FILENO _fileno -#define FSTAT _fstat64 -#define GETCWD S_windows_getcwd -#define GETPID _getpid -#define HYPOT _hypot -#define LSEEK _lseeki64 -#define LSTAT S_windows_stat64 -#define OFF_T __int64 -#define OPEN S_windows_open -#define READ _read -#define RENAME S_windows_rename -#define RMDIR S_windows_rmdir -#define STAT S_windows_stat64 -#define STATBUF _stat64 -#define SYSTEM S_windows_system -#define UNLINK S_windows_unlink -#define WRITE _write -#define SECATIME(sb) (sb).st_atime -#define SECCTIME(sb) (sb).st_ctime -#define SECMTIME(sb) (sb).st_mtime -#define NSECATIME(sb) 0 -#define NSECCTIME(sb) 0 -#define NSECMTIME(sb) 0 -#define ICONV_INBUF_TYPE char ** -struct timespec; -#define UNUSED -#endif - -#if (machine_type == machine_type_i3ob || machine_type == machine_type_ti3ob || machine_type == machine_type_a6ob || machine_type == machine_type_ta6ob) -#if (machine_type == machine_type_ti3ob || machine_type == machine_type_ta6ob) -#define PTHREADS -#endif -#define NOBLOCK O_NONBLOCK -#define LOAD_SHARED_OBJECT -#define USE_MMAP -#define MMAP_HEAP -#define IEEE_DOUBLE -#define LITTLE_ENDIAN_IEEE_DOUBLE -#define LDEXP -#define ARCHYPERBOLIC -#define GETPAGESIZE() getpagesize() -typedef char *memcpy_t; -struct timespec; -#define MAKE_NAN(x) { x = 0.0; x = x / x; } -#define GETWD(x) getcwd((x),PATH_MAX) -typedef int tputsputcchar; -#define LOCKF -#define DIRMARKERP(c) ((c) == '/') -#ifndef DISABLE_X11 -#define LIBX11 "libX11.so" -#endif -#define SECATIME(sb) (sb).st_atimespec.tv_sec -#define SECCTIME(sb) (sb).st_ctimespec.tv_sec -#define SECMTIME(sb) (sb).st_mtimespec.tv_sec -#define NSECATIME(sb) (sb).st_atimespec.tv_nsec -#define NSECCTIME(sb) (sb).st_ctimespec.tv_nsec -#define NSECMTIME(sb) (sb).st_mtimespec.tv_nsec -#define ICONV_INBUF_TYPE char ** -#define UNUSED __attribute__((__unused__)) -#define USE_OSSP_UUID -#endif - -#if (machine_type == machine_type_i3osx || machine_type == machine_type_ti3osx || machine_type == machine_type_a6osx || machine_type == machine_type_ta6osx) -#if (machine_type == machine_type_ti3osx || machine_type == machine_type_ta6osx) -#define PTHREADS -#endif -#if (machine_type == machine_type_a6osx || machine_type == machine_type_ta6osx) -#ifndef NO_ROSETTA_CHECK -#define CHECK_FOR_ROSETTA -extern int is_rosetta; -#endif -#endif -#define MACOSX -#define NOBLOCK O_NONBLOCK -#define LOAD_SHARED_OBJECT -#define USE_MMAP -#define MMAP_HEAP -#define IEEE_DOUBLE -#define LITTLE_ENDIAN_IEEE_DOUBLE -#define LDEXP -#define ARCHYPERBOLIC -#define GETPAGESIZE() getpagesize() -typedef char *memcpy_t; -#define MAKE_NAN(x) { x = 0.0; x = x / x; } -#define GETWD(x) getcwd((x),PATH_MAX) -typedef int tputsputcchar; -#define LOCKF -#define DIRMARKERP(c) ((c) == '/') -#ifndef DISABLE_X11 -#define LIBX11 "/usr/X11R6/lib/libX11.dylib" -#endif -#define _DARWIN_USE_64_BIT_INODE -#define SECATIME(sb) (sb).st_atimespec.tv_sec -#define SECCTIME(sb) (sb).st_ctimespec.tv_sec -#define SECMTIME(sb) (sb).st_mtimespec.tv_sec -#define NSECATIME(sb) (sb).st_atimespec.tv_nsec -#define NSECCTIME(sb) (sb).st_ctimespec.tv_nsec -#define NSECMTIME(sb) (sb).st_mtimespec.tv_nsec -#define ICONV_INBUF_TYPE char ** -#define UNUSED __attribute__((__unused__)) -#endif - -#if (machine_type == machine_type_i3qnx || machine_type == machine_type_ti3qnx) -#if (machine_type == machine_type_ti3qnx) -#define PTHREADS -#endif -#define NOBLOCK O_NONBLOCK -#define LOAD_SHARED_OBJECT -#define USE_MMAP -#define MMAP_HEAP -#define IEEE_DOUBLE -#define LITTLE_ENDIAN_IEEE_DOUBLE -#define LDEXP -#define ARCHYPERBOLIC -#define GETPAGESIZE() getpagesize() -typedef char *memcpy_t; -#define MAKE_NAN(x) { x = 0.0; x = x / x; } -#define GETWD(x) getcwd((x),PATH_MAX) -typedef int tputsputcchar; -#define LOCKF -#define DIRMARKERP(c) ((c) == '/') -#define LSEEK lseek64 -#define OFF_T off64_t -#define _LARGEFILE64_SOURCE -#define SECATIME(sb) (sb).st_atime -#define SECCTIME(sb) (sb).st_ctime -#define SECMTIME(sb) (sb).st_mtime -#define NSECATIME(sb) 0 -#define NSECCTIME(sb) 0 -#define NSECMTIME(sb) 0 -#define ICONV_INBUF_TYPE char ** -#define NOFILE 256 -#define UNUSED -#endif - -#if (machine_type == machine_type_i3s2 || machine_type == machine_type_ti3s2 || machine_type == machine_type_a6s2 || machine_type == machine_type_ta6s2) -#if (machine_type == machine_type_ti3s2 || machine_type == machine_type_ta6s2) -#define PTHREADS -#endif -#define NOBLOCK O_NONBLOCK -#define LOAD_SHARED_OBJECT -#define USE_MMAP -#define MMAP_HEAP -#define IEEE_DOUBLE -#define LITTLE_ENDIAN_IEEE_DOUBLE -#define LDEXP -#define ARCHYPERBOLIC -#define LOG1P -#define DEFINE_MATHERR -#define GETPAGESIZE() getpagesize() -typedef char *memcpy_t; -#define MAKE_NAN(x) { x = 0.0; x = x / x; } -#define _setjmp setjmp -#define _longjmp longjmp -typedef char tputsputcchar; -#define LOCKF -#define DIRMARKERP(c) ((c) == '/') -#ifndef DISABLE_X11 -#define LIBX11 "libX11.so" -#endif -#define SECATIME(sb) (sb).st_atim.tv_sec -#define SECCTIME(sb) (sb).st_ctim.tv_sec -#define SECMTIME(sb) (sb).st_mtim.tv_sec -#define NSECATIME(sb) (sb).st_atim.tv_nsec -#define NSECCTIME(sb) (sb).st_ctim.tv_nsec -#define NSECMTIME(sb) (sb).st_mtim.tv_nsec -#define ICONV_INBUF_TYPE const char ** -#define UNUSED __attribute__((__unused__)) -#endif - -/* defaults */ - -#ifndef CHDIR -# define CHDIR chdir -#endif -#ifndef CHMOD -# define CHMOD chmod -#endif -#ifndef CLOSE -# define CLOSE close -#endif -#ifndef DUP -# define DUP dup -#endif -#ifndef FILENO -# define FILENO fileno -#endif -#ifndef FSTAT -# define FSTAT fstat -#endif -#ifndef GETPID -# define GETPID getpid -#endif -#ifndef HYPOT -# define HYPOT hypot -#endif -#ifndef OFF_T -# define OFF_T off_t -#endif -#ifndef LSEEK -# define LSEEK lseek -#endif -#ifndef LSTAT -# define LSTAT lstat -#endif -#ifndef OPEN -# define OPEN open -#endif -#ifndef READ -# define READ read -#endif -#ifndef RENAME -# define RENAME rename -#endif -#ifndef RMDIR -# define RMDIR rmdir -#endif -#ifndef STAT -# define STAT stat -#endif -#ifndef STATBUF -# define STATBUF stat -#endif -#ifndef SYSTEM -# define SYSTEM system -#endif -#ifndef UNLINK -# define UNLINK unlink -#endif -#ifndef WRITE -# define WRITE write -#endif diff --git a/ta6ob/examples/Makefile b/ta6ob/examples/Makefile deleted file mode 100644 index 3edfdd0..0000000 --- a/ta6ob/examples/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# Unix make file to compile the examples. -# Compilation is not necessary since the examples may be loaded from -# source, but this gives an example of how to use make for Scheme. -# * To compile files not already compiled, type "make". Only those -# files in the object list below and not yet compiled will be compiled. -# * To compile all files, type "make all". Only those files in the object -# list below will be compiled. -# * To compile one file, say "fumble.ss", type "make fumble.so". The -# file need not be in the object list below. -# * To remove the object files, type "make clean". -# * To print the examples, type "make print". - -src = def.ss edit.ss fact.ss fatfib.ss fft.ss fib.ss freq.ss interpret.ss\ - m4.ss macro.ss matrix.ss object.ss power.ss queue.ss rabbit.ss rsa.ss\ - scons.ss setof.ss socket.ss unify.ss compat.ss ez-grammar-test.ss -obj = ${src:%.ss=%.so} - -Scheme = ../bin/scheme -q - -.SUFFIXES: -.SUFFIXES: .ss .so -.ss.so: ; echo '(time (compile-file "$*"))' | ${Scheme} - -needed: ${obj} - -all: ; echo "(time (for-each compile-file (map symbol->string '(${src}))))" | ${Scheme} - -clean: ; rm -f $(obj) expr.md diff --git a/ta6ob/examples/compat.ss b/ta6ob/examples/compat.ss deleted file mode 100644 index 43ec014..0000000 --- a/ta6ob/examples/compat.ss +++ /dev/null @@ -1,291 +0,0 @@ -;;; compat.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; miscellaneous definitions to make this version compatible -;;; (where possible) with previous versions...and to a small extent with -;;; other versions of scheme and other dialects of lisp as well - -;;; use only those items that you need to avoid introducing accidental -;;; dependencies on other items. - -(define-syntax define! - (syntax-rules () - ((_ x v) (begin (set! x v) 'x)))) - -(define-syntax defrec! - (syntax-rules () - ((_ x v) (define! x (rec x v))))) - -(define-syntax begin0 - (syntax-rules () - ((_ x y ...) (let ((t x)) y ... t)))) - -(define-syntax recur - (syntax-rules () - ((_ f ((i v) ...) e1 e2 ...) - (let f ((i v) ...) e1 e2 ...)))) - -(define-syntax trace-recur - (syntax-rules () - ((_ f ((x v) ...) e1 e2 ...) - (trace-let f ((x v) ...) e1 e2 ...)))) - -(define swap-box! - (lambda (b v) - (if (box? b) - (let ((x (unbox b))) (set-box! b v) x) - (error 'swap-box! "~s is not a box" b)))) - -(define cull - (lambda (pred? ls) - (unless (procedure? pred?) - (error 'cull "~s is not a procedure" pred?)) - (let f ([l ls]) - (cond - [(pair? l) - (if (pred? (car l)) - (cons (car l) (f (cdr l))) - (f (cdr l)))] - [(null? l) '()] - [else (error 'cull "~s is not a proper list" ls)])))) - -(define cull! cull) - -(define mem - (lambda (pred? ls) - (unless (procedure? pred?) - (error 'mem "~s is not a procedure" pred?)) - (let f ([l ls]) - (cond - [(pair? l) (if (pred? (car l)) l (f (cdr l)))] - [(null? l) #f] - [else (error 'mem "~s is not a proper list" ls)])))) - -(define rem - (lambda (pred? ls) - (unless (procedure? pred?) - (error 'rem "~s is not a procedure" pred?)) - (let f ([l ls]) - (cond - [(pair? l) - (if (pred? (car l)) - (f (cdr l)) - (cons (car l) (f (cdr l))))] - [(null? l) '()] - [else (error 'rem "~s is not a proper list" ls)])))) - -(define rem! - (lambda (pred? ls) - (unless (procedure? pred?) - (error 'rem! "~s is not a procedure" pred?)) - (let f ([l ls]) - (cond - [(pair? l) - (if (pred? (car l)) - (f (cdr l)) - (begin - (set-cdr! l (f (cdr l))) - l))] - [(null? l) '()] - [else (error 'rem! "~s is not a proper list" ls)])))) - -(define ass - (lambda (pred? alist) - (unless (procedure? pred?) - (error 'ass "~s is not a procedure" pred?)) - (let loop ([l alist]) - (cond - [(and (pair? l) (pair? (car l))) - (if (pred? (caar l)) - (car l) - (loop (cdr l)))] - [(null? l) #f] - [else (error 'ass "improperly formed alist ~s" alist)])))) - -(define prompt-read - (lambda (fmt . args) - (apply printf fmt args) - (read))) - -(define tree-copy - (rec tree-copy - (lambda (x) - (if (pair? x) - (cons (tree-copy (car x)) (tree-copy (cdr x))) - x)))) - -(define ferror error) - -(define *most-negative-short-integer* (most-negative-fixnum)) -(define *most-positive-short-integer* (most-positive-fixnum)) - -(define *most-negative-fixnum* (most-negative-fixnum)) -(define *most-positive-fixnum* (most-positive-fixnum)) - -(define *eof* (read-char (open-input-string ""))) - -(define short-integer? fixnum?) -(define big-integer? bignum?) -(define ratio? ratnum?) -(define float? flonum?) - -(define bound? top-level-bound?) -(define global-value top-level-value) -(define set-global-value! set-top-level-value!) -(define define-global-value define-top-level-value) -(define symbol-value top-level-value) -(define set-symbol-value! set-top-level-value!) - -(define put putprop) -(define get getprop) - -(define copy-list list-copy) -(define copy-tree tree-copy) -(define copy-string string-copy) -(define copy-vector vector-copy) - -(define intern string->symbol) -(define symbol-name symbol->string) -(define string->uninterned-symbol gensym) -(define make-temp-symbol string->uninterned-symbol) -(define uninterned-symbol? gensym?) -(define temp-symbol? uninterned-symbol?) - -(define compile-eval compile) - -(define closure? procedure?) - -(define =? =) -(define ? >) -(define <=? <=) -(define >=? >=) - -(define float exact->inexact) -(define rational inexact->exact) - -(define char-equal? char=?) -(define char-less? charsyntax-object #'k - (let ((g (gensym))) - `(lambda (,g) - (let ,(parse (datum args) `(cdr ,g)) - ,@(datum forms))))))) - #'(define-syntax name - (lambda (x) - (syntax-case x () - ((k1 . r) - (datum->syntax-object #'k1 - (proc (syntax-object->datum x)))))))))]))) - -(alias define-macro define-macro!) -(alias defmacro define-macro!) - -(define-macro! define-struct! (name . slots) - `(begin - (define ,name - (lambda ,slots - (vector ',name ,@slots))) - (define ,(string->symbol (format "~a?" name)) - (lambda (x) - (and (vector? x) - (= (vector-length x) (1+ ,(length slots))) - (eq? ',name (vector-ref x 0))))) - ,@(\#make-accessors name slots) - ',name)) - -(define \#make-accessors - (lambda (name slots) - (recur f ((n 1) (slots slots)) - (if (not (null? slots)) - (let* - ((afn (string->symbol (format "~a-~a" name (car slots)))) - (sfn (string->symbol (format "~a!" afn)))) - `((define-macro! ,afn (x) `(vector-ref ,x ,,n)) - (define-macro! ,sfn (x v) `(vector-set! ,x ,,n ,v)) - ,@(f (1+ n) (cdr slots)))) - '())))) diff --git a/ta6ob/examples/crepl.c b/ta6ob/examples/crepl.c deleted file mode 100644 index 13a8c1e..0000000 --- a/ta6ob/examples/crepl.c +++ /dev/null @@ -1,86 +0,0 @@ -/* crepl.c - * Copyright 1984-2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* -This is a variant of main.c that implements a Scheme repl in C. -It's not at all useful, but it highlights how to invoke Scheme -without going through Sscheme_start. - -Test in a workarea's examples subdirectory with: - -( cd ../c ; ln -sf ../examples/crepl.c . ) -( cd ../c ; make mainsrc=crepl.c ) -sh -c 'SCHEMEHEAPDIRS=../boot/%m ../bin/scheme' - */ - -#include "scheme.h" -#include -#include - -#define CALL0(who) Scall0(Stop_level_value(Sstring_to_symbol(who))) -#define CALL1(who, arg) Scall1(Stop_level_value(Sstring_to_symbol(who)), arg) - -static void custom_init(void) {} - -int main(int argc, char *argv[]) { - int n, new_argc = 1, ignoreflags = 0; - ptr p; - - Sscheme_init(NULL); - - /* process command-line arguments, registering boot and heap files */ - for (n = 1; n < argc; n += 1) { - if (!ignoreflags && *argv[n] == '-') { - switch (*(argv[n]+1)) { - case '-': /* pass through remaining options */ - if (*(argv[n]+2) != 0) break; - ignoreflags = 1; - continue; - case 'b': /* boot option, expects boot file pathname */ - if (*(argv[n]+2) != 0) break; - if (++n == argc) { - (void) fprintf(stderr,"\n-b option requires argument\n"); - exit(1); - } - Sregister_boot_file(argv[n]); - continue; - default: - break; - } - } - argv[new_argc++] = argv[n]; - } - - /* must call Sscheme_heap after registering boot and heap files - * Sscheme_heap() completes the initialization of the Scheme system - * and loads the boot or heap files. Before loading boot files, - * it calls custom_init(). */ - Sbuild_heap(argv[0], custom_init); - - for (;;) { - CALL1("display", Sstring("* ")); - p = CALL0("read"); - if (Seof_objectp(p)) break; - p = CALL1("eval", p); - if (p != Svoid) CALL1("pretty-print", p); - } - CALL0("newline"); - - /* must call Scheme_deinit after saving the heap and before exiting */ - Sscheme_deinit(); - - exit(0); -} diff --git a/ta6ob/examples/csocket.c b/ta6ob/examples/csocket.c deleted file mode 100644 index f2821ef..0000000 --- a/ta6ob/examples/csocket.c +++ /dev/null @@ -1,103 +0,0 @@ -/*/ csocket.c -R. Kent Dybvig May 1998 -Updated by Jamie Taylor, Sept 2016 -Public Domain -/*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* c_write attempts to write the entire buffer, pushing through - interrupts, socket delays, and partial-buffer writes */ -int c_write(int fd, char *buf, ssize_t start, ssize_t n) { - ssize_t i, m; - - buf += start; - m = n; - while (m > 0) { - if ((i = write(fd, buf, m)) < 0) { - if (errno != EAGAIN && errno != EINTR) - return i; - } else { - m -= i; - buf += i; - } - } - return n; -} - -/* c_read pushes through interrupts and socket delays */ -int c_read(int fd, char *buf, size_t start, size_t n) { - int i; - - buf += start; - for (;;) { - i = read(fd, buf, n); - if (i >= 0) return i; - if (errno != EAGAIN && errno != EINTR) return -1; - } -} - -/* bytes_ready(fd) returns true if there are bytes available - to be read from the socket identified by fd */ -int bytes_ready(int fd) { - int n; - - (void) ioctl(fd, FIONREAD, &n); - return n; -} - -/* socket support */ - -/* do_socket() creates a new AF_UNIX socket */ -int do_socket(void) { - - return socket(AF_UNIX, SOCK_STREAM, 0); -} - -/* do_bind(s, name) binds name to the socket s */ -int do_bind(int s, char *name) { - struct sockaddr_un sun; - int length; - - sun.sun_family = AF_UNIX; - (void) strcpy(sun.sun_path, name); - length = sizeof(sun.sun_family) + sizeof(sun.sun_path); - - return bind(s, (struct sockaddr*)(&sun), length); -} - -/* do_accept accepts a connection on socket s */ -int do_accept(int s) { - struct sockaddr_un sun; - socklen_t length; - - length = sizeof(sun.sun_family) + sizeof(sun.sun_path); - - return accept(s, (struct sockaddr*)(&sun), &length); -} - -/* do_connect initiates a socket connection */ -int do_connect(int s, char *name) { - struct sockaddr_un sun; - int length; - - sun.sun_family = AF_UNIX; - (void) strcpy(sun.sun_path, name); - length = sizeof(sun.sun_family) + sizeof(sun.sun_path); - - return connect(s, (struct sockaddr*)(&sun), length); -} - -/* get_error returns the operating system's error status */ -char* get_error(void) { - extern int errno; - return strerror(errno); -} diff --git a/ta6ob/examples/def.ss b/ta6ob/examples/def.ss deleted file mode 100644 index a39dde2..0000000 --- a/ta6ob/examples/def.ss +++ /dev/null @@ -1,125 +0,0 @@ -;;; def.ss -;;; Copyright (C) 1987 R. Kent Dybvig - -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -;;; Prototype code for definition facility that remembers definitions and -;;; allows you to pretty-print or edit them (using the structure editor -;;; defined in the file "edit.ss"). - -;;; def can be in place of define at top level (i.e., not within a lambda, -;;; let, let*, or letrec body). It saves the source for the definition -;;; as well as performing the defintion. Type (ls-def) for a list of -;;; variables defined this session, and (pp-def variable) to return the -;;; definition of a particular variable. - -;;; Possible exercises/enhancements: -;;; -;;; 1) Write a "dskout" function that pretty-prints the definitions of -;;; all or selected variables defined this session to a file. -;;; -;;; 2) In place of "def", write a modified "load" that remembers where -;;; (that is, in which file) it saw the definition for each variable -;;; defined in a particular session. This would be used instead of -;;; the "def" form. "ls-def" would be similar to what it is now. -;;; "pp-def" could be similar to what it is now, or it could involve -;;; rereading the corresponding file. "ed-def" could invoke the -;;; structure editor and (as an option) print the modified definition -;;; back to the corresponding file, or "ed-def" could invoke a host -;;; editor (such as Unix "vi" or VMS "edit") on the corresponding -;;; source file, with an option to reload. If this tool is smart -;;; enough, it could get around the limitation that definitions use -;;; define at top-level, i.e., (let ([x #f]) (set! foo (lambda () x))) -;;; could be recognized as a definition for foo. - -(define-syntax def - ;; only makes sense for "top level" definitions - (syntax-rules () - [(_ (var . formals) . body) - (begin (define (var . formals) . body) - (insert-def! 'var '(def (var . formals) . body) var) - 'var)] - [(_ var exp) - (begin (define var exp) - (insert-def! 'var '(def var exp) var) - 'var)])) - -(define-syntax pp-def - (syntax-rules (quote) - ; allow var to be unquoted or quoted - [(_ var) (pp-def-help 'var var)] - [(_ 'var) (pp-def-help 'var var)])) - -(define-syntax ed-def - (syntax-rules (quote) - ; allow var to be unquoted or quoted - [(_ var) (ed-def-help 'var var)] - [(_ 'var) (ed-def-help 'var var)])) - - -(define insert-def! #f) ; assigned within the let below -(define ls-def #f) ; assigned within the let below -(define pp-def-help #f) ; assigned within the let below -(define ed-def-help #f) ; assigned within the let below -(let ([defs '()]) - (define tree-copy - (rec tree-copy - (lambda (x) - (if (pair? x) - (cons (tree-copy (car x)) (tree-copy (cdr x))) - x)))) - (set! insert-def! - (lambda (var defn val) - (unless (symbol? var) - (error 'insert-def! "~s is not a symbol" var)) - (let ([a (assq var defs)]) - (if a - (set-cdr! a (cons defn val)) - (set! defs (cons (cons var (cons defn val)) defs)))))) - (set! ls-def - (lambda () - (map car defs))) - (set! pp-def-help - (lambda (var val) - (unless (symbol? var) - (error 'pp-def "~s is not a symbol" var)) - (let ([a (assq var defs)]) - (unless a - (error 'pp-def - "~s has not been defined during this session" - var)) - (unless (eq? (cddr a) val) - (printf "Warning: ~s has been reassigned since definition" - var)) - (cadr a)))) - (set! ed-def-help - (lambda (var val) - (unless (symbol? var) - (error 'ed-def "~s is not a symbol" var)) - (let ([a (assq var defs)]) - (unless a - (error 'ed-def - "~s has not been defined during this session" - var)) - (unless (eq? (cddr a) val) - (printf "Warning: ~s reassigned since last definition" - var)) - ; edit is destructive; the copy allows the defined name to - ; be changed without affecting the old name's definition - (eval (edit (tree-copy (cadr a)))))))) diff --git a/ta6ob/examples/edit.ss b/ta6ob/examples/edit.ss deleted file mode 100644 index 68acd04..0000000 --- a/ta6ob/examples/edit.ss +++ /dev/null @@ -1,464 +0,0 @@ -;;; edit.ss -;;; Copyright (C) 1987 R. Kent Dybvig - -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -;;; This file contains an implementation of a simple interactive structure -;;; editor for Scheme. The editor is invoked with an expression as it's -;;; single argument. It prompts for, reads, and processes editor commands. - -;;; The editor commands recognized are those documented in the Texas -;;; Instruments' PC Scheme manual. They are summarized below. - -;;; Command syntax Action -;;; -;;; q or Quit the editor, returning edited expression. -;;; -;;; p Write the current expression. -;;; -;;; ? Write to level 2, length 10. -;;; -;;; pp Pretty print the current expression. -;;; -;;; ?? Pretty print to level 2, length 10. -;;; -;;; Move to subexpression of current expression -;;; = 0 is the current expression, > 0 -;;; is the numbered subexpression (1 for first, 2 -;;; for second, ...), < 0 is the numbered -;;; subexpression from the right (-1 for last, -2 -;;; for second to last, ...), and = * is the -;;; "last cdr" of the current expression. If -;;; is not 0, the current expression must be a list. -;;; -;;; b Move back to parent expression. -;;; -;;; t Move to top-level expression. -;;; -;;; pr Move to expression on the left (previous). -;;; -;;; n Move to expression on the right (next). -;;; -;;; (f ) Find within or to the right of the current -;;; expression using equal?. -;;; -;;; f or (f) Find of last (f ) command. -;;; -;;; (d ) Delete the expression at position . -;;; -;;; (r ) Replace the expression at position with -;;; . -;;; -;;; (s ) Replace all occurrences of by -;;; within the current expression. -;;; -;;; (dp ) Remove parens from around expression at position -;;; . -;;; -;;; (ap ) Insert parens around expressions from position -;;; through (inclusive). If is -;;; 0 or *, is ignored and may be omitted. -;;; -;;; (ib ) Insert before expression at position . -;;; -;;; (ia ) Insert after expression at position . -;;; -;;; (sb ) Splice before expression at position . -;;; -;;; (sa ) Splice after expression at position . - -;;; Possible exercises/enhancements: -;;; -;;; 1) Implement an infinite undo ("u") command in the editor. This -;;; can be done by creating an "inverse" function for each operation -;;; that causes a side-effect, i.e, a closure that "remembers" the -;;; list cells involved and knows how to put them back the way they -;;; were. An undo (u) variable could then be added to the editor's -;;; main loop; it would be bound to a list containing the set of -;;; registers at the point of the last side-effect (similarly to the -;;; "back" (b) variable) and the undo function for the side-effect. -;;; -;;; 2) Implement an infinite redo ("r") command in the editor. This -;;; can be done by remembering the undo functions and registers for -;;; the undo's since the last non-undo command. -;;; -;;; 3) Handle circular structures better in the editor. Specifically, -;;; modify the find ("f") command so that it always terminates, and -;;; devise a method for printing circular structures with the "p" -;;; and "pp" commands. Cure the bug mentioned in the overview of -;;; the code given later in the file. -;;; -;;; 4) Add a help ("h") command to the editor. This could be as simple -;;; as listing the available commands. -;;; -;;; 5) Make the editor "extensible" via user-defined macros or editor -;;; commands written in Scheme. -;;; -;;; 6) Modify the editor to provide more descriptive error messages that -;;; diagnose the problem and attempt to give some help. For example, -;;; if the editor receives "(r 1)" it might respond with: -;;; "Two few arguments: -;;; Type (r pos exp) to replace the expression at position pos -;;; with the expression exp." -;;; This should be implemented in conjunction with the help command. -;;; Should it be possible to disable such verbose error messages? - -;;; Implementation: -;;; -;;; The main editor loop and many of the help functions operate on a -;;; set of "registers". These registers are described below: -;;; -;;; s The current find object. s is initially #f, and is bound to a -;;; pair containing the find object when the first (f ) command -;;; is seen. The identical f and (f) commands use the saved object. -;;; -;;; p The parent of the current expression. This is initially a list -;;; of one element, the argument to edit. It is updated by various -;;; movement commands. -;;; -;;; i The index of the current expression in the parent (p). This is -;;; initially 0. It is updated by various movement commands. -;;; -;;; b The "back" chain; actually a list containing the registers p, i -;;; and b for the parent of the current expression. It is initially -;;; (). It is updated by various movement commands. -;;; -;;; Bugs: -;;; -;;; When editing a circular structure, it is possible for the editor to -;;; get lost. That is, when the parent node of the current expression -;;; is changed by a command operating on a subexpression of the current -;;; expression, the index for the current expression may become incorrect. -;;; This can result in abnormal termination of the editor. It would be -;;; fairly simple to check for this (in list-ref) and reset the editor, -;;; and it may be possible to use a different set of registers to avoid -;;; the problem altogether. - -(define edit #f) ; assigned within the let expression below -(let () - (define cmdeq? - ;; used to check command syntax - (lambda (cmd pat) - (and (pair? cmd) - (eq? (car cmd) (car pat)) - (let okargs? ([cmd (cdr cmd)] [pat (cdr pat)]) - (if (null? pat) - (null? cmd) - (and (not (null? cmd)) - (okargs? (cdr cmd) (cdr pat)))))))) - (define find - ;; find expression within or to right of current expression - (lambda (s0 p0 i0 b0) - (define check - (lambda (p i b) - (if (equal? (list-ref p i) (car s0)) - (wrlev s0 p i b) - (continue p i b)))) - (define continue - (lambda (p i b) - (let ([e (list-ref p i)]) - (if (atom? e) - (let next ([p p] [i i] [b b]) - (let ([n (maxref p)]) - (if (or (not n) (< i n)) - (check p (+ i 1) b) - (if (null? b) - (search-failed s0 p0 i0 b0) - (apply next b))))) - (check e 0 (list p i b)))))) - (continue p0 i0 b0))) - (define maxref - ;; use "hare and tortoise" algorithm to check for circular lists. - ;; return maximum reference index (zero-based) for a list x. return - ;; -1 for atoms and #f for circular lists. - (lambda (x) - (let f ([hare x] [tortoise x] [n -1]) - (cond - [(atom? hare) n] - [(atom? (cdr hare)) (+ n 1)] - [(eq? (cdr hare) tortoise) #f] - [else (f (cddr hare) (cdr tortoise) (+ n 2))])))) - (define move - ;; move to subexpression specified by x and pass current state to k. - (lambda (x s p i b k) - (cond - [(eqv? x 0) (k s p i b)] - [(eq? x '*) - (let ([m (maxref (list-ref p i))]) - (if m - (k s (list-ref p i) '* (list p i b)) - (invalid-movement s p i b)))] - [(> x 0) - (let ([m (maxref (list-ref p i))] [x (- x 1)]) - (if (or (not m) (>= m x)) - (k s (list-ref p i) x (list p i b)) - (invalid-movement s p i b)))] - [else - (let ([m (maxref (list-ref p i))] [x (- -1 x)]) - (if (and m (>= m x)) - (let ([x (- m x)]) - (k s (list-ref p i) x (list p i b))) - (invalid-movement s p i b)))]))) - (define proper-list? - ;; return #t if x is a proper list. - (lambda (x) - (and (maxref x) - (or (null? x) (null? (cdr (last-pair x))))))) - (define list-ref - ;; reference list ls element i. i may be *, in which case return - ;; the last pair of ls. - (lambda (ls i) - (if (eq? i '*) - (cdr (last-pair ls)) - (car (list-tail ls i))))) - (define list-set! - ;; change element i of ls to x. - (lambda (ls i x) - (if (eq? i '*) - (set-cdr! (last-pair ls) x) - (set-car! (list-tail ls i) x)))) - (define list-cut! - ;; remove element i from ls. - (lambda (ls i) - (let ([a (cons '() ls)]) - (set-cdr! (list-tail a i) (list-tail a (+ i 2))) - (cdr a)))) - (define list-splice! - ;; insert ls2 into ls1 in place of element i. - (lambda (ls1 i ls2) - (let ([a (list-tail ls1 i)]) - (unless (null? (cdr a)) - (set-cdr! (last-pair ls2) (cdr a))) - (set-car! a (car ls2)) - (set-cdr! a (cdr ls2))) - ls1)) - (define list-ap*! - ;; place parens from element i through last pair of ls. - (lambda (ls i) - (let ([a (list-tail ls i)]) - (let ([c (cons (car a) (cdr a))]) - (set-car! a c) - (set-cdr! a '()))) - ls)) - (define list-ap! - ;; place parens from element i0 through element i1. - (lambda (ls i0 i1) - (let ([a (list-tail ls i0)] [b (list-tail ls i1)]) - (let ([c (cons (car a) (cdr a))]) - (set-car! a c) - (if (eq? a b) - (set-cdr! c '()) - (begin (set-cdr! a (cdr b)) - (set-cdr! b '()))))) - ls)) - (define wrlev - ;; write current expression to level 2, length 10 and continue. - (lambda (s p i b) - (parameterize ([print-level 2] [print-length 10]) - (printf "~s~%" (list-ref p i))) - (edit-loop s p i b))) - (define wr - ;; write current expression and continue. - (lambda (s p i b) - (printf "~s~%" (list-ref p i)) - (edit-loop s p i b))) - (define pplev - ;; pretty print current expression to level 2, length 10 and continue. - (lambda (s p i b) - (parameterize ([print-level 2] [print-length 10]) - (pretty-print (list-ref p i))) - (edit-loop s p i b))) - (define pp - ;; pretty print current expression and continue. - (lambda (s p i b) - (pretty-print (list-ref p i)) - (edit-loop s p i b))) - (define not-a-proper-list - ;; complain and continue. - (lambda (s p i b) - (printf "structure is not a proper list~%") - (edit-loop s p i b))) - (define cannot-dp-zero - ;; complain and continue. - (lambda (s p i b) - (printf "cannot remove parens from current expression~%") - (edit-loop s p i b))) - (define pos2-before-pos1 - ;; complain and continue. - (lambda (s p i b) - (printf "second position before first~%") - (edit-loop s p i b))) - (define invalid-movement - ;; complain and continue. - (lambda (s p i b) - (printf "no such position~%") - (edit-loop s p i b))) - (define unrecognized-command-syntax - ;; complain and continue. - (lambda (s p i b) - (printf "unrecognized command syntax~%") - (edit-loop s p i b))) - (define search-failed - ;; complain and continue. - (lambda (s p i b) - (printf "search failed~%") - (edit-loop s p i b))) - (define no-previous-find - ;; complain and continue. - (lambda (s p i b) - (printf "no previous find command~%") - (edit-loop s p i b))) - (define edit-loop - ;; read command and process. - (lambda (s p i b) - (let ([x (begin (printf "edit> ") (read))]) - (cond - [(eof-object? x) (newline)] ; need newline after eof - [(eq? x 'q)] ; do not need newline after q - [(eq? x 'p) (wr s p i b)] - [(eq? x '?) (wrlev s p i b)] - [(eq? x 'pp) (pp s p i b)] - [(eq? x '??) (pplev s p i b)] - [(or (integer? x) (eqv? x '*)) (move x s p i b wrlev)] - [(eq? x 't) - (let f ([p p] [i i] [b b]) - (if (null? b) - (wrlev s p i b) - (apply f b)))] - [(eq? x 'b) - (if (pair? b) - (apply wrlev s b) - (invalid-movement s p i b))] - [(eq? x 'n) - (let ([n (maxref p)]) - (if (and (not (eq? i '*)) (or (not n) (< i n))) - (wrlev s p (+ i 1) b) - (invalid-movement s p i b)))] - [(eq? x 'pr) - (if (and (not (eq? i '*)) (> i 0)) - (wrlev s p (- i 1) b) - (invalid-movement s p i b))] - [(or (eq? x 'f) (cmdeq? x '(f))) - (if s - (find s p i b) - (no-previous-find s p i b))] - [(cmdeq? x '(f x)) - (find (cons (cadr x) '()) p i b)] - [(and (cmdeq? x '(r x x)) - (or (integer? (cadr x)) (eq? (cadr x) '*))) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (list-set! p0 i0 (caddr x)))) - (wrlev s p i b)] - [(cmdeq? x '(s x x)) - (list-set! p i (subst! (caddr x) (cadr x) (list-ref p i))) - (wrlev s p i b)] - [(and (cmdeq? x '(d x)) (eqv? (cadr x) 0)) - (list-set! p i '()) - (wrlev s p i b)] - [(and (cmdeq? x '(d x)) (eq? (cadr x) '*)) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (set-cdr! (last-pair p0) '()) - (wrlev s p i b)))] - [(and (cmdeq? x '(d x)) (integer? (cadr x))) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (list-set! p i (list-cut! p0 i0)) - (wrlev s p i b)))] - [(and (cmdeq? x '(dp x)) (eqv? (cadr x) 0)) - (let ([e (list-ref p i)]) - (if (and (pair? e) (null? (cdr e))) - (begin (list-set! p i (car e)) - (wrlev s p i b)) - (cannot-dp-zero s p i b)))] - [(and (cmdeq? x '(dp x)) - (and (integer? (cadr x)) (not (= (cadr x) 0)))) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (let ([e0 (list-ref p0 i0)]) - (if (or (proper-list? e0) - (and (pair? e0) (eqv? i0 (maxref p0)))) - (begin (if (null? e0) - (list-set! p i (list-cut! p0 i0)) - (list-splice! p0 i0 e0)) - (wrlev s p i b)) - (not-a-proper-list s p i b)))))] - [(and (or (cmdeq? x '(ap x)) (cmdeq? x '(ap x x))) - (memv (cadr x) '(0 *))) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (list-set! p0 i0 (list (list-ref p0 i0))) - (wrlev s p i b)))] - [(and (cmdeq? x '(ap x x)) - (and (integer? (cadr x)) (not (= (cadr x) 0))) - (eq? (caddr x) '*)) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (list-ap*! p0 i0) - (wrlev s p i b)))] - [(and (cmdeq? x '(ap x x)) - (and (integer? (cadr x)) (not (= (cadr x) 0))) - (and (integer? (caddr x)) (not (= (caddr x) 0)))) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (move (caddr x) s p i b - (lambda (s1 p1 i1 b1) - (if (>= i1 i0) - (begin (list-ap! p0 i0 i1) - (wrlev s p i b)) - (pos2-before-pos1 s p i b))))))] - [(and (cmdeq? x '(ib x x)) - (and (integer? (cadr x)) (not (= (cadr x) 0)))) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (list-splice! p0 i0 (list (caddr x) (list-ref p0 i0))) - (wrlev s p i b)))] - [(and (cmdeq? x '(ia x x)) - (and (integer? (cadr x)) (not (= (cadr x) 0)))) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (list-splice! p0 i0 (list (list-ref p0 i0) (caddr x))) - (wrlev s p i b)))] - [(and (cmdeq? x '(sb x x)) - (and (integer? (cadr x)) (not (= (cadr x) 0)))) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (list-splice! p0 i0 - (append (caddr x) (list (list-ref p0 i0)))) - (wrlev s p i b)))] - [(and (cmdeq? x '(sa x x)) - (and (integer? (cadr x)) (not (= (cadr x) 0)))) - (move (cadr x) s p i b - (lambda (s0 p0 i0 b0) - (list-splice! p0 i0 (cons (list-ref p0 i0) (caddr x))) - (wrlev s p i b)))] - [else - (unrecognized-command-syntax s p i b)])))) - (set! edit - ;; set up keyboard interrupt handler and go. - (lambda (e) - (let ([p (cons e '())]) - (let ([k (call/cc (lambda (k) k))]) ; return here on interrupt - (parameterize ([keyboard-interrupt-handler - (lambda () - (printf "reset~%") - (k k))]) - (wrlev #f p 0 '()) - (car p))))))) diff --git a/ta6ob/examples/ez-grammar-test.ss b/ta6ob/examples/ez-grammar-test.ss deleted file mode 100644 index 3dd4871..0000000 --- a/ta6ob/examples/ez-grammar-test.ss +++ /dev/null @@ -1,570 +0,0 @@ -;;; Copyright 2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; This file contains a sample parser defined via the ez-grammar system -;;; and a simple test of the parser. - -;;; This file is organized as follows: -;;; -;;; - (streams) library providing the required exports for ez-grammar and -;;; the parser. -;;; -;;; - (state-case) library exporting the state-case macro, copped from -;;; cmacros.ss, for use by the lexer. -;;; -;;; - (lexer) library providing a simple lexer that reads characters -;;; from a port and produces a corresponding stream of tokens. -;;; -;;; - (parser) library providing the sample parser. -;;; -;;; - ez-grammar-test procedure that tests the sample parser. -;;; -;;; Instructions for running the test are at the end of this file. - -(library (streams) - (export stream-cons stream-car stream-cdr stream-nil stream-null? - stream-map stream stream-append2 stream-append-all stream-last-forced) - (import (chezscheme)) - - (define stream-cons - (lambda (x thunk) - (cons x thunk))) - - (define stream-car - (lambda (x) - (car x))) - - (define stream-cdr - (lambda (x) - (when (procedure? (cdr x)) (set-cdr! x ((cdr x)))) - (cdr x))) - - (define stream-nil '()) - - (define stream-null? - (lambda (x) - (null? x))) - - (define stream-map - (lambda (f x) - (if (stream-null? x) - '() - (stream-cons (f (stream-car x)) - (lambda () - (stream-map f (stream-cdr x))))))) - - (define stream - (lambda xs - xs)) - - (define stream-append2 - (lambda (xs thunk) - (if (null? xs) - (thunk) - (stream-cons (stream-car xs) - (lambda () - (stream-append2 (stream-cdr xs) thunk)))))) - - (define stream-append-all - (lambda (stream$) ;; stream of streams - (if (stream-null? stream$) - stream$ - (stream-append2 (stream-car stream$) - (lambda () (stream-append-all (stream-cdr stream$))))))) - - (define stream-last-forced - (lambda (x) - (and (not (null? x)) - (let loop ([x x]) - (let ([next (cdr x)]) - (if (pair? next) - (loop next) - (car x))))))) -) - -(library (state-case) - (export state-case eof) - (import (chezscheme)) - - ;;; from Chez Scheme Version 9.5.1 cmacros.ss - (define-syntax state-case - (lambda (x) - (define state-case-test - (lambda (cvar k) - (with-syntax ((cvar cvar)) - (syntax-case k (-) - (char - (char? (datum char)) - #'(char=? cvar char)) - ((char1 - char2) - (and (char? (datum char1)) (char? (datum char2))) - #'(char<=? char1 cvar char2)) - (predicate - (identifier? #'predicate) - #'(predicate cvar)))))) - (define state-case-help - (lambda (cvar clauses) - (syntax-case clauses (else) - (((else exp1 exp2 ...)) - #'(begin exp1 exp2 ...)) - ((((k ...) exp1 exp2 ...) . more) - (with-syntax (((test ...) - (map (lambda (k) (state-case-test cvar k)) - #'(k ...))) - (rest (state-case-help cvar #'more))) - #'(if (or test ...) (begin exp1 exp2 ...) rest))) - (((k exp1 exp2 ...) . more) - (with-syntax ((test (state-case-test cvar #'k)) - (rest (state-case-help cvar #'more))) - #'(if test (begin exp1 exp2 ...) rest)))))) - (syntax-case x (eof) - ((_ cvar (eof exp1 exp2 ...) more ...) - (identifier? #'cvar) - (with-syntax ((rest (state-case-help #'cvar #'(more ...)))) - #'(if (eof-object? cvar) - (begin exp1 exp2 ...) - rest)))))) - - (define-syntax eof - (lambda (x) - (syntax-error x "misplaced aux keyword"))) -) - -(library (lexer) - (export token? token-type token-value token-bfp token-efp lexer) - (import (chezscheme) (state-case) (streams)) - - (define-record-type token - (nongenerative) - (fields type value bfp efp)) - - ;; test lexer - (define lexer - (lambda (fn ip) - (define $prev-pos 0) - (define $pos 0) - (define ($get-char) - (set! $pos (+ $pos 1)) - (get-char ip)) - (define ($unread-char c) - (set! $pos (- $pos 1)) - (unread-char c ip)) - (define ($ws!) (set! $prev-pos $pos)) - (define ($make-token type value) - (let ([tok (make-token type value $prev-pos $pos)]) - (set! $prev-pos $pos) - tok)) - (define ($lex-error c) - (errorf #f "unexpected ~a at character ~s of ~a" - (if (eof-object? c) - "eof" - (format "character '~c'" c)) - $pos fn)) - (define-syntax lex-error - (syntax-rules () - [(_ ?c) - (let ([c ?c]) - ($lex-error c) - (void))])) - (let-values ([(sp get-buf) (open-string-output-port)]) - (define (return-token type value) - (stream-cons ($make-token type value) lex)) - (module (identifier-initial? identifier-subsequent?) - (define identifier-initial? - (lambda (c) - (char-alphabetic? c))) - (define identifier-subsequent? - (lambda (c) - (or (char-alphabetic? c) - (char-numeric? c))))) - (define-syntax define-state-case - (syntax-rules () - [(_ ?def-id ?char-id clause ...) - (define (?def-id) - (let ([?char-id ($get-char)]) - (state-case ?char-id clause ...)))])) - (define-state-case lex c - [eof stream-nil] - [char-whitespace? ($ws!) (lex)] - [char-numeric? (lex-number c)] - [#\/ (seen-slash)] - [identifier-initial? (put-char sp c) (lex-identifier)] - [#\( (return-token 'lparen #\()] - [#\) (return-token 'rparen #\))] - [#\! (return-token 'bang #\!)] - [#\+ (seen-plus)] - [#\- (seen-minus)] - [#\= (seen-equals)] - [#\* (return-token 'binop '*)] - [#\, (return-token 'sep #\,)] - [#\; (return-token 'sep #\;)] - [else (lex-error c)]) - (module (lex-identifier) - (define (id) (return-token 'id (string->symbol (get-buf)))) - (define-state-case next c - [eof (id)] - [identifier-subsequent? (put-char sp c) (next)] - [else ($unread-char c) (id)]) - (define (lex-identifier) (next))) - (define-state-case seen-plus c - [eof (return-token 'binop '+)] - [char-numeric? (lex-signed-number #\+ c)] - [else (return-token 'binop '+)]) - (define-state-case seen-minus c - [eof (return-token 'binop '-)] - [char-numeric? (lex-signed-number #\- c)] - [else (return-token 'binop '-)]) - (define-state-case seen-equals c - [eof (return-token 'binop '=)] - [#\> (return-token 'big-arrow #f)] - [else (return-token 'binop '=)]) - (module (lex-number lex-signed-number) - (define (finish-number) - (let ([str (get-buf)]) - (let ([n (string->number str 10)]) - (unless n (errorf 'lexer "unexpected number literal ~a" str)) - (return-token 'integer n)))) - (define (num) - (let ([c ($get-char)]) - (state-case c - [eof (finish-number)] - [char-numeric? (put-char sp c) (num)] - [else ($unread-char c) (finish-number)]))) - (define (lex-signed-number s c) - (put-char sp s) - (lex-number c)) - (define (lex-number c) - (state-case c - [eof (assert #f)] - [char-numeric? (put-char sp c) (num)] - [else (assert #f)]))) - (define-state-case seen-slash c - [eof (return-token 'binop '/)] - [#\* (lex-block-comment)] - [#\/ (lex-comment)] - [else (return-token 'binop '/)]) - (define-state-case lex-comment c - [eof (lex)] - [#\newline ($ws!) (lex)] - [else (lex-comment)]) - (define (lex-block-comment) - (define-state-case maybe-end-comment c - [eof (lex-error c)] - [#\/ ($ws!) (lex)] - [else (lex-block-comment)]) - (let ([c ($get-char)]) - (state-case c - [eof (lex-error c)] - [#\* (maybe-end-comment)] - [else (lex-block-comment)]))) - (lex)))) - - (record-writer (record-type-descriptor token) - (lambda (x p wr) - (put-char p #\[) - (wr (token-type x) p) - (put-char p #\,) - (put-char p #\space) - (wr (token-value x) p) - (put-char p #\]) - (put-char p #\:) - (wr (token-bfp x) p) - (put-char p #\-) - (wr (token-efp x) p))) -) - -(module parser () - (export parse *sfd*) - (import (chezscheme) (streams) (lexer)) - (define *sfd*) - (module (define-grammar is sat parse-consumed-all? parse-result-value grammar-trace make-src) - (define (sep->parser sep) - (cond - [(char? sep) (sat (lambda (x) (and (eq? (token-type x) 'sep) (eq? (token-value x) sep))))] - [(symbol? sep) (sat (lambda (x) (eq? (token-type x) sep)))] - [else (errorf "don't know how to parse separator: ~s" sep)])) - (meta define (constant? x) (let ([x (syntax->datum x)]) (or (string? x) (char? x)))) - (define constant->parser - (lambda (const) - (define (token-sat type val) - (sat (lambda (x) - (let ([ans (and (token? x) (eqv? (token-type x) type) (eqv? (token-value x) val))]) - (when (grammar-trace) (printf " ~s is [~s, ~a]? => ~s~%" x type val ans)) - ans)))) - (if (string? const) - (case const - [else (token-sat 'id (string->symbol const))]) - (case const - [#\( (token-sat 'lparen const)] - [#\) (token-sat 'rparen const)] - [#\! (token-sat 'bang const)] - [else (errorf 'constant->parser "don't know how to construct a parser for ~a" const)])))) - (meta define (constant->markdown k) - (format "~a" k)) - (define binop->parser - (lambda (binop) - (define (binop-sat type val) - (is val - (where [x <- item] (and (token? x) (eq? (token-type x) type) (eq? (token-value x) val))))) - (define (unexpected) (errorf 'binop->parser "don't know how to construct a parser for ~a" binop)) - (if (string? binop) - (binop-sat 'binop - (case binop - ["=" '=] - ["+" '+] - ["-" '-] - ["*" '*] - ["/" '/] - [else (unexpected)])) - (unexpected)))) - (define make-src - (lambda (bfp efp) - (make-source-object *sfd* bfp efp))) - (include "ez-grammar.ss")) - - (define token - (case-lambda - [(type) - (is (token-value x) - (where - [x <- (sat (lambda (x) - (let ([ans (eq? (token-type x) type)]) - (when (grammar-trace) (printf " ~s is ~s? => ~s~%" x type ans)) - ans)))]))] - [(type val) - (is (token-value x) - (where - [x <- (sat (lambda (x) - (let ([ans (and - (eq? (token-type x) type) - (eqv? (token-value x) val))]) - (when (grammar-trace) (printf " ~s is [~s, ~s]? => ~s~%" x type val ans)) - ans)))]))])) - - (define identifier (token 'id)) - - (define integer (token 'integer)) - - (define-grammar expr (markdown-directory ".") - (TERMINALS - (identifier (x y) (DESCRIPTION ("An identifier is ..."))) - (integer (i) (DESCRIPTION ("An integer literal is ...")))) - (expr (e) - (BINOP src ((RIGHT "=") (LEFT "+" "-") (LEFT "*" "/")) t) => - (lambda (src op x y) - (make-annotation `(,op ,x ,y) src `(,op ,(annotation-stripped x) ,(annotation-stripped y))))) - (term (t) - [test-SEP+ :: src "sepplus" #\( (SEP+ e #\;) #\) => - (lambda (src e+) - (make-annotation `(SEP+ ,@e+) src `(SEP+ ,@(map annotation-stripped e+))))] - [test-SEP* :: src "sepstar" #\( (SEP* e #\,) #\) => - (lambda (src e*) - (make-annotation `(SEP* ,@e*) src `(SEP* ,@(map annotation-stripped e*))))] - [test-OPT :: src "opt" #\( (OPT e #f) #\) => - (lambda (src maybe-e) - (if maybe-e - (make-annotation `(OPT ,maybe-e) src `(OPT ,(annotation-stripped maybe-e))) - (make-annotation `(OPT) src `(OPT))))] - [test-K+ :: src "kplus" #\( (K+ e) #\) => - (lambda (src e+) - (make-annotation `(K+ ,@e+) src `(K+ ,@(map annotation-stripped e+))))] - [test-K* :: src "kstar" #\( (K* e) #\) => - (lambda (src e*) - (make-annotation `(K* ,@e*) src `(K* ,@(map annotation-stripped e*))))] - [varref :: src x => - (lambda (src id) - (make-annotation `(id ,id) src `(id ,id)))] - [intref :: src i => - (lambda (src n) - (make-annotation `(int ,n) src `(int ,n)))] - [group :: src #\( e #\) => - (lambda (src e) - `(group ,src ,e))])) - - (define parse - (lambda (fn ip) - (let ([token-stream (lexer fn ip)]) - (define (oops) - (let ([last-token (stream-last-forced token-stream)]) - (if last-token - (errorf 'parse "parse error at or before character ~s of ~a" (token-bfp last-token) fn) - (errorf 'parse "no expressions found in ~a" fn)))) - ;;; return the first result, if any, for which the input stream was entirely consumed. - (let loop ([res* (expr token-stream)]) - (if (null? res*) - (oops) - (let ([res (car res*)]) - (if (parse-consumed-all? res) - (parse-result-value res) - (loop (cdr res*)))))))))) - -(define run - (lambda (fn) - (import parser) - (let* ([ip (open-file-input-port fn)] - [sfd (make-source-file-descriptor fn ip #t)] - [ip (transcoded-port ip (native-transcoder))]) - (fluid-let ([*sfd* sfd]) - (eval - `(let () - (define-syntax define-ops - (lambda (x) - (syntax-case x () - [(_ op ...) - #`(begin - (define-syntax op - (lambda (x) - (let ([src (annotation-source (syntax->annotation x))]) - (with-syntax ([bfp (source-object-bfp src)] [efp (source-object-efp src)]) - (syntax-case x () - [(_ e (... ...)) #'`(op (bfp . efp) ,e (... ...))]))))) - ...)]))) - (define-ops SEP+ SEP* OPT K+ K* id int group) - (define-ops = + - * /) - (define x 'x) - (define y 'y) - (define z 'z) - ,(dynamic-wind - void - (lambda () (parse fn ip)) - (lambda () (close-input-port ip))))))))) - -(define (ez-grammar-test) - (define n 0) - (define test - (lambda (line* okay?) - (set! n (+ n 1)) - (let ([fn (format "testfile~s" n)]) - (with-output-to-file fn - (lambda () (for-each (lambda (line) (printf "~a\n" line)) line*)) - 'replace) - (let ([result (parameterize ([compile-profile #t] [compile-interpret-simple #f]) - (guard (c [else c]) (run fn)))]) - (guard (c [else #f]) (profile-dump-html)) - (delete-file fn) - (delete-file "profile.html") - (delete-file (format "~a.html" fn)) - (unless (okay? result) - (printf "test ~s failed\n" n) - (printf " test code:") - (for-each (lambda (line) (printf " ~a\n" line)) line*) - (printf " result:\n ") - (if (condition? result) - (begin (display-condition result) (newline)) - (parameterize ([pretty-initial-indent 4]) - (pretty-print result))) - (newline)))))) - - (define-syntax returns - (syntax-rules () - [(_ k) (lambda (x) (equal? x 'k))])) - - (define-syntax oops - (syntax-rules () - [(_ (c) e1 e2 ...) - (lambda (c) (and (condition? c) e1 e2 ...))])) - - (test - '( - "1347" - ) - (returns - (int (0 . 4) 1347))) - - (test - '( - "3 /*" - ) - (oops (c) - (equal? (condition-message c) "unexpected ~a at character ~s of ~a") - (equal? (condition-irritants c) '("eof" 6 "testfile2")))) - - (test - '( - "3 / 4 + 5 opt(6)" - ) - (oops (c) - (equal? (condition-message c) "parse error at or before character ~s of ~a") - (equal? (condition-irritants c) '(10 "testfile3")))) - - (test - '( - "x = y = 5" - ) - (returns - (= - (0 . 9) - (id (0 . 1) x) - (= (4 . 9) (id (4 . 5) y) (int (8 . 9) 5))))) - - (test - '( - "x = y = x + 5 - z * 7 + 8 / z" - ) - (returns - (= - (0 . 29) - (id (0 . 1) x) - (= - (4 . 29) - (id (4 . 5) y) - (+ - (8 . 29) - (- - (8 . 21) - (+ (8 . 13) (id (8 . 9) x) (int (12 . 13) 5)) - (* (16 . 21) (id (16 . 17) z) (int (20 . 21) 7))) - (/ (24 . 29) (int (24 . 25) 8) (id (28 . 29) z))))))) - - (test - '( - "opt(opt(opt()))" - ) - (returns - (OPT (0 . 15) (OPT (4 . 14) (OPT (8 . 13)))))) - - (test - '( - "kstar(3 4 kplus(1 2 3 kstar()))" - ) - (returns - (K* (0 . 31) - (int (6 . 7) 3) - (int (8 . 9) 4) - (K+ (10 . 30) - (int (16 . 17) 1) - (int (18 . 19) 2) - (int (20 . 21) 3) - (K* (22 . 29)))))) - - (test - '( - "sepplus( opt() ; opt(5) ; sepstar(17, 34) ; sepstar())" - ) - (returns - (SEP+ (0 . 54) - (OPT (9 . 14)) - (OPT (17 . 23) (int (21 . 22) 5)) - (SEP* (26 . 41) (int (34 . 36) 17) (int (38 . 40) 34)) - (SEP* (44 . 53))))) - - (delete-file "expr.md") - (printf "~s tests ran\n" n) - ) - -#!eof - -The following should print only " tests ran". - -echo '(ez-grammar-test)' | ../bin/scheme -q ez-grammar-test.ss diff --git a/ta6ob/examples/ez-grammar.ss b/ta6ob/examples/ez-grammar.ss deleted file mode 100644 index 1d95dd8..0000000 --- a/ta6ob/examples/ez-grammar.ss +++ /dev/null @@ -1,759 +0,0 @@ -;;; Copyright 2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; See http://www.cs.nott.ac.uk/~pszgmh/monparsing.pdf for origins of -;;; some of the monadic combinators. - -;;; Authors: Jon Rossie, Kent Dybvig - -;;; The define-grammar form produces a parser: -;;; -;;; parser : token-stream -> ((Tree token-stream) ...) -;;; -;;; If the return value is the empty list, a parse error occurred. -;;; If the return value has multiple elements, the parse was ambiguous. -;;; The token-stream in each (Tree token-stream) is the tail of the -;;; input stream that begins with the last token consumed by the parse. -;;; This gives the consumer access to both the first and last token, -;;; allowing it to determine cheaply the extent of the parse, including -;;; source locations if source information is attached to the tokens. - -;;; Internally, backtracking occurs whenever a parser return value -;;; has multiple elements. - -;;; This code should be included into a lexical context that supplies: -;;; -;;; token-bfp : token -> token's beginning file position -;;; token-efp : token -> token's ending file position -;;; meta constant? : syntax-object -> boolean -;;; sep->parser : sep -> parser -;;; constant->parser : constant -> parser -;;; make-src : bfp x efp -> src. bfp > efp => no tokens consumed. -;;; -;;; See ez-grammar-test.ss for an example. - -(module (define-grammar - is sat item peek seq ++ +++ many many+ ? - parse-consumed-all? parse-result-value parse-result-unused - grammar-trace - ) - (import (streams)) - - (define grammar-trace (make-parameter #f)) - - (define-record-type parse-result - (nongenerative parse-result) - (sealed #t) - (fields value unused)) - - ;; to enable $trace-is to determine the ending file position (efp) of a parse - ;; form, the input stream actually points to the preceding token rather than - ;; to the current token. the next few routines establish, maintain, and deal - ;; with that invariant. - (define make-top-level-parser - (lambda (parser) - (lambda (inp) - (parser (stream-cons 'dummy-token inp))))) - - (define preceding-token - (lambda (inp) - (stream-car inp))) - - (define current-token - (lambda (inp) - (stream-car (stream-cdr inp)))) - - (define remaining-tokens - (lambda (inp) - (stream-cdr inp))) - - (define no-more-tokens? - (lambda (inp) - (stream-null? (stream-cdr inp)))) - - (define parse-consumed-all? - (lambda (res) - (no-more-tokens? (parse-result-unused res)))) - - ;; A parser generator - (define result - (lambda (v) - ;; this is a parser that ignores its input and produces v - (lambda (inp) - (stream (make-parse-result v inp))))) - - ;; A parse that always generates a parse error - (define zero - (lambda (inp) - stream-nil)) - - ;; For a non-empty stream, successfully consume the first element - (define item - (lambda (inp) - (cond - [(no-more-tokens? inp) '()] - [else - (stream (make-parse-result (current-token inp) (remaining-tokens inp)))]))) - - (define (peek p) - (lambda (inp) - (stream-map (lambda (pr) - (make-parse-result (parse-result-value pr) inp)) - (p inp)))) - - ;;------------------------------------------ - - (define bind - (lambda (parser receiver) - (lambda (inp) - (let ([res* (parser inp)]) - (stream-append-all - (stream-map (lambda (res) - ((receiver (parse-result-value res)) - (parse-result-unused res))) - res*)))))) - - ;; monad comprehensions - (define-syntax is-where ; used by is and trace-is - (lambda (x) - (syntax-case x (where <-) - [(_ expr (where)) #'expr] - [(_ expr (where [x <- p] clauses ...)) - #'(bind p (lambda (x) (is-where expr (where clauses ...))))] - [(_ expr (where pred clauses ...)) - #'(if pred (is-where expr (where clauses ...)) zero)] - [(_ expr where-clause) (syntax-error #'where-clause)]))) - (indirect-export is-where bind) - - (define-syntax is - (syntax-rules () - [(_ expr where-clause) (is-where (result expr) where-clause)])) - (indirect-export is is-where) - - (module (trace-is) - (define ($trace-is name proc head) - (lambda (unused) - (let ([res (proc (token-bfp (current-token head)) (token-efp (preceding-token unused)))]) - (when (and name (grammar-trace)) (printf "<<~s = ~s~%" name res)) - (stream (make-parse-result res unused))))) - - (define-syntax trace-is - (syntax-rules () - [(_ name proc-expr where-clause) - (lambda (inp) ((is-where ($trace-is 'name proc-expr inp) where-clause) inp))])) - (indirect-export trace-is $trace-is)) - - (define (seq2 p q) (is (cons x y) (where [x <- p] [y <- q]))) - - (define seq - (lambda p* - (let loop ([p* p*]) - (cond - [(null? p*) (result '())] - [else (seq2 (car p*) (loop (cdr p*)))])))) - - (define (sat pred) (is x (where [x <- item] (pred x)))) - - (define ++ ;; introduce ambiguity - (lambda (p q) - (lambda (inp) - (stream-append2 (p inp) - (lambda () - (q inp)))))) - - (define (many+ p) (is (cons x xs) (where [x <- p] [xs <- (many p)]))) - - (define (many p) (++ (many+ p) (result '()))) - - (define (? p) (++ (sat p) (result #f))) - - (define (sepby1 p sep) - (is (cons x xs) - (where - [x <- p] - [xs <- (many (is y (where [_ <- sep] [y <- p])))]))) - - (define (sepby p sep) (++ (sepby1 p sep) (result '()))) - - (define (bracket open p close) (is x (where [_ <- open] [x <- p] [_ <- close]))) - - (define (optional p default) - (lambda (inp) - (let ([res (p inp)]) - (if (stream-null? res) - (stream (make-parse-result default inp)) - res)))) - - (define (first p) - (lambda (inp) - (let ([res (p inp)]) - (if (stream-null? res) - res - (stream (stream-car res)))))) - - (define (+++ p q) (first (++ p q))) ;; choose first match, cut backtracking - - (define-syntax infix-expression-parser - (lambda (x) - (syntax-case x () - [(_ ((L/R ?op-parser) ...) ?term-parser ?receiver) - (with-syntax ([(op-parser ...) (generate-temporaries #'(?op-parser ...))]) - #`(let ([op-parser ?op-parser] ... [term-parser (lambda (inp) (?term-parser inp))] [receiver ?receiver]) - #,(let f ([ls #'((L/R op-parser) ...)]) - (if (null? ls) - #'term-parser - #`(let ([next #,(f (cdr ls))]) - #,(syntax-case (car ls) (LEFT RIGHT) - [(LEFT op-parser) - #'(let () - (define-record-type frob (nongenerative) (sealed #t) (fields op y efp)) - (trace-is binop-left (lambda (bfp ignore-this-efp) - (fold-left - (lambda (x f) (receiver bfp (frob-efp f) (frob-op f) x (frob-y f))) - x f*)) - (where - [x <- next] - [f* <- (rec this - (optional - (is (cons f f*) - (where - [f <- (trace-is binop-left-tail (lambda (bfp efp) (make-frob op y efp)) - (where - [op <- op-parser] - [y <- next]))] - [f* <- this])) - '()))])))] - [(RIGHT op-parser) - #'(rec this - (+++ - (trace-is binop-right (lambda (bfp efp) (receiver bfp efp op x y)) - (where - [x <- next] - [op <- op-parser] - [y <- this])) - next))]))))))]))) - - (define (format-inp inp) - (if (no-more-tokens? inp) - "#" - (format "(~s ...)" (current-token inp)))) - - (define-syntax define-grammar - (lambda (x) - (define-record-type grammar - (nongenerative) - (sealed #t) - (fields title paragraph* section*)) - (define-record-type section - (nongenerative) - (sealed #t) - (fields title paragraph* suppressed? clause*)) - (define-record-type clause - (nongenerative) - (fields id alias* before-paragraph* after-paragraph*)) - (define-record-type regular-clause - (nongenerative) - (sealed #t) - (parent clause) - (fields prod*)) - (define-record-type binop-clause - (nongenerative) - (sealed #t) - (parent clause) - (fields level* term receiver) - (protocol - (lambda (pargs->new) - (lambda (nt alias* before-paragraph* after-paragraph* level* term src? receiver) - ((pargs->new nt alias* before-paragraph* after-paragraph*) level* term - #`(lambda (bfp efp op x y) - #,(if src? - #`(#,receiver (make-src bfp efp) op x y) - #`(#,receiver op x y)))))))) - (define-record-type terminal-clause - (nongenerative) - (sealed #t) - (fields term*)) - (define-record-type terminal - (nongenerative) - (sealed #t) - (fields parser alias* paragraph*)) - (define-record-type production - (nongenerative) - (sealed #t) - (fields name paragraph* elt* receiver) - (protocol - (let () - (define (check-elts elt*) - (for-each (lambda (elt) (unless (elt? elt) (errorf 'make-production "~s is not an elt" elt))) elt*)) - (lambda (new) - (case-lambda - [(name elt* receiver) - (check-elts elt*) - (new name #f elt* receiver)] - [(name paragraph* elt* receiver) - (check-elts elt*) - (new name paragraph* elt* receiver)]))))) - (define-record-type elt - (nongenerative)) - (define-record-type sep-elt - (nongenerative) - (sealed #t) - (parent elt) - (fields +? elt sep)) - (define-record-type opt-elt - (nongenerative) - (sealed #t) - (parent elt) - (fields elt default)) - (define-record-type kleene-elt - (nongenerative) - (sealed #t) - (parent elt) - (fields +? elt)) - (define-record-type constant-elt - (nongenerative) - (sealed #t) - (parent elt) - (fields k)) - (define-record-type id-elt - (nongenerative) - (sealed #t) - (parent elt) - (fields id)) - (define paragraph? - (lambda (x) - (syntax-case x (include) - [(include filename) (string? (datum filename))] - [(str ...) (andmap string? (datum (str ...)))]))) - (define (gentemp) (datum->syntax #'* (gensym))) - (define (elt-temps elt*) - (for-each (lambda (elt) (unless (elt? elt) (errorf 'elt-temps "~s is not an elt" elt))) elt*) - (fold-left - (lambda (t* elt) - (if (constant-elt? elt) t* (cons (gentemp) t*))) - '() - elt*)) - (define (left-factor clause*) - (define syntax-equal? - (lambda (x y) - (equal? (syntax->datum x) (syntax->datum y)))) - (define (elt-equal? x y) - (cond - [(sep-elt? x) - (and (sep-elt? y) - (eq? (sep-elt-+? x) (sep-elt-+? y)) - (elt-equal? (sep-elt-elt x) (sep-elt-elt y)) - (syntax-equal? (sep-elt-sep x) (sep-elt-sep y)))] - [(opt-elt? x) - (and (opt-elt? y) - (elt-equal? (opt-elt-elt x) (opt-elt-elt y)) - (syntax-equal? (opt-elt-default x) (opt-elt-default y)))] - [(kleene-elt? x) - (and (kleene-elt? y) - (eq? (kleene-elt-+? x) (kleene-elt-+? y)) - (elt-equal? (kleene-elt-elt x) (kleene-elt-elt y)))] - [(constant-elt? x) - (and (constant-elt? y) - (syntax-equal? (constant-elt-k x) (constant-elt-k y)))] - [(id-elt? x) - (and (id-elt? y) - (syntax-equal? (id-elt-id x) (id-elt-id y)))] - [else #f])) - (let lp1 ([clause* clause*] [new-clause* '()]) - (if (null? clause*) - (reverse new-clause*) - (let ([clause (car clause*)]) - (let lp2 ([prod* (regular-clause-prod* clause)] [new-prod* '()] [clause* (cdr clause*)]) - (if (null? prod*) - (lp1 clause* (cons (make-regular-clause (clause-id clause) (clause-alias* clause) '() '() (reverse new-prod*)) new-clause*)) - (let ([prod (car prod*)] [prod* (cdr prod*)]) - (let ([elt* (production-elt* prod)]) - (if (null? elt*) - (lp2 prod* (cons prod new-prod*) clause*) - (let ([elt (car elt*)]) - (let-values ([(haves have-nots) (partition - (lambda (prod) - (let ([elt* (production-elt* prod)]) - (and (not (null? elt*)) - (elt-equal? (car elt*) elt)))) - prod*)]) - (if (null? haves) - (lp2 prod* (cons prod new-prod*) clause*) - (let ([haves (cons prod haves)]) - ; "haves" start with the same elt. to cut down on the number of new - ; nonterminals and receiver overhead, find the largest common prefix - (let ([prefix (cons elt - (let f ([elt** (map production-elt* haves)]) - (let ([elt** (map cdr elt**)]) - (if (ormap null? elt**) - '() - (let ([elt (caar elt**)]) - (if (andmap (lambda (elt*) (elt-equal? (car elt*) elt)) (cdr elt**)) - (cons elt (f elt**)) - '()))))))]) - (let ([t (gentemp)] [n (length prefix)] [t* (elt-temps prefix)]) - (lp2 have-nots - (cons (make-production #f (append prefix (list (make-id-elt t))) - #`(lambda (bfp efp #,@t* p) (p bfp #,@t*))) - new-prod*) - (cons (make-regular-clause t '() '() '() - (map (lambda (prod) - (let ([elt* (list-tail (production-elt* prod) n)]) - (make-production (production-name prod) elt* - (let ([u* (elt-temps elt*)]) - #`(lambda (bfp efp #,@u*) - (lambda (bfp #,@t*) - (#,(production-receiver prod) bfp efp #,@t* #,@u*))))))) - haves)) - clause*))))))))))))))))) - (define (make-env tclause* clause*) - (let ([env (make-hashtable (lambda (x) (symbol-hash (syntax->datum x))) free-identifier=?)]) - (define (insert parser) - (lambda (name) - (let ([a (hashtable-cell env name #f)]) - (when (cdr a) (syntax-error name "duplicate terminal/non-terminal name")) - (set-cdr! a parser)))) - (for-each - (lambda (tclause) - (for-each - (lambda (term) - (let ([parser (terminal-parser term)]) - (for-each (insert parser) (cons parser (terminal-alias* term))))) - (terminal-clause-term* tclause))) - tclause*) - (for-each - (lambda (clause) - (let ([id (clause-id clause)]) - (for-each (insert id) (cons id (clause-alias* clause))))) - clause*) - env)) - (define (lookup id env) - (or (hashtable-ref env id #f) - (syntax-error id "unrecognized terminal or nonterminal"))) - (define (render-markdown name grammar mdfn env) - (define (separators sep ls) - (if (null? ls) - "" - (apply string-append - (cons (car ls) - (map (lambda (s) (format "~a~a" sep s)) (cdr ls)))))) - (define (render-paragraph hard-leading-newline?) - (lambda (paragraph) - (define (md-text s) - (list->string - (fold-right - (lambda (c ls) - (case c - [(#\\) (cons* c c ls)] - [else (cons c ls)])) - '() - (string->list s)))) - (syntax-case paragraph (include) - [(include filename) - (string? (datum filename)) - (let ([text (call-with-port (open-input-file (datum filename)) get-string-all)]) - (unless (equal? text "") - (if hard-leading-newline? (printf "\\\n") (newline)) - (display-string text)))] - [(sentence ...) - (andmap string? (datum (sentence ...))) - (let ([sentence* (datum (sentence ...))]) - (unless (null? sentence*) - (if hard-leading-newline? (printf "\\\n") (newline)) - (printf "~a\n" (separators " " (map md-text sentence*)))))]))) - (define (format-elt x) - (cond - [(sep-elt? x) - (let* ([one (format-elt (sep-elt-elt x))] - [sep (constant->markdown (syntax->datum (sep-elt-sep x)))] - [seq (format "~a  ~a  `...`" one sep)]) - (if (sep-elt-+? x) - seq - (format "OPT(~a)" seq)))] - [(opt-elt? x) - (format "~a~~opt~~" (format-elt (opt-elt-elt x)))] - [(kleene-elt? x) - (let ([one (format-elt (kleene-elt-elt x))]) - (if (kleene-elt-+? x) - (format "~a  `...`" one) - (format "OPT(~a)" one)))] - [(constant-elt? x) (constant->markdown (syntax->datum (constant-elt-k x)))] - [(id-elt? x) (format "[*~s*](#~s)" - (syntax->datum (id-elt-id x)) - (syntax->datum (lookup (id-elt-id x) env)))] - [else (errorf 'format-elt "unexpected elt ~s" x)])) - (define (render-elt x) - (printf "  ~a" (format-elt x))) - (define (render-production prod) - (unless (null? (production-elt* prod)) - (printf " : ") - (for-each render-elt (production-elt* prod)) - (printf "\n")) - (when (and (null? (production-elt* prod)) - (not (null? (production-paragraph* prod)))) - (errorf 'render-production "empty production must not have description: ~a" (production-paragraph* prod))) - (for-each (render-paragraph #t) (production-paragraph* prod))) - (define (render-clause clause) - (define (render-aliases alias*) - (unless (null? alias*) - (printf " \naliases: ~{*~a*~^, ~}\n" (map syntax->datum alias*)))) - (if (terminal-clause? clause) - (for-each - (lambda (term) - (printf "\n#### *~a* {#~:*~a}\n" (syntax->datum (terminal-parser term))) - (render-aliases (terminal-alias* term)) - (for-each (render-paragraph #f) (terminal-paragraph* term))) - (terminal-clause-term* clause)) - (let ([id (syntax->datum (clause-id clause))]) - (printf "\n#### *~a* {#~:*~a}\n" id) - (render-aliases (clause-alias* clause)) - (for-each (render-paragraph #f) (clause-before-paragraph* clause)) - (printf "\nsyntax:\n") - (if (binop-clause? clause) - (let ([level* (binop-clause-level* clause)]) - (let loop ([level* level*] [first? #t]) - (unless (null? level*) - (let ([level (syntax->datum (car level*))] [level* (cdr level*)]) - (let ([L/R (car level)] [op* (cdr level)]) - (printf " : _~(~a~)-associative" L/R) - (if first? - (if (null? level*) - (printf ":_\n") - (printf ", highest precedence:_\n")) - (if (null? level*) - (printf ", lowest precedence:_\n") - (printf ":_\n"))) - (for-each - (lambda (op) (printf " : ~s ~a ~s\n" id (constant->markdown op) id)) - op*)) - (loop level* #f)))) - (printf " : _leaves:_\n") - (printf " : ") - (render-elt (binop-clause-term clause)) - (printf "\n")) - (for-each render-production (or (regular-clause-prod* clause) '()))) - (for-each (render-paragraph #f) (clause-after-paragraph* clause))))) - (define (render-section section) - (unless (section-suppressed? section) - (printf "\n## ~a\n" (or (section-title section) "The section")) - (for-each (render-paragraph #f) (section-paragraph* section)) - (for-each render-clause (section-clause* section)))) - (with-output-to-file mdfn - (lambda () - (printf "# ~a\n" (or (grammar-title grammar) "The grammar")) - (for-each (render-paragraph #f) (grammar-paragraph* grammar)) - (for-each render-section (grammar-section* grammar))) - 'replace)) - (module (parse-grammar) - (define parse-elt - (lambda (elt) - (syntax-case elt (SEP+ SEP* OPT K* K+) - [(SEP+ p sep) (make-sep-elt #t (parse-elt #'p) #'sep)] - [(SEP* p sep) (make-sep-elt #f (parse-elt #'p) #'sep)] - [(OPT p default) (make-opt-elt (parse-elt #'p) #'default)] - [(K+ p) (make-kleene-elt #t (parse-elt #'p))] - [(K* p) (make-kleene-elt #f (parse-elt #'p))] - [k (constant? #'k) (make-constant-elt #'k)] - [id (identifier? #'id) (make-id-elt #'id)] - [_ (syntax-error elt "invalid production element")]))) - (define parse-production - (lambda (prod) - (define (finish name src? paragraph* elt* receiver) - (let ([elt* (map parse-elt elt*)]) - (make-production name paragraph* elt* - (with-syntax ([(t ...) (elt-temps elt*)]) - #`(lambda (bfp efp t ...) - #,(if src? - #`(#,receiver (make-src bfp efp) t ...) - #`(#,receiver t ...))))))) - (syntax-case prod (:: src =>) - [[name :: src elt ... => receiver] - (finish #'name #t '() #'(elt ...) #'receiver)] - [[name :: elt ... => receiver] - (finish #'name #f '() #'(elt ...) #'receiver)]))) - (define (parse-terminal term) - (syntax-case term (DESCRIPTION) - [(parser (alias ...) (DESCRIPTION paragraph ...)) - (and (identifier? #'parser) (andmap identifier? #'(alias ...)) (andmap paragraph? #'(paragraph ...))) - (make-terminal #'parser #'(alias ...) #'(paragraph ...))] - [(parser (alias ...)) - (and (identifier? #'parser) (andmap identifier? #'(alias ...))) - (make-terminal #'parser #'(alias ...) '())])) - (define (parse-clause clause nt alias* before-paragraph* after-paragraph* stuff*) - (syntax-case stuff* (BINOP :: src =>) - [((BINOP src (level ...) term) => receiver) - (make-binop-clause nt alias* before-paragraph* after-paragraph* #'(level ...) (parse-elt #'term) #t #'receiver)] - [((BINOP (level ...) term) => receiver) - (make-binop-clause nt alias* before-paragraph* after-paragraph* #'(level ...) (parse-elt #'term) #f #'receiver)] - [(prod prods ...) - (make-regular-clause nt alias* before-paragraph* after-paragraph* (map parse-production #'(prod prods ...)))] - [else (syntax-error clause)])) - (define (parse-top top* knull kgrammar ksection kclause) - (if (null? top*) - (knull) - (let ([top (car top*)] [top* (cdr top*)]) - (syntax-case top (GRAMMAR SECTION SUPPRESSED DESCRIPTION BINOP TERMINALS src =>) - [(GRAMMAR title paragraph ...) - (andmap paragraph? #'(paragraph ...)) - (kgrammar top* (datum title) #'(paragraph ...))] - [(SECTION SUPPRESSED title paragraph ...) - (andmap paragraph? #'(paragraph ...)) - (ksection top* (datum title) #'(paragraph ...) #t)] - [(SECTION title paragraph ...) - (andmap paragraph? #'(paragraph ...)) - (ksection top* (datum title) #'(paragraph ...) #f)] - [(TERMINALS term ...) - (kclause top* (make-terminal-clause (map parse-terminal #'(term ...))))] - [(TERMINALS term ...) - (kclause top* (make-terminal-clause (map parse-terminal #'(term ...))))] - [(nt (alias ...) (DESCRIPTION paragraph1 ...) stuff ... (DESCRIPTION paragraph2 ...)) - (and (identifier? #'nt) (andmap identifier? #'(alias ...)) (andmap paragraph? #'(paragraph1 ...)) (andmap paragraph? #'(paragraph2 ...))) - (kclause top* (parse-clause top #'nt #'(alias ...) #'(paragraph1 ...) #'(paragraph2 ...) #'(stuff ...)))] - [(nt (alias ...) (DESCRIPTION paragraph ...) stuff ...) - (and (identifier? #'nt) (andmap identifier? #'(alias ...)) (andmap paragraph? #'(paragraph ...))) - (kclause top* (parse-clause top #'nt #'(alias ...) #'(paragraph ...) '() #'(stuff ...)))] - [(nt (alias ...) stuff ... (DESCRIPTION paragraph ...)) - (and (identifier? #'nt) (andmap identifier? #'(alias ...)) (andmap paragraph? #'(paragraph ...))) - (kclause top* (parse-clause top #'nt #'(alias ...) '() #'(paragraph ...) #'(stuff ...)))] - [(nt (alias ...) stuff ...) - (and (identifier? #'nt) (andmap identifier? #'(alias ...))) - (kclause top* (parse-clause top #'nt #'(alias ...) '() '() #'(stuff ...)))])))) - (define (parse-grammar top*) - (define (misplaced-grammar-error top) - (syntax-error top "unexpected GRAMMAR element after other elements")) - (define (s1 top*) ; looking for GRAMMAR form, first SECTION form, or clause - (parse-top top* - (lambda () (make-grammar #f '() '())) - (lambda (top* title paragraph*) - (make-grammar title paragraph* (s2 top*))) - (lambda (top* title paragraph* suppressed?) - (make-grammar #f '() - (s3 top* title paragraph* suppressed? '() '()))) - (lambda (top* clause) - (make-grammar #f '() - (s3 top* #f '() #f (list clause) '()))))) - (define (s2 top*) ; looking for first SECTION form or clause - (parse-top top* - (lambda () '()) - (lambda (title paragraph*) (misplaced-grammar-error (car top*))) - (lambda (top* title paragraph* suppressed?) - (s3 top* title paragraph* suppressed? '() '())) - (lambda (top* clause) - (s3 top* #f '() #f (list clause) '())))) - (define (s3 top* title paragraph* suppressed? rclause* rsection*) ; steady state: looking for remaining SECTION forms and clauses - (define (finish-section) - (cons (make-section title paragraph* suppressed? (reverse rclause*)) rsection*)) - (parse-top top* - (lambda () (reverse (finish-section))) - (lambda (title paragraph*) (misplaced-grammar-error (car top*))) - (lambda (top* title paragraph* suppressed?) - (s3 top* title paragraph* suppressed? '() (finish-section))) - (lambda (top* clause) - (s3 top* title paragraph* suppressed? (cons clause rclause*) rsection*)))) - (s1 top*))) - (define (go init-nts top* mddir) - (let ([grammar (parse-grammar top*)]) - (let* ([clause* (apply append (map section-clause* (grammar-section* grammar)))] - [terminal-clause* (filter terminal-clause? clause*)] - [binop-clause* (filter binop-clause? clause*)] - [regular-clause* (left-factor (filter regular-clause? clause*))] - [env (make-env terminal-clause* (append binop-clause* regular-clause*))]) - (define (elt-helper x) - (cond - [(sep-elt? x) #`(#,(if (sep-elt-+? x) #'sepby1 #'sepby) #,(elt-helper (sep-elt-elt x)) (sep->parser #,(sep-elt-sep x)))] - [(opt-elt? x) #`(optional #,(elt-helper (opt-elt-elt x)) #,(opt-elt-default x))] - [(kleene-elt? x) #`(#,(if (kleene-elt-+? x) #'many+ #'many) #,(elt-helper (kleene-elt-elt x)))] - [(constant-elt? x) #`(constant->parser '#,(constant-elt-k x))] - [(id-elt? x) (lookup (id-elt-id x) env)] - [else (errorf 'elt-helper "unhandled elt ~s\n" x)])) - (define (binop-helper clause) - #`[#,(clause-id clause) - (infix-expression-parser - #,(map (lambda (level) - (syntax-case level () - [(L/R op1 ... op2) - (or (free-identifier=? #'L/R #'LEFT) (free-identifier=? #'L/R #'RIGHT)) - #`(L/R #,(fold-right (lambda (op next) #`(++ (binop->parser '#,op) #,next)) #'(binop->parser 'op2) #'(op1 ...)))])) - (binop-clause-level* clause)) - #,(elt-helper (binop-clause-term clause)) - #,(binop-clause-receiver clause))]) - (define (nt-helper clause) - #`[#,(clause-id clause) - #,(let f ([prod* (regular-clause-prod* clause)]) - (if (null? prod*) - #'zero - (let ([elt* (production-elt* (car prod*))]) - (with-syntax ([name (production-name (car prod*))] - [(elt ...) elt*] - [receiver (production-receiver (car prod*))]) - (with-syntax ([(x ...) (generate-temporaries elt*)]) - (with-syntax ([([y _] ...) (filter (lambda (pr) (not (constant-elt? (cadr pr)))) #'([x elt] ...))]) - (with-syntax ([(where-nt ...) (map elt-helper elt*)]) - #`(+++ ;; use +++ if you don't ever need to backtrack to a previous production for the same non-terminal - (lambda (inp) - (when (and 'name (grammar-trace)) (printf ">>~s(~a)~%" 'name (format-inp inp))) - (let ([res ((trace-is name (lambda (bfp efp) (receiver bfp efp y ...)) (where [x <- where-nt] ...)) inp)]) - (when (and 'name (grammar-trace)) - (if (stream-null? res) - (printf "<<~s(~a) failed~%" 'name (format-inp inp)) - (printf "<<~s(~a) succeeded~%" 'name (format-inp inp)))) - res)) - #,(f (cdr prod*))))))))))]) - (with-syntax ([(init-nt ...) - (syntax-case init-nts () - [(id1 id2 ...) (andmap identifier? #'(id1 id2 ...)) #'(id1 id2 ...)] - [id (identifier? #'id) (list #'id)])]) - (when mddir - (for-each - (lambda (init-nt) - (let ([mdfn (format "~a/~a.md" mddir (syntax->datum init-nt))]) - (render-markdown init-nt grammar mdfn env))) - #'(init-nt ...))) - (with-syntax ([((lhs rhs) ...) - (append - (map binop-helper binop-clause*) - (map nt-helper regular-clause*))]) - #'(module (init-nt ...) - (module M (init-nt ...) (define lhs rhs) ...) - (define init-nt - (let () - (import M) - (make-top-level-parser init-nt))) - ...)))))) - (syntax-case x (markdown-directory) - [(_ init-nts (markdown-directory mddir) top ...) - (string? (datum mddir)) - (go #'init-nts #'(top ...) (datum mddir))] - [(_ init-nts top ...) (go #'init-nts #'(top ...) #f)]))) - - (indirect-export define-grammar - result - zero - is - trace-is - sepby1 - sepby - optional - many - many+ - +++ - infix-expression-parser - - grammar-trace - format-inp - trace-is - - make-top-level-parser - ) -) diff --git a/ta6ob/examples/fact.ss b/ta6ob/examples/fact.ss deleted file mode 100644 index 037cd2c..0000000 --- a/ta6ob/examples/fact.ss +++ /dev/null @@ -1,11 +0,0 @@ -;;; simple factorial function - -;;; it is interesting to change the 'lambda' into 'trace-lambda' -;;; or simply type (trace fact) before running fact to observe -;;; the nesting of recursive calls. - -(define fact - (lambda (x) - (if (zero? x) - 1 - (* x (fact (1- x)))))) diff --git a/ta6ob/examples/fatfib.ss b/ta6ob/examples/fatfib.ss deleted file mode 100644 index 6f150e2..0000000 --- a/ta6ob/examples/fatfib.ss +++ /dev/null @@ -1,19 +0,0 @@ -;;; fat fibonacci function - -;;; this is "fat" because it uses only increments and decrements -;;; for addition and subtraction (i.e., peano arithmetic). - -;;; note that fat+ is tail-recursive; this is how all looping is -;;; performed in Scheme. - -(define fat+ - (lambda (x y) - (if (zero? y) - x - (fat+ (1+ x) (1- y))))) - -(define fatfib - (lambda (x) - (if (< x 2) - 1 - (fat+ (fatfib (1- x)) (fatfib (1- (1- x))))))) diff --git a/ta6ob/examples/fft.ss b/ta6ob/examples/fft.ss deleted file mode 100644 index edcb407..0000000 --- a/ta6ob/examples/fft.ss +++ /dev/null @@ -1,63 +0,0 @@ -;;; fft.ss -;;; Copyright (C) 1996 R. Kent Dybvig -;;; from "The Scheme Programming Language, 2ed" by R. Kent Dybvig - -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -(define (dft x) - (define (w-powers n) - (let ((pi (* (acos 0.0) 2))) - (let ((delta (/ (* -2.0i pi) n))) - (let f ((n n) (x 0.0)) - (if (= n 0) - '() - (cons (exp x) (f (- n 2) (+ x delta)))))))) - (define (evens w) - (if (null? w) - '() - (cons (car w) (evens (cddr w))))) - (define (interlace x y) - (if (null? x) - '() - (cons (car x) (cons (car y) (interlace (cdr x) (cdr y)))))) - (define (split ls) - (let split ((fast ls) (slow ls)) - (if (null? fast) - (values '() slow) - (call-with-values - (lambda () (split (cddr fast) (cdr slow))) - (lambda (front back) - (values (cons (car slow) front) back)))))) - (define (butterfly x w) - (call-with-values - (lambda () (split x)) - (lambda (front back) - (values - (map + front back) - (map * (map - front back) w))))) - (define (rfft x w) - (if (null? (cddr x)) - (let ((x0 (car x)) (x1 (cadr x))) - (list (+ x0 x1) (- x0 x1))) - (call-with-values - (lambda () (butterfly x w)) - (lambda (front back) - (let ((w (evens w))) - (interlace (rfft front w) (rfft back w))))))) - (rfft x (w-powers (length x)))) diff --git a/ta6ob/examples/fib.ss b/ta6ob/examples/fib.ss deleted file mode 100644 index 12e3155..0000000 --- a/ta6ob/examples/fib.ss +++ /dev/null @@ -1,9 +0,0 @@ -;;; simple fibonacci function - -;;; uses trace-lambda to show the nesting - -(define fib - (trace-lambda fib (x) - (if (<= x 1) - 1 - (+ (fib (- x 1)) (fib (- x 2)))))) diff --git a/ta6ob/examples/foreign.ss b/ta6ob/examples/foreign.ss deleted file mode 100644 index dd68f56..0000000 --- a/ta6ob/examples/foreign.ss +++ /dev/null @@ -1,179 +0,0 @@ -;;; foreign.ss -;;; Copyright (c) 1997 R. Kent Dybvig - -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -;;; Prototype code for converting ``foreign-callable'' declarations into -;;; C interface routines to support C calls to Scheme procedures with -;;; automatic datatype conversion analogous to that provided for Scheme -;;; calls to C procedures via foreign-procedure. - -;;; Todo -;;; - support for foreign-pointer and foreign-object -;;; - similar support for foreign-procedure declarations - -(define spec->decl - (lambda (spec) - (case spec - [(integer-32 boolean) "int"] - [(unsigned-32) "unsigned int"] - [(char) "char"] - [(string) "char *"] - [(fixnum) "int"] - [(double-float) "double"] - [(single-float) "float"] - [(void) "void"] - [(scheme-object) "ptr"] - [else - (record-case spec - [(foreign-pointer foreign-object) () - (error 'spec->decl "unsupported specifier ~s" spec)] - [else (error 'spec->decl "unexpected specifier ~s" spec)])]))) - -(define C->Scheme - (lambda (spec id) - (case spec - [(boolean) (format "Sboolean(~a)" id)] - [(char) (format "Schar(~a)" id)] - [(fixnum) (format "Sfixnum(~a)" id)] - [(integer-32) (format "Sinteger(~a)" id)] - [(unsigned-32) (format "Sunsigned(~a)" id)] - [(single-float) (format "Sflonum((double)~a)" id)] - [(double-float) (format "Sflonum(~a)" id)] - [(scheme-object) id] - [(string) (format "Sstring(~a)" id)] - [else - (record-case spec - [(foreign-pointer foreign-object) () - (error 'C->Scheme "unsupported specifier ~s" spec)] - [else (error 'C->Scheme "unexpected specifier ~s" spec)])]))) - -(define Scheme->C - (lambda (op spec src) - (case spec - [(boolean) (fprintf op "Sboolean_value(~a)" src)] - [(char) (fprintf op "Schar_value(~a)" src)] - [(fixnum) (fprintf op "Sfixnum_value(~a)" src)] - [(integer-32) (fprintf op "Sinteger_value(~a)" src)] - [(unsigned-32) (fprintf op "Sunsigned_value(~a)" src)] - [(single-float) (fprintf op "(float)Sflonum_value(~a)" src)] - [(double-float) (fprintf op "Sflonum_value(~a)" src)] - [(scheme-object) (display src op)] - [(string) (fprintf op "Sstring_value(~a)" src)] - [else - (record-case spec - [(foreign-pointer foreign-object) () - (error 'Scheme->C "unsupported specifier ~s" spec)] - [else (error 'Scheme->C "unexpected specifier ~s" spec)])]))) - -(define gen-fcallable - (case-lambda - [(cname arg-specs res-spec) - (gen-fcallable (current-output-port) cname arg-specs res-spec)] - [(op cname arg-specs res-spec) - (let ((names (let loop ((ls arg-specs) (i 1)) - (if (null? ls) - '() - (cons (format "x~d" i) (loop (cdr ls) (+ i 1)))))) - (count (length arg-specs))) - (newline op) - (fprintf op "~a ~a(ptr proc" (spec->decl res-spec) cname) ;) - (let loop ((arg-specs arg-specs) (names names)) - (unless (null? arg-specs) - (fprintf op ", ~a ~a" (spec->decl (car arg-specs)) (car names)) - (loop (cdr arg-specs) (cdr names)))) ;( - (fprintf op ") {~%") - (if (<= 0 count 3) - (begin - (display " return " op) - (Scheme->C op res-spec - (let ((op (open-output-string))) - (fprintf op "Scall~d(proc" count) ;) - (let loop ((arg-specs arg-specs) (names names)) - (unless (null? arg-specs) - (display ", " op) - (display (C->Scheme (car arg-specs) (car names)) op) - (loop (cdr arg-specs) (cdr names)))) ;( - (fprintf op ")") - (get-output-string op)))) - (begin - (fprintf op " Sinitframe(~d);~%" count) - (let loop ([arg-specs arg-specs] [names names] [num 1]) - (unless (null? arg-specs) - (fprintf op " Sput_arg(~d, ~a);~%" - num (C->Scheme (car arg-specs) (car names))) - (loop (cdr arg-specs) (cdr names) (+ num 1)))) - (fprintf op " return ") - (Scheme->C op res-spec - (format "Scall(proc, ~d)" count)))) - (fprintf op ";~%}~%"))])) - -(define-syntax foreign-callable - (syntax-rules () - ((_ n args res) - (gen-fcallable n 'args 'res)))) - -(define gen-file - (lambda (fnroot) - (let ((ifn (format "~a.ss" fnroot)) - (ofn (format "~a.xx" fnroot))) - (with-output-to-file ofn - (lambda () (load ifn)) - 'replace)))) - -#!eof ; cut off the input here so we can give examples w/o comment chars - -Example input file: - ------------------------------------------------------------------------- -(foreign-callable "foo" - (boolean single-float double-float) - scheme-object) - -(foreign-callable "bar" - (boolean char integer-32 unsigned-32 single-float - double-float scheme-object) - string) - -(foreign-callable "baz" () fixnum) ------------------------------------------------------------------------- - -Generated output file: - ------------------------------------------------------------------------- -ptr foo(ptr proc, int x1, float x2, double x3) { - return Scall3(proc, Sboolean(x1), Sflonum((double)x2), Sflonum(x3)); -} - -char * bar(ptr proc, int x1, char x2, int x3, unsigned int x4, float x5, double x6, ptr x7) { - Sinitframe(7); - Sput_arg(1, Sboolean(x1)); - Sput_arg(2, Schar(x2)); - Sput_arg(3, Sinteger(x3)); - Sput_arg(4, Sunsigned(x4)); - Sput_arg(5, Sflonum((double)x5)); - Sput_arg(6, Sflonum(x6)); - Sput_arg(7, x7); - return Sstring_value(Scall(proc, 7)); -} - -int baz(ptr proc) { - return Sfixnum_value(Scall0(proc)); -} ------------------------------------------------------------------------- diff --git a/ta6ob/examples/freq.ss b/ta6ob/examples/freq.ss deleted file mode 100644 index a036676..0000000 --- a/ta6ob/examples/freq.ss +++ /dev/null @@ -1,123 +0,0 @@ -;;; freq.ss -;;; Copyright (C) 1996 R. Kent Dybvig -;;; from "The Scheme Programming Language, 2ed" by R. Kent Dybvig - -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -;;; If the next character on p is a letter, get-word reads a word -;;; from p and returns it in a string. If the character is not a -;;; letter, get-word returns the character (on eof, the eof-object). -(define get-word - (lambda (p) - (let ((c (read-char p))) - (if (eq? (char-type c) 'letter) - (list->string - (let loop ((c c)) - (cons c - (if (memq (char-type (peek-char p)) '(letter digit)) - (loop (read-char p)) - '())))) - c)))) - -;;; char-type tests for the eof-object first, since the eof-object -;;; may not be a valid argument to char-alphabetic? or char-numeric? -;;; It returns the eof-object, the symbol letter, the symbol digit, -;;; or the argument itself if it is not a letter or digit. -(define char-type - (lambda (c) - (cond - ((eof-object? c) c) - ((char-alphabetic? c) 'letter) - ((char-numeric? c) 'digit) - (else c)))) - -;;; Trees are represented as vectors with four fields: word, left, -;;; right, and count. Only one field, word, is initialized by an -;;; argument to the constructor procedure make-tree. The remaining -;;; fields are explicitly initialized and changed by subsequent -;;; operations. Most Scheme systems provide structure definition -;;; facilities that automate creation of structure manipulation -;;; procedures, but we simply define the procedures by hand here. -(define make-tree - (lambda (word) - (vector word '() '() 1))) - -(define tree-word (lambda (tree) (vector-ref tree 0))) - -(define tree-left (lambda (tree) (vector-ref tree 1))) -(define set-tree-left! - (lambda (tree new-left) - (vector-set! tree 1 new-left))) - -(define tree-right (lambda (tree) (vector-ref tree 2))) -(define set-tree-right! - (lambda (tree new-right) - (vector-set! tree 2 new-right))) - -(define tree-count (lambda (tree) (vector-ref tree 3))) -(define set-tree-count! - (lambda (tree new-count) - (vector-set! tree 3 new-count))) - -;;; If the word already exists in the tree, tree increments its -;;; count. Otherwise, a new tree node is created and put into the -;;; tree. In any case, the new or modified tree is returned. -(define tree - (lambda (node word) - (cond - ((null? node) (make-tree word)) - ((string=? word (tree-word node)) - (set-tree-count! node (+ (tree-count node) 1)) - node) - ((stringlist s) (ibuf-pb ib))))) - -(define int->str - (lambda (num) - (format "~s" num))) - -(define char->digit - (let ([zero (char->integer #\0)]) - (lambda (c) - (- (char->integer c) zero)))) - -(define str->int - (let ([ustr->int - (lambda (s i n) - (let f ([a 0] [i i]) - (if (= i n) - a - (f (+ (* a 10) (char->digit (string-ref s i))) - (+ i 1)))))]) - (lambda (s) - (let ([n (string-length s)]) - (if (= n 0) - 0 - (if (char=? (string-ref s 0) #\-) - (- (ustr->int s 1 n)) - (ustr->int s 0 n))))))) - -(define eval-string - (let ([str #f] [port #f] [token #f] [value #f]) - (define eval-error - (lambda () - (error 'm4 "invalid arithmetic expression ~s" str))) - (define next-token! - (lambda () - (let ([c (read-char port)]) - (cond - [(eof-object? c) (set! token 'eof)] - [(char-whitespace? c) (next-token!)] - [(char-numeric? c) - (let loop ([a (char->digit c)]) - (let ([c (read-char port)]) - (cond - [(eof-object? c) - (set! token 'integer) - (set! value a)] - [(char-numeric? c) - (loop (+ (* a 10) (char->digit c)))] - [else - (unread-char c port) - (set! token 'integer) - (set! value a)])))] - [(char=? c oparen) (set! token 'oparen)] - [(char=? c cparen) (set! token 'cparen)] - [(char=? c #\-) (set! token '-)] - [(char=? c #\*) - (let ([c (read-char port)]) - (cond - [(eof-object? c) (set! token '*)] - [(char=? c #\*) (set! token '**)] - [else (unread-char c port) (set! token '*)]))] - [(char=? c #\+) (set! token '+)] - [(char=? c #\-) (set! token '+)] - [(char=? c #\/) (set! token '/)] - [(char=? c #\%) (set! token '%)] - [(char=? c #\!) - (let ([c (read-char port)]) - (cond - [(eof-object? c) (set! token '!)] - [(char=? c #\=) (set! token '!=)] - [else (unread-char c port) (set! token '!)]))] - [(char=? c #\|) - (let ([c (read-char port)]) - (cond - [(eof-object? c) (eval-error)] - [(char=? c #\|) (set! token 'or)] - [else (unread-char c port) (eval-error)]))] - [(char=? c #\&) - (let ([c (read-char port)]) - (cond - [(eof-object? c) (eval-error)] - [(char=? c #\&) (set! token 'and)] - [else (unread-char c port) (eval-error)]))] - [(char=? c #\=) - (let ([c (read-char port)]) - (cond - [(eof-object? c) (eval-error)] - [(char=? c #\=) (set! token '==)] - [else (unread-char c port) (eval-error)]))] - [(char=? c #\<) - (let ([c (read-char port)]) - (cond - [(eof-object? c) (set! token '<)] - [(char=? c #\=) (set! token '<=)] - [else (unread-char c port) (set! token '<)]))] - [(char=? c #\>) - (let ([c (read-char port)]) - (cond - [(eof-object? c) (set! token '>)] - [(char=? c #\=) (set! token '>=)] - [else (unread-char c port) (set! token '>)]))])))) - (define E0 ; or - (lambda () - (E0* (E1)))) - (define E0* - (lambda (v) - (case token - [or (next-token!) (E0* (if (= (+ v (E1)) 0) 0 1))] - [else v]))) - (define E1 ; and - (lambda () - (E1* (E2)))) - (define E1* - (lambda (v) - (case token - [and (next-token!) (E1* (if (= (* v (E2)) 0) 0 1))] - [else v]))) - (define E2 ; ==, != - (lambda () - (E2* (E3)))) - (define E2* - (lambda (v) - (case token - [== (next-token!) (E2* (if (= v (E3)) 1 0))] - [!= (next-token!) (E2* (if (= v (E3)) 0 1))] - [else v]))) - (define E3 ; <, <=, >, >= - (lambda () - (E3* (E4)))) - (define E3* - (lambda (v) - (case token - [< (next-token!) (E3* (if (< v (E4)) 1 0))] - [<= (next-token!) (E3* (if (<= v (E4)) 1 0))] - [> (next-token!) (E3* (if (> v (E4)) 1 0))] - [>= (next-token!) (E3* (if (>= v (E4)) 1 0))] - [else v]))) - (define E4 ; +, - - (lambda () - (E4* (E5)))) - (define E4* - (lambda (v) - (case token - [+ (next-token!) (E4* (+ v (E5)))] - [- (next-token!) (E4* (- v (E5)))] - [else v]))) - (define E5 ; *, /, % - (lambda () - (E5* (E6)))) - (define E5* - (lambda (v) - (case token - [* (next-token!) (E5* (* v (E6)))] - [/ (next-token!) (E5* (quotient v (E6)))] - [% (next-token!) (E5* (modulo v (E6)))] - [else v]))) - (define E6 ; ** - (lambda () - (E6* (E7)))) - (define E6* - (lambda (v) - (case token - [** (next-token!) (E6* (expt v (E7)))] - [else v]))) - (define E7 ; -, integer, paren - (lambda () - (case token - [- (next-token!) (- (E7))] - [! (next-token!) (if (= (E7) 0) 1 0)] - [oparen - (next-token!) - (let ([v (E0)]) - (unless (eq? token 'cparen) (eval-error)) - (next-token!) - v)] - [integer (next-token!) value] - [else (eval-error)]))) - (lambda (s) - (fluid-let ([str s] [port (open-input-string s)] [token #f] [value #f]) - (next-token!) - (let ([v (E0)]) - (unless (eq? token 'eof) (eval-error)) - v))))) - -(define *divnum* #f) -(define *diversions* #f) - -(define m4-put-string - (lambda (s) - (unless (= *divnum* -1) - (display s (vector-ref *diversions* *divnum*))))) - -(define *open-quote* #f) -(define *close-quote* #f) - -(define *macros* #f) -(define builtin-macros '()) - -(define *translit-table* #f) - -(define define-builtin-macro - (lambda (name proc) - (set! builtin-macros (cons (cons name proc) builtin-macros)))) - -(define m4 - (lambda (ofn ifn . rest) - (let ([op (open-output-file ofn 'replace)]) - (fluid-let ([*macros* builtin-macros] - [*open-quote* #\`] - [*close-quote* #\'] - [*translit-table* #f] - [*divnum* 0] - [*diversions* (vector op #f #f #f #f #f #f #f #f #f)]) - (let loop ([ip (open-input-file ifn)] [rest rest]) - (m4-process (make-ibuf ip) op) - (close-input-port ip) - (unless (null? rest) - (loop (open-input-file (car rest)) (cdr rest)))) - (for-each undivert '(1 2 3 4 5 6 7 8 9))) - (close-output-port op)))) - -(define m4-process - (lambda (ib op) - (let ([lexeme (read-lexeme ib)]) - (case (lexeme-type lexeme) - [(comment literal) - (m4-put-string (lexeme-value lexeme)) - (m4-process ib op)] - [macro - ((cdr (lexeme-value lexeme)) (read-args ib) ib) - (m4-process ib op)] - [eof #t] - [else (error 'm4-internal "unexpected lexeme ~s" lexeme)])))) - -(define name-start-char? - (lambda (c) - (or (char-alphabetic? c) - (char=? c #\_)))) - -(define name-char? - (lambda (c) - (or (name-start-char? c) - (char-numeric? c)))) - -(define read-lexeme - (lambda (ib) - (let ([c (m4-get-char ib)]) - (cond - [(eof-object? c) (cons 'eof c)] - [(char=? c #\#) (cons 'comment (read-comment ib))] - [(char=? c *open-quote*) (cons 'literal (read-quoted ib))] - [(name-start-char? c) (lookup-macro (cons c (read-alpha ib)))] - [else (cons 'literal (string c))])))) - -(define read-comment - (lambda (ib) - (let loop ([ls '(#\#)]) - (let ([c (m4-get-char ib)]) - (cond - [(eof-object? c) (list->string (reverse ls))] - [(char=? c #\newline) (list->string (reverse (cons c ls)))] - [else (loop (cons c ls))]))))) - -(define read-quoted - (lambda (ib) - (let loop ([ls '()] [n 0]) - (let ([c (m4-get-char ib)]) - (cond - [(eof-object? c) - (error 'm4 "end-of-file detected at quote level ~s" n)] - [(char=? c *close-quote*) - (if (= n 0) - (list->string (reverse ls)) - (loop (cons c ls) (- n 1)))] - [(char=? c *open-quote*) (loop (cons c ls) (+ n 1))] - [else (loop (cons c ls) n)]))))) - -(define read-alpha - (lambda (ib) - (let ([c (m4-get-char ib)]) - (cond - [(eof-object? c) '()] - [(name-char? c) (cons c (read-alpha ib))] - [else (m4-unget-char c ib) '()])))) - -(define lookup-macro - (lambda (ls) - (let ([s (list->string ls)]) - (let ([a (assoc s *macros*)]) - (if a - (cons 'macro a) - (cons 'literal s)))))) - -(define read-args - (lambda (ib) - (let ([c (m4-get-char ib)]) - (cond - [(eof-object? c) '()] - [(char=? c oparen) - (let next-arg () - (let skip-white () - (let ([c (m4-get-char ib)]) - (cond - [(eof-object? c) '()] - [(char-whitespace? c) (skip-white)] - [else (m4-unget-char c ib)]))) - (let this-arg ([strings '()]) - (let ([c (m4-get-char ib)]) - (cond - [(or (eof-object? c) (char=? c cparen)) - (if (null? strings) - '() - (cons (apply string-append (reverse strings)) - '()))] - [(char=? c oparen) - (let nest ([strings (cons (string oparen) - strings)] - [k this-arg]) - (let ([c (m4-get-char ib)]) - (cond - [(eof-object? c) (this-arg strings)] - [(char=? c cparen) - (k (cons (string cparen) strings))] - [(char=? c oparen) - (nest (cons (string oparen) strings) - (lambda (strings) - (nest strings k)))] - [else - (m4-unget-char c ib) - (let ([lexeme (read-lexeme ib)]) - (case (lexeme-type lexeme) - [comment (nest strings k)] - [literal - (nest (cons (lexeme-value lexeme) - strings) - k)] - [macro - ((cdr (lexeme-value lexeme)) - (read-args ib) - ib) - (nest strings k)] - [else - (error 'm4-internal - "unexpected lexeme ~s" - lexeme)]))])))] - [(char=? c #\,) - (cons (apply string-append (reverse strings)) - (next-arg))] - - [else - (m4-unget-char c ib) - (let ([lexeme (read-lexeme ib)]) - (case (lexeme-type lexeme) - [comment (this-arg strings)] - [literal - (this-arg - (cons (lexeme-value lexeme) strings))] - [macro - ((cdr (lexeme-value lexeme)) (read-args ib) ib) - (this-arg strings)] - [else - (error 'm4-internal - "unexpected lexeme ~s" - lexeme)]))]))))] - [else (m4-unget-char c ib) '()])))) - -;;; builtin macros - -(define $$ (lambda (ls) (if (null? ls) ls (cdr ls)))) -(define $1 (lambda (ls) (if (null? ls) "" (car ls)))) -(define $2 (lambda (ls) ($1 ($$ ls)))) -(define $3 (lambda (ls) ($2 ($$ ls)))) -(define $4 (lambda (ls) ($3 ($$ ls)))) -(define $5 (lambda (ls) ($4 ($$ ls)))) -(define $6 (lambda (ls) ($5 ($$ ls)))) -(define $7 (lambda (ls) ($6 ($$ ls)))) -(define $8 (lambda (ls) ($7 ($$ ls)))) -(define $9 (lambda (ls) ($8 ($$ ls)))) - -(define-builtin-macro "changequote" - (lambda (args ib) - (set! *open-quote* - (if (string=? ($1 args) "") #\` (string-ref ($1 args) 0))) - (set! *close-quote* - (if (string=? ($2 args) "") #\' (string-ref ($2 args) 0))))) - -(define-builtin-macro "define" - (lambda (args ib) - (let ([name ($1 args)]) - (unless (let ([n (string-length name)]) - (and (fx> n 0) - (name-start-char? (string-ref name 0)) - (let ok? ([i 1]) - (or (fx= i n) - (and (name-char? (string-ref name i)) - (ok? (fx+ i 1))))))) - (error 'm4-define "invalid macro name ~s" name)) - (let ([proc (make-macro ($2 args))]) - (let ([a (assoc name *macros*)]) - (if a - (set-cdr! a proc) - (set! *macros* (cons (cons name proc) *macros*)))))))) - -(define make-macro - (lambda (s) - (let ([ls (string->list s)]) - (lambda (args ib) - (let loop ([ls ls]) - (unless (null? ls) - (case (and (char=? (car ls) #\$) - (not (null? (cdr ls))) - (cadr ls)) - [#\1 (loop (cddr ls)) (unget-string ($1 args) ib)] - [#\2 (loop (cddr ls)) (unget-string ($2 args) ib)] - [#\3 (loop (cddr ls)) (unget-string ($3 args) ib)] - [#\4 (loop (cddr ls)) (unget-string ($4 args) ib)] - [#\5 (loop (cddr ls)) (unget-string ($5 args) ib)] - [#\6 (loop (cddr ls)) (unget-string ($6 args) ib)] - [#\7 (loop (cddr ls)) (unget-string ($7 args) ib)] - [#\8 (loop (cddr ls)) (unget-string ($8 args) ib)] - [#\9 (loop (cddr ls)) (unget-string ($9 args) ib)] - [else (loop (cdr ls)) (m4-unget-char (car ls) ib)]))))))) - -(define-builtin-macro "divert" - (lambda (args ib) - (set! *divnum* - (if (string=? ($1 args) "") - 0 - (case (string-ref ($1 args) 0) - [#\0 0] - [#\1 1] - [#\2 2] - [#\3 3] - [#\4 4] - [#\5 5] - [#\6 6] - [#\7 7] - [#\8 8] - [#\9 9] - [else -1]))) - (when (and (<= 1 *divnum* 9) (not (vector-ref *diversions* *divnum*))) - (vector-set! *diversions* *divnum* (open-output-string))))) - -(define-builtin-macro "divnum" - (lambda (args ib) - (unget-string (format "~a" *divnum*) ib))) - -(define-builtin-macro "dnl" - (lambda (args ib) - (let loop () - (let ([c (m4-get-char ib)]) - (cond - [(eof-object? c) '()] - [(char=? c #\newline) '()] - [else (loop)]))))) - -(define-builtin-macro "dumpdef" - (lambda (args ib) - (printf "m4 warning: no dumpdef yet~%"))) - -(define-builtin-macro "errprint" - (lambda (args ib) - (display ($1 args) *error-output*) - (newline *error-output*))) - -(define-builtin-macro "eval" - (lambda (args ib) - (unget-string (int->str (eval-string ($1 args))) ib))) - -(define-builtin-macro "ifdef" - (lambda (args ib) - (unget-string ((if (assoc ($1 args) *macros*) $2 $3) args) ib))) - -(define-builtin-macro "ifelse" - (rec ifelse - (lambda (args ib) - (if (string=? ($1 args) ($2 args)) - (unget-string ($3 args) ib) - (if (> (length args) 4) - (ifelse ($$ ($$ ($$ args))) ib) - (unget-string ($4 args) ib)))))) - -(define-builtin-macro "include" - (lambda (args ib) - (printf "m4 warning: no include yet~%"))) - -(define-builtin-macro "incr" - (lambda (args ib) - (unget-string (int->str (+ (str->int ($1 args)) 1)) ib))) - -(define-builtin-macro "index" - (lambda (args ib) - (let ([s1 ($1 args)] [s2 ($2 args)]) - (let ([n1 (string-length s1)] [n2 (string-length s2)]) - (let find ([i 0]) - (if (fx> n2 (fx- n1 i)) - (unget-string "-1" ib) - (let try ([i1 i] [i2 0]) - (if (fx= i2 n2) - (unget-string (int->str i) ib) - (if (char=? (string-ref s1 i1) (string-ref s2 i2)) - (try (fx+ i1 1) (fx+ i2 1)) - (find (fx+ i 1))))))))))) - -(define-builtin-macro "len" - (lambda (args ib) - (unget-string (int->str (string-length ($1 args))) ib))) - -(define-builtin-macro "maketemp" - (lambda (args ib) - (printf "m4 warning: no maketemp yet~%"))) - -(define-builtin-macro "shift" - (lambda (args ib) - (printf "m4 warning: no shift yet~%"))) - -(define-builtin-macro "sinclude" - (lambda (args ib) - (printf "m4 warning: no sinclude yet~%"))) - -(define-builtin-macro "substr" - (lambda (args ib) - (let ([s ($1 args)] [start ($2 args)] [count ($3 args)]) - (let ([n (string-length s)]) - (let ([start (min (max (str->int start) 0) n)]) - (let ([end (if (string=? count "") - n - (min (max (+ (str->int count) start) start) n))]) - (unget-string (substring s start end) ib))))))) - -(define-builtin-macro "syscmd" - ;;; cannot be written in Scheme---needs something more powerful than - ;;; "system" or "process" - (lambda (args ib) - (printf "m4 warning: no syscmd yet~%"))) - -(define-builtin-macro "translit" - (lambda (args ib) - (let ([s1 ($1 args)] [s2 ($2 args)] [s3 ($3 args)]) - (let ([n1 (string-length s1)] [n2 (string-length s2)]) - (unless (= n2 (string-length s3)) - (error 'm4 "translit arguments ~s and ~s are not of same length" - s2 s3)) - (when (null? *translit-table*) - (set! *translit-table* (make-string 256))) - (do ([i 0 (fx+ i 1)]) - ((fx= i 256)) - (string-set! *translit-table* i (integer->char i))) - (do ([i 0 (fx+ i 1)]) - ((fx= i n2)) - (string-set! *translit-table* - (char->integer (string-ref s2 i)) - (string-ref s3 i))) - (let ([s4 (make-string n1)]) - (do ([i 0 (fx+ i 1)]) - ((fx= i n1)) - (string-set! s4 i - (string-ref *translit-table* - (char->integer (string-ref s1 i))))) - (unget-string s4 ib)))))) - -(define-builtin-macro "undefine" - (lambda (args ib) - (let ([a (assoc ($1 args) *macros*)]) - (unless a (error 'm4 "cannot undefine ~s (not defined)" ($1 args))) - (set-car! a #f)))) - -(define-builtin-macro "undivert" - (rec myself - (lambda (args ib) - (if (null? args) - (myself '("1" "2" "3" "4" "5" "6" "7" "8" "9") ib) - (for-each - (lambda (x) - (case (and (not (string=? x "")) (string-ref x 0)) - [#\1 (undivert 1)] - [#\2 (undivert 2)] - [#\3 (undivert 3)] - [#\4 (undivert 4)] - [#\5 (undivert 5)] - [#\6 (undivert 6)] - [#\7 (undivert 7)] - [#\8 (undivert 8)] - [#\9 (undivert 9)])) - args))))) - -(define undivert - (lambda (n) - (let ([op (vector-ref *diversions* n)]) - (when op - (display (get-output-string op) (vector-ref *diversions* 0)))))) diff --git a/ta6ob/examples/macro.ss b/ta6ob/examples/macro.ss deleted file mode 100644 index 4b03a48..0000000 --- a/ta6ob/examples/macro.ss +++ /dev/null @@ -1,89 +0,0 @@ -;;; Copyright (C) 1989 R. Kent Dybvig - -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -;;; PCScheme/MacScheme "macro" defined in terms of "syntax-case": - -(define-syntax macro - (lambda (x) - (syntax-case x () - ((_ name fcn) - #'(define-syntax name - (lambda (x) - (syntax-case x () - ((k . stuff) - (datum->syntax-object #'k - (fcn (syntax-object->datum x))))))))))) - - -;;; PCScheme/MacScheme "macro" defined in terms of "extend-syntax": -;;; requires (current-expand eps-expand) - -;(extend-syntax (macro) -; [(macro name fcn) -; (eval-when (compile load eval) -; (let ([f fcn]) -; (extend-syntax (name) -; [anything -; ((with ([w 'with]) w) -; ([v (f 'anything)]) v)])))]) - -;;; The strange expression "(with ([w 'with]) w)" is used to insert the -;;; keyword "with" into the expansion. The "eval-when" in the expansion is -;;; necessary to allow macros defined in a file to be used later in the -;;; file, even if the file is compiled with "compile-file". If it were -;;; left out, the implicit "eval-when" wrapped around the "extend-syntax" -;;; would cause it to be evaluated, but without the enclosing "let" -;;; expression. The enclosing "let" expression is necessary to cause the -;;; function to be evaluated once, which may be important if the function -;;; something other than a simple lambda expression. - - -;;; PCScheme/MacScheme "macro" defined in terms of "define-syntax-expander": -;;; requires (current-expand eps-expand) - -;(extend-syntax (macro) -; [(macro name fcn) -; (define-syntax-expander name -; (let ([f fcn]) -; (lambda (x e) (e (f x) e))))]) - -;;; The "eval-when" is not necessary because "define-syntax-expander" -;;; expands into an "eval-when" expression, and the "let" expression is -;;; tucked inside the "define-syntax-expander" expression. - -;;; If you want to see the expander generated by either of the above -;;; "extend-syntax" definitions looks like, use "extend-syntax/code" in -;;; place of "extend-syntax": - -;;; > (extend-syntax/code (macro) -;;; [(macro name fcn) -;;; (define-syntax-expander name -;;; (let ([f fcn]) -;;; (lambda (x e) (e (f x) e))))]) -;;; -;;; (lambda (x e) -;;; (unless (procedure? e) -;;; (error 'macro "~s is not a procedure" e)) -;;; (e (cond -;;; [(syntax-match? '(macro * *) x) -;;; `(define-syntax-expander ,(cadr x) -;;; (let ([f ,@(cddr x)]) (lambda (x e) (e (f x) e))))] -;;; [else (error 'macro "invalid syntax ~s" x)]) -;;; e)) diff --git a/ta6ob/examples/matrix.ss b/ta6ob/examples/matrix.ss deleted file mode 100644 index 833f7b0..0000000 --- a/ta6ob/examples/matrix.ss +++ /dev/null @@ -1,127 +0,0 @@ -;;; matrix.ss -;;; Copyright (C) 1996 R. Kent Dybvig -;;; from "The Scheme Programming Language, 2ed" by R. Kent Dybvig - -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -;;; make-matrix creates a matrix (a vector of vectors). -(define make-matrix - (lambda (rows columns) - (do ((m (make-vector rows)) - (i 0 (+ i 1))) - ((= i rows) m) - (vector-set! m i (make-vector columns))))) - -;;; matrix? checks to see if its argument is a matrix. -;;; It isn't foolproof, but it's generally good enough. -(define matrix? - (lambda (x) - (and (vector? x) - (> (vector-length x) 0) - (vector? (vector-ref x 0))))) - -;;; matrix-ref returns the jth element of the ith row. -(define matrix-ref - (lambda (m i j) - (vector-ref (vector-ref m i) j))) - -;;; matrix-set! changes the jth element of the ith row. -(define matrix-set! - (lambda (m i j x) - (vector-set! (vector-ref m i) j x))) - -;;; mul is the generic matrix/scalar multiplication procedure -(define mul - (lambda (x y) - ;; type-error is called to complain when mul receives an invalid - ;; type of argument. - (define type-error - (lambda (what) - (error 'mul - "~s is not a number or matrix" - what))) - - ;; match-error is called to complain when mul receives a pair of - ;; incompatible arguments. - (define match-error - (lambda (what1 what2) - (error 'mul - "~s and ~s are incompatible operands" - what1 - what2))) - - ;; matrix-rows returns the number of rows in a matrix. - (define matrix-rows - (lambda (x) - (vector-length x))) - - ;; matrix-columns returns the number of columns in a matrix. - (define matrix-columns - (lambda (x) - (vector-length (vector-ref x 0)))) - - ;; mat-sca-mul multiplies a matrix by a scalar. - (define mat-sca-mul - (lambda (m x) - (let* ((nr (matrix-rows m)) - (nc (matrix-columns m)) - (r (make-matrix nr nc))) - (do ((i 0 (+ i 1))) - ((= i nr) r) - (do ((j 0 (+ j 1))) - ((= j nc)) - (matrix-set! r i j - (* x (matrix-ref m i j)))))))) - - ;; mat-mat-mul multiplies one matrix by another, after verifying - ;; that the first matrix has as many columns as the second - ;; matrix has rows. - (define mat-mat-mul - (lambda (m1 m2) - (let* ((nr1 (matrix-rows m1)) - (nr2 (matrix-rows m2)) - (nc2 (matrix-columns m2)) - (r (make-matrix nr1 nc2))) - (if (not (= (matrix-columns m1) nr2)) - (match-error m1 m2)) - (do ((i 0 (+ i 1))) - ((= i nr1) r) - (do ((j 0 (+ j 1))) - ((= j nc2)) - (do ((k 0 (+ k 1)) - (a 0 - (+ a - (* (matrix-ref m1 i k) - (matrix-ref m2 k j))))) - ((= k nr2) - (matrix-set! r i j a)))))))) - - ;; body of mul; dispatch based on input types - (cond - ((number? x) - (cond - ((number? y) (* x y)) - ((matrix? y) (mat-sca-mul y x)) - (else (type-error y)))) - ((matrix? x) - (cond - ((number? y) (mat-sca-mul x y)) - ((matrix? y) (mat-mat-mul x y)) - (else (type-error y)))) - (else (type-error x))))) diff --git a/ta6ob/examples/object.ss b/ta6ob/examples/object.ss deleted file mode 100644 index e4e7be0..0000000 --- a/ta6ob/examples/object.ss +++ /dev/null @@ -1,54 +0,0 @@ -;;; object.ss -;;; Copyright (C) 1996 R. Kent Dybvig -;;; from "The Scheme Programming Language, 2ed" by R. Kent Dybvig - -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -;;; define-object creates an object constructor that uses let* to bind -;;; local fields and letrec to define the exported procedures. An -;;; object is itself a procedure that accepts messages corresponding -;;; to the names of the exported procedures. The second pattern is -;;; used to allow the set of local fields to be omitted. -(define-syntax define-object - (syntax-rules () - ((_ (name . varlist) - ((var1 val1) ...) - ((var2 val2) ...)) - (define name - (lambda varlist - (let* ((var1 val1) ...) - (letrec ((var2 val2) ...) - (lambda (msg . args) - (case msg - ((var2) (apply var2 args)) ... - (else - (error 'name "invalid message ~s" - (cons msg args)))))))))) - ((_ (name . varlist) - ((var2 val2) ...)) - (define-object (name . varlist) - () - ((var2 val2) ...))))) - -;;; send-message abstracts the act of sending a message from the act -;;; of applying a procedure and allows the message to be unquoted. -(define-syntax send-message - (syntax-rules () - ((_ obj msg arg ...) - (obj 'msg arg ...)))) diff --git a/ta6ob/examples/power.ss b/ta6ob/examples/power.ss deleted file mode 100644 index 7d1a704..0000000 --- a/ta6ob/examples/power.ss +++ /dev/null @@ -1,12 +0,0 @@ -;;; doubly recursive power (expt) function - -;;; try using trace-lambda to see the nesting. - -(define power - (lambda (x n) - (cond - [(= n 0) 1] - [(= n 1) x] - [else - (let ([q (quotient n 2)]) - (* (power x q) (power x (- n q))))]))) diff --git a/ta6ob/examples/queue.ss b/ta6ob/examples/queue.ss deleted file mode 100644 index 389611a..0000000 --- a/ta6ob/examples/queue.ss +++ /dev/null @@ -1,56 +0,0 @@ -;;; queue -;;; an abstract datatype - -;;; operations: -;;; (queue) ;create a queue object - -;;; if 'q' is a queue object: - -;;; (q 'type?) ;return the type (queue), useful if there are other -;;; ;abstract datatypes floating around. -;;; (q 'empty?) ;returns true iff q is empty -;;; (q 'put val) ;adds val to end of q; returns val -;;; (q 'get) ;removes first element of q and returns it - -;;; Examples - -;;; (define! q (queue)) -;;; (q 'type?) => queue -;;; (q 'empty?) => #!true -;;; (q 'put 3) -;;; (q 'put 4) -;;; (q 'put 5) -;;; (q 'empty?) => () -;;; (q 'get) => 3 -;;; (q 'get) => 4 -;;; (q 'put 7) -;;; (q 'get) => 5 -;;; (q 'get) => 7 -;;; (q 'empty?) => #!true - -(define queue - (lambda () - (let ([head '()] [tail '()]) - (lambda (request . args) - (case request - [type? 'queue] - [empty? (null? head)] - [put - (let ([v (car args)]) - (if (null? head) - (let ([p (cons v '())]) - (set! tail p) - (set! head p)) - (let ([quebit (cons v '())]) - (set-cdr! tail quebit) - (set! tail quebit))) - v)] - [get - (if (null? head) - (error 'queue "queue is empty") - (let ([v (car head)]) - (set! head (cdr head)) - (when (null? head) (set! tail '())) - v))] - [else - (error 'queue "~s is not a valid request" request)]))))) diff --git a/ta6ob/examples/rabbit.ss b/ta6ob/examples/rabbit.ss deleted file mode 100644 index 6e2f29d..0000000 --- a/ta6ob/examples/rabbit.ss +++ /dev/null @@ -1,90 +0,0 @@ -;;; rabbit - -;;; The rabbit program highlights the use of continuations and -;;; timer interrupts to perform thread scheduling. The scheduler -;;; maintains a thread queue and operating system primitives for -;;; dispatching and thread creation. The queue is only visible -;;; to the operating system kernel and all accesses are performed -;;; with the timer off to prevent corruption. - -;;; (thread exp) will create a thread out of exp and place it in -;;; the thread queue. you may do this for as many threads as -;;; you like. (dispatch) starts the threads going. If the -;;; thread queue ever becomes empty, dispatch exits. Threads -;;; may create other threads. - -;;; The rabbit function creates a thread that spawns two offspring -;;; and dies. Each thread has a generation number associated with -;;; it. The generation number of each rabbit is one lower than that -;;; of it's parent; rabbits in generation 0 are sterile. - -;;; load the queue datatype -- might need a fuller pathname -(load "queue.ss") - -;;; swap-time determines the number of timer ticks in a time slice -(define swap-time - (make-parameter - 100 - (lambda (x) - (unless (and (integer? x) (positive? x)) - (error 'swap-time "~s is not a positive integer" x)) - x))) - -(define dispatch #f) -(define thread #f) - -(let ([pq (queue)]) - (set! dispatch - (lambda () - (unless (pq 'empty?) - ; the thread queue holds continuations---grab one and invoke it - (let ([next (pq 'get)]) - (set-timer (swap-time)) - (next #f))))) - (set! thread - (lambda (thunk) - (call/cc - (lambda (return) - (call/cc - (lambda (k) - ; turn off the timer while accessing the queue - (let ([time-left (set-timer 0)]) - ; put the thread on the queue - (pq 'put k) - (set-timer time-left) - ; get out of here - (return #f)))) - ; the first time through we will return before getting - ; here. the second time is when a thread is first - ; dispatched from the thread queue. - (thunk) - (set-timer 0) - (dispatch))))) - (timer-interrupt-handler - (lambda () - (printf "swapping~%") - (call/cc - (lambda (l) - ; place the continuation of the interrupt on the queue - (pq 'put l) - (dispatch)))))) - - -;;; *delay-max* gives the maximum random delay before a rabbit -;;; reaches child-bearing age. -(define *delay-max* 10000) - -(define rabbit - (lambda (n) - (thread - (lambda () - (printf "~s~%" n) - (unless (zero? n) - (do ([i (random *delay-max*) (1- i)]) ((zero? i))) - (rabbit (1- n)) - (rabbit (1- n))))))) - -;;; try: -;;; (rabbit 3) -;;; (rabbit 5) -;;; (dispatch) diff --git a/ta6ob/examples/rsa.ss b/ta6ob/examples/rsa.ss deleted file mode 100644 index c59d377..0000000 --- a/ta6ob/examples/rsa.ss +++ /dev/null @@ -1,308 +0,0 @@ -;;; rsa.ss -;;; Bruce T. Smith, University of North Carolina at Chapel Hill -;;; (circa 1984) - -;;; Updated for Chez Scheme Version 7, May 2005 - -;;; This is a toy example of an RSA public-key encryption system. It -;;; is possible to create users who register their public keys with a -;;; center and hide their private keys. Then, it is possible to have -;;; the users exchange messages. To a limited extent one can look at -;;; the intermediate steps of the process by using encrypt and decrypt. -;;; The encrypted messages are represented by lists of numbers. - -;;; Example session: - -#| -> (make-user bonzo) -Registered with Center -User: bonzo -Base: 152024296883113044375867034718782727467 -Encryption exponent: 7 -> (make-user bobo) -Registered with Center -User: bobo -Base: 244692569127295893294157219042233636899 -Encryption exponent: 5 -> (make-user tiger) -Registered with Center -User: tiger -Base: 138555414233087084786368622588289286073 -Encryption exponent: 7 -> (show-center) - -User: tiger -Base: 138555414233087084786368622588289286073 -Encryption exponent: 7 - -User: bobo -Base: 244692569127295893294157219042233636899 -Encryption exponent: 5 - -User: bonzo -Base: 152024296883113044375867034718782727467 -Encryption exponent: 7 -> (send "hi there" bonzo bobo) -"hi there" -> (send "hi there to you" bobo bonzo) -"hi there to you" -> (decrypt (encrypt "hi there" bonzo bobo) tiger) -" #z R4WN Zbb E8J" -|# - -;;; Implementation: - -(module ((make-user user) show-center encrypt decrypt send) - -;;; (make-user name) creates a user with the chosen name. When it -;;; creates the user, it tells him what his name is. He will use -;;; this when registering with the center. - -(define-syntax make-user - (syntax-rules () - [(_ uid) - (begin (define uid (user 'uid)) (uid 'register))])) - -;;; (encrypt mesg u1 u2) causes user 1 to encrypt mesg using the public -;;; keys for user 2. - -(define-syntax encrypt - (syntax-rules () - [(_ mesg u1 u2) ((u1 'send) mesg 'u2)])) - -;;; (decrypt number-list u) causes the user to decrypt the list of -;;; numbers using his private key. - -(define-syntax decrypt - (syntax-rules () - [(_ numbers u) ((u 'receive) numbers)])) - -;;; (send mesg u1 u2) this combines the functions 'encrypt' and 'decrypt', -;;; calling on user 1 to encrypt the message for user 2 and calling on -;;; user 2 to decrypt the message. - -(define-syntax send - (syntax-rules () - [(_ mesg u1 u2) (decrypt (encrypt mesg u1 u2) u2)])) - -;;; A user is capable of the following: -;;; - choosing public and private keys and registering with the center -;;; - revealing his public and private keys -;;; - retrieving user's private keys from the center and encrypting a -;;; message for that user -;;; - decrypting a message with his private key - -(define user - (lambda (name) - (let* ([low (expt 2 63)] ; low, high = bounds on p and q - [high (* 2 low)] - [p 0] ; p,q = two large, probable primes - [q 0] - [n 0] ; n = p * q, base for modulo arithmetic - [phi 0] ; phi = lcm(p-1,q-1), not quite the Euler phi function, - ; but it will serve for our purposes - [e 0] ; e = exponent for encryption - [d 0]) ; d = exponent for decryption - (lambda (request) - (case request - ;; choose keys and register with the center - [register - (set! p (find-prime low high)) - (set! q - (let loop ([q1 (find-prime low high)]) - (if (= 1 (gcd p q1)) - q1 - (loop (find-prime low high))))) - (set! n (* p q)) - (set! phi - (/ (* (1- p) (1- q)) - (gcd (1- p) (1- q)))) - (set! e - (do ([i 3 (+ 2 i)]) - ((= 1 (gcd i phi)) i))) - (set! d (mod-inverse e phi)) - (register-center (cons name (list n e))) - (printf "Registered with Center~%") - (printf "User: ~s~%" name) - (printf "Base: ~d~%" n) - (printf "Encryption exponent: ~d~%" e)] - - ;; divulge your keys-- you should resist doing this... - [show-all - (printf "p = ~d ; q = ~d~%" p q) - (printf "n = ~d~%" n) - (printf "phi = ~d~%" (* (1- p) (1- q))) - (printf "e = ~d ; d = ~d~%" e d)] - - ;; get u's public key from the center and encode - ;; a message for him - [send - (lambda (mesg u) - (let* ([public (request-center u)] - [base (car public)] - [exponent (cadr public)] - [mesg-list (string->numbers mesg base)]) - (map (lambda (x) (expt-mod x exponent base)) - mesg-list)))] - - ;; decrypt a message with your private key - [receive - (lambda (crypt-mesg) - (let ([mesg-list (map (lambda (x) (expt-mod x d n)) crypt-mesg)]) - (numbers->string mesg-list)))]))))) - -;;; The center maintains the list of public keys. It can register -;;; new users, provide the public keys for any particular user, or -;;; display the whole public file. - -(module (register-center request-center show-center) - (define public-keys '()) - (define register-center - (lambda (entry) - (set! public-keys - (cons entry - (remq (assq (car entry) public-keys) public-keys))))) - (define request-center - (lambda (u) - (let ([a (assoc u public-keys)]) - (when (null? a) - (error 'request-center - "User ~s not registered in center" - u)) - (cdr a)))) - (define show-center - (lambda () - (for-each - (lambda (entry) - (printf "~%User: ~s~%" (car entry)) - (printf "Base: ~s~%" (cadr entry)) - (printf "Encryption exponent: ~s~%" (caddr entry))) - public-keys))) -) - -;;; string->numbers encodes a string as a list of numbers -;;; numbers->string decodes a string from a list of numbers - -;;; string->numbers and numbers->string are defined with respect to -;;; an alphabet. Any characters in the alphabet are translated into -;;; integers---their regular ascii codes. Any characters outside -;;; the alphabet cause an error during encoding. An invalid code -;;; during decoding is translated to a space. - -(module (string->numbers numbers->string) - (define first-code 32) - (define last-code 126) - (define alphabet - ; printed form of the characters, indexed by their ascii codes - (let ([alpha (make-string 128 #\space)]) - (do ([i first-code (1+ i)]) - ((= i last-code) alpha) - (string-set! alpha i (integer->char i))))) - - (define string->integer - (lambda (str) - (let ([ln (string-length str)]) - (let loop ([i 0] [m 0]) - (if (= i ln) - m - (let* ([c (string-ref str i)] [code (char->integer c)]) - (when (or (< code first-code) (>= code last-code)) - (error 'rsa "Illegal character ~s" c)) - (loop (1+ i) (+ code (* m 128))))))))) - - (define integer->string - (lambda (n) - (list->string - (map (lambda (n) (string-ref alphabet n)) - (let loop ([m n] [lst '()]) - (if (zero? m) - lst - (loop (quotient m 128) - (cons (remainder m 128) lst)))))))) - - ; turn a string into a list of numbers, each no larger than base - (define string->numbers - (lambda (str base) - (letrec ([block-size - (do ([i -1 (1+ i)] [m 1 (* m 128)]) ((>= m base) i))] - [substring-list - (lambda (str) - (let ([ln (string-length str)]) - (if (>= block-size ln) - (list str) - (cons (substring str 0 block-size) - (substring-list - (substring str block-size ln))))))]) - (map string->integer (substring-list str))))) - - ; turn a list of numbers into a string - (define numbers->string - (lambda (lst) - (letrec ([reduce - (lambda (f l) - (if (null? (cdr l)) - (car l) - (f (car l) (reduce f (cdr l)))))]) - (reduce - string-append - (map (lambda (x) (integer->string x)) lst))))) -) - -;;; find-prime finds a probable prime between two given arguments. -;;; find-prime uses a cheap but fairly dependable test for primality -;;; for large numbers, by first weeding out multiples of first 200 -;;; primes, then applies Fermat's theorem with base 2. - -(module (find-prime) - (define product-of-primes - ; compute product of first n primes, n > 0 - (lambda (n) - (let loop ([n (1- n)] [p 2] [i 3]) - (cond - [(zero? n) p] - [(= 1 (gcd i p)) (loop (1- n) (* p i) (+ i 2))] - [else (loop n p (+ i 2))])))) - (define prod-first-200-primes (product-of-primes 200)) - (define probable-prime - ; first check is quick, and weeds out most non-primes - ; second check is slower, but weeds out almost all non-primes - (lambda (p) - (and (= 1 (gcd p prod-first-200-primes)) - (= 1 (expt-mod 2 (1- p) p))))) - (define find-prime - ; find probable prime in range low to high (inclusive) - (lambda (low high) - (let ([guess - (lambda (low high) - (let ([g (+ low (random (1+ (- high low))))]) - (if (odd? g) g (1+ g))))]) - (let loop ([g (guess low high)]) - (cond - ; start over if already too high - [(> g high) (loop (guess low high))] - ; if guess is probably prime, return - [(probable-prime g) g] - ; don't bother with even guesses - [else (loop (+ 2 g))]))))) -) - -;;; mod-inverse finds the multiplicative inverse of x mod b, if it exists - -(module (mod-inverse) - (define gcdx - ; extended Euclid's gcd algorithm, x <= y - (lambda (x y) - (let loop ([x x] [y y] [u1 1] [u2 0] [v1 0] [v2 1]) - (if (zero? y) - (list x u1 v1) - (let ([q (quotient x y)] [r (remainder x y)]) - (loop y r u2 (- u1 (* q u2)) v2 (- v1 (* q v2)))))))) - - (define mod-inverse - (lambda (x b) - (let* ([x1 (modulo x b)] [g (gcdx x1 b)]) - (unless (= (car g) 1) - (error 'mod-inverse "~d and ~d not relatively prime" x b)) - (modulo (cadr g) b)))) -) -) diff --git a/ta6ob/examples/scons.ss b/ta6ob/examples/scons.ss deleted file mode 100644 index 83dc575..0000000 --- a/ta6ob/examples/scons.ss +++ /dev/null @@ -1,41 +0,0 @@ -;;; scons.ss -;;; a stream-construction facility - -;;; The scons special form performs a cons, suspending the cdr field -;;; by enclosing it in a procedure of no arguments. scdr tests to see -;;; if the cdr is a procedure, and if so, invokes it. scar is provided -;;; for symmetry; it is just car. - -;;; The function stream-ref is simply list-ref defined in terms of -;;; scdr and scar. - -;;; factlist and fiblist are two infinite streams. -;;; Try (stream-ref factlist 10) or (stream-ref fiblist 20). - -;;; scons could easily suspend the car field as well. This would -;;; implement the lazy cons of Friedman & Wise. - -(define-syntax scons - (syntax-rules () - ((_ car cdr) (cons car (lambda () cdr))))) - -(define scar car) - -(define scdr - (lambda (x) - (when (procedure? (cdr x)) (set-cdr! x ((cdr x)))) - (cdr x))) - -(define stream-ref - (lambda (x n) - (if (zero? n) - (scar x) - (stream-ref (scdr x) (1- n))))) - -(define factlist - (let fact ([a 1] [n 1]) - (scons a (fact (* a n) (1+ n))))) - -(define fiblist - (let fib ([fib-2 0] [fib-1 1]) - (scons fib-1 (fib fib-1 (+ fib-2 fib-1))))) diff --git a/ta6ob/examples/setof.ss b/ta6ob/examples/setof.ss deleted file mode 100644 index 51a5fc8..0000000 --- a/ta6ob/examples/setof.ss +++ /dev/null @@ -1,52 +0,0 @@ -;;; setof.ss -;;; Copyright (C) 1996 R. Kent Dybvig -;;; from "The Scheme Programming Language, 2ed" by R. Kent Dybvig - -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -;;; set-of uses helper syntactic extension set-of-help, passing it -;;; an initial base expression of '() -(define-syntax set-of - (syntax-rules () - ((_ e m ...) - (set-of-help e '() m ...)))) - -;;; set-of-help recognizes in, is, and predicate expressions and -;;; changes them into nested named let, let, and if expressions. -(define-syntax set-of-help - (syntax-rules (in is) - ((_ e base) - (set-cons e base)) - ((_ e base (x in s) m ...) - (let loop ((set s)) - (if (null? set) - base - (let ((x (car set))) - (set-of-help e (loop (cdr set)) m ...))))) - ((_ e base (x is y) m ...) - (let ((x y)) (set-of-help e base m ...))) - ((_ e base p m ...) - (if p (set-of-help e base m ...) base)))) - -;;; set-cons returns the original set y if x is already in y. -(define set-cons - (lambda (x y) - (if (memv x y) - y - (cons x y)))) diff --git a/ta6ob/examples/socket.ss b/ta6ob/examples/socket.ss deleted file mode 100644 index 6f3e7c0..0000000 --- a/ta6ob/examples/socket.ss +++ /dev/null @@ -1,248 +0,0 @@ -;;; socket.ss -;;; R. Kent Dybvig May 1998 -;;; Updated November 2005 -;;; Updated by Jamie Taylor, Sept 2016 -;;; Public Domain -;;; -;;; bindings for socket operations and other items useful for writing -;;; programs that use sockets. - -;;; Requires csocket.so, built from csocket.c. -;;; Example compilation command line from macOS: -;;; cc -c csocket.c -o csocket.o -;;; cc csocket.o -dynamic -dynamiclib -current_version 1.0 -compatibility_version 1.0 -o csocket.so -(load-shared-object "./csocket.so") - -;;; Requires from C library: -;;; close, dup, execl, fork, kill, listen, tmpnam, unlink -(case (machine-type) - [(i3le ti3le a6le ta6le) (load-shared-object "libc.so.6")] - [(i3osx ti3osx a6osx ta6osx) (load-shared-object "libc.dylib")] - [else (load-shared-object "libc.so")]) - -;;; basic C-library stuff - -(define close - (foreign-procedure "close" (int) - int)) - -(define dup - (foreign-procedure "dup" (int) - int)) - -(define execl4 - (let ((execl-help - (foreign-procedure "execl" - (string string string string void*) - int))) - (lambda (s1 s2 s3 s4) - (execl-help s1 s2 s3 s4 0)))) - -(define fork - (foreign-procedure "fork" () - int)) - -(define kill - (foreign-procedure "kill" (int int) - int)) - -(define listen - (foreign-procedure "listen" (int int) - int)) - -(define tmpnam - (foreign-procedure "tmpnam" (void*) - string)) - -(define unlink - (foreign-procedure "unlink" (string) - int)) - -;;; routines defined in csocket.c - -(define accept - (foreign-procedure "do_accept" (int) - int)) - -(define bytes-ready? - (foreign-procedure "bytes_ready" (int) - boolean)) - -(define bind - (foreign-procedure "do_bind" (int string) - int)) - -(define c-error - (foreign-procedure "get_error" () - string)) - -(define c-read - (foreign-procedure "c_read" (int u8* size_t size_t) - ssize_t)) - -(define c-write - (foreign-procedure "c_write" (int u8* size_t ssize_t) - ssize_t)) - -(define connect - (foreign-procedure "do_connect" (int string) - int)) - -(define socket - (foreign-procedure "do_socket" () - int)) - -;;; higher-level routines - -(define dodup - ; (dodup old new) closes old and dups new, then checks to - ; make sure that resulting fd is the same as old - (lambda (old new) - (check 'close (close old)) - (unless (= (dup new) old) - (error 'dodup - "couldn't set up child process io for fd ~s" old)))) - -(define dofork - ; (dofork child parent) forks a child process and invokes child - ; without arguments and parent with the child's pid - (lambda (child parent) - (let ([pid (fork)]) - (cond - [(= pid 0) (child)] - [(> pid 0) (parent pid)] - [else (error 'fork (c-error))])))) - -(define setup-server-socket - ; create a socket, bind it to name, and listen for connections - (lambda (name) - (let ([sock (check 'socket (socket))]) - (unlink name) - (check 'bind (bind sock name)) - (check 'listen (listen sock 1)) - sock))) - -(define setup-client-socket - ; create a socket and attempt to connect to server - (lambda (name) - (let ([sock (check 'socket (socket))]) - (check 'connect (connect sock name)) - sock))) - -(define accept-socket - ; accept a connection - (lambda (sock) - (check 'accept (accept sock)))) - -(define check - ; signal an error if status x is negative, using c-error to - ; obtain the operating-system's error message - (lambda (who x) - (if (< x 0) - (error who (c-error)) - x))) - -(define terminate-process - ; kill the process identified by pid - (lambda (pid) - (define sigterm 15) - (kill pid sigterm) - (void))) - -(define open-process - (lambda (command) - (define (make-r! socket) - (lambda (bv start n) - (check 'r! (c-read socket bv start n)))) - (define (make-w! socket) - (lambda (bv start n) - (check 'w! (c-write socket bv start n)))) - (define (make-close pid socket) - (lambda () - (check 'close (close socket)) - (terminate-process pid))) - (let* ([server-socket-name (tmpnam 0)] - [server-socket (setup-server-socket server-socket-name)]) - (dofork - (lambda () ; child - (check 'close (close server-socket)) - (let ([sock (setup-client-socket server-socket-name)]) - (dodup 0 sock) - (dodup 1 sock)) - (check 'execl (execl4 "/bin/sh" "/bin/sh" "-c" command)) - (error 'open-process "subprocess exec failed")) - (lambda (pid) ; parent - (let ([sock (accept-socket server-socket)]) - (check 'close (close server-socket)) - (make-custom-binary-input/output-port command - (make-r! sock) (make-w! sock) #f #f (make-close pid sock)))))))) - -#!eof - -;;; sample session using base socket functionality - -> (define client-pid) -> (define client-socket) -> (let* ([server-socket-name (tmpnam 0)] - [server-socket (setup-server-socket server-socket-name)]) - ; fork a child, use it to exec a client Scheme process, and set - ; up server-side client-pid and client-socket variables. - (dofork ; child - (lambda () - ; the child establishes the socket input/output fds as - ; stdin and stdout, then starts a new Scheme session - (check 'close (close server-socket)) - (let ([sock (setup-client-socket server-socket-name)]) - (dodup 0 sock) - (dodup 1 sock)) - (check 'execl (execl4 "/bin/sh" "/bin/sh" "-c" "exec scheme")) - (error 'client "returned!")) - (lambda (pid) ; parent - ; the parent waits for a connection from the client - (set! client-pid pid) - (set! client-socket (accept-socket server-socket)) - (check 'close (close server-socket))))) -> (define put ; procedure to send data to client - (lambda (x) - (let* ([s (format "~s~%" x)] - [bv (string->utf8 s)]) - (c-write client-socket bv 0 (bytevector-length bv))) - (void))) -> (define get ; procedure to read data from client - (let ([buff (make-bytevector 1024)]) - (lambda () - (let* ([n (c-read client-socket buff 0 (bytevector-length buff))] - [bv (make-bytevector n)]) - (bytevector-copy! buff 0 bv 0 n) - (printf "client:~%~a~%server:~%" (utf8->string bv)))))) -> (get) -client: -Chez Scheme Version 9.5.1 -Copyright 1984-2017 Cisco Systems, Inc. - -> -server: -> (put '(let ((x 3)) x)) -> (get) -client: -3 -> -server: -> (terminate-process client-pid) -> (exit) - - -;;; sample session using process port - -> (define p (transcoded-port (open-process "exec scheme -q") (native-transcoder))) -> (pretty-print '(+ 3 4) p) -> (read p) -7 -> (pretty-print '(define (f x) (if (= x 0) 1 (* x (f (- x 1))))) p) -> (pretty-print '(f 10) p) -> (read p) -3628800 -> (pretty-print '(exit) p) -> (read p) -#!eof -> (close-port p) diff --git a/ta6ob/examples/template.ss b/ta6ob/examples/template.ss deleted file mode 100644 index 5aa6161..0000000 --- a/ta6ob/examples/template.ss +++ /dev/null @@ -1,858 +0,0 @@ -#!chezscheme -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. -;;; include-template: a simple yet powerful extensible templating mechanism -;;; -;;; Authors: Andrew W. Keep and R. Kent Dybvig -;;; -;;; The syntax (include-template ) expands into an expression whose -;;; value is a string containing the contents of the file named by , -;;; except each occurrence of @@ within the file is replaced by @, and each -;;; occurrence of @() is replaced with the value of -;;; . must be a string literal, and the value -;;; of each must be a string. The file named by -;;; must be present at expand time and need not be present at run time. -;;; -;;; The template system can also be extended using the syntax: -;;; -;;; (define-template-extension ) -;;; -;;; where: -;;; -;;; -> ( *) -;;; | -;;; -> (*) -;;; | -;;; -> -;;; | ( (*) ) ... -;;; | ( ) ... -;;; | (optional (*) -;;; ) -;;; | (optional ) -;;; -> (*) -;;; -> -;;; -> a - z | A - Z | ! | $ | % | & | * | / | : | < -;;; | = | > | ? | ^ | _ | ~ -;;; -> | 0 - 9 | - | + | . -;;; -;;; is treated as a quasisyntax template, -;;; is a syntax-rules pattern and, -;;; is any valid scheme identifier. -;;; -;;; For using a a new @ -;;; form is created and when the @(*) is encountered -;;; in a template, it is immediately replaced with the . -;;; -;;; For instance an extension that converts numbers to strings can be -;;; implemented as: -;;; -;;; (define-template-extension (num (e)) (number->string e)) -;;; -;;; When @num(10) is encountered in a template, the string "10" is generated. -;;; -;;; For with an each in the -;;; the define-template-extension will create a new syntax -;;; form @ along with an @end for the from the -;;; . When include-template encounters an -;;; @ ... @end pattern it will match the -;;; * (when supplied) against the following scheme expression -;;; and match the template expressions found between the @ to the -;;; matching bindings. -;;; -;;; For example, we can add a "for" loop extension as: -;;; -;;; (define-template-extension (for ([x e] [xs es] ...) tmpl) -;;; (let ([t e]) -;;; (apply string-append (map (lambda (x xs ...) tmpl) t es ...)))) -;;; -;;; (for (exprs ...) tmpl) -;;; => -;;; @for (lambda (...) -;;; (let ([t (read-scheme k...)]) -;;; (cons (incomplete-node @for t) ...))) -;;; @endfor (lambda (...) -;;; --- -;;; (let loop ([t '()] [tmpl '()] ...) -;;; (cond -;;; [(and (incomplete-node? (car stack)) (eq? (incomplete-node-kw (car stack)) '@for)) -;;; (with-syntax (['([x e] [xs es] ...) (incomplete-node-stx (car stack))]) -;;; '(let ([t e]) -;;; (apply string-append (map (lambda (x xs ...) tmpl) t es ..)))) -;;; -;;; In a template if: @for([x '("a" "b" "c")]) got @(t). @endfor -;;; is encountered, it will print the string " got a. got b. got c. " for -;;; this expression (which will be produced by the code: -;;; (apply string-append -;;; (map (lambda (x) (string-append " got " x ". ") '("a" "b" "c")))) -;;; -;;; For a more complex example see the @if/@elif/@else/@endif example at -;;; the end of the library. -;;; -;;; Additional examples are embedded within the tests below #!eof. - -;;; The (template-helpers) library supplies scheme procedures that are used at -;;; macro-expansion time by both the include-template and -;;; define-template-extension macros. -(library (template-helpers) - (export - incomplete-node? make-incomplete-node - incomplete-node-type incomplete-node-e* incomplete-node-bfp - source-string source-error - read-scheme initial-id-char? id-char? - make-string-buffer extend-string-buffer! extract-string-and-reset! - open-positional-string-output-port - strip-blanks) - (import (chezscheme)) - - (define (source-string sfd bfp) - (call-with-values - (lambda () (locate-source sfd bfp)) - (case-lambda - [() (format "at char position ~s of ~a" bfp - (source-file-descriptor-path sfd))] - [(path lp cp) (format "at line ~s, char ~s of ~a" lp cp - (source-file-descriptor-path sfd))]))) - - (define (source-error sfd bfp msg . args) - (errorf 'include-template "~? ~a" msg args (source-string sfd bfp))) - - (define (read-scheme k ip sfd bfp) - (let-values ([(x new-bfp) (get-datum/annotations ip sfd bfp)]) - (let ([x (if (annotation? x) (annotation-expression x) x)]) - (values (datum->syntax k x) new-bfp)))) - - (define-record-type incomplete-node (nongenerative) (fields type e* bfp)) - - (define (initial-id-char? c) - (or (char<=? #\a c #\z) (char<=? #\A c #\Z) - (char=? c #\!) (char<=? #\$ c #\&) - (char=? c #\*) (char=? c #\/) - (char=? c #\:) (char<=? #\< c #\?) - (char=? c #\^) (char=? c #\_) (char=? c #\~))) - - (define (id-char? c) - (or (initial-id-char? c) (char<=? #\0 c #\9) - (char=? c #\-) (char=? c #\+) (char=? c #\.))) - - (define-record-type string-buffer (nongenerative) - (fields (mutable n) (mutable str)) - (protocol (lambda (new) (lambda () (new 0 (make-string 16)))))) - (define (get-buffer tb n required-capacity) - (let* ([str (string-buffer-str tb)] [len (string-length str)]) - (if (fx< (fx- len n) required-capacity) - (let ([new-str (make-string (fx* 2 (fx+ len required-capacity)))]) - (string-copy! str 0 new-str 0 n) - (string-buffer-str-set! tb new-str) - new-str) - str))) - (define (extend-string-buffer! tb c) - (let ([n (string-buffer-n tb)]) - (string-set! (get-buffer tb n 1) n c) - (string-buffer-n-set! tb (fx+ n 1)))) - (define (append-to-string-buffer! tb str) - (let ([n (string-buffer-n tb)] [len (string-length str)]) - (string-copy! (get-buffer tb n len) n str 0 len) - (string-buffer-n-set! tb (fx+ n len)))) - (define (extract-string-and-reset! tb) - (let ([str (substring (string-buffer-str tb) 0 (string-buffer-n tb))]) - (string-buffer-n-set! tb 0) - str)) - (define (open-positional-string-output-port) - (define-record-type position (nongenerative) - (fields (mutable line) (mutable column)) - (protocol (lambda (new) (lambda () (new 1 1))))) - (let ([tb (make-string-buffer)] [pos (make-position)]) - (define (w! str start cnt) - (let* ([n (string-buffer-n tb)] - [buf (get-buffer tb n cnt)] - [end (fx+ start cnt)]) - (let loop! ([i start] [n n] [line (position-line pos)] [column (position-column pos)]) - (if (fx= i end) - (begin - (position-line-set! pos line) - (position-column-set! pos column) - (string-buffer-n-set! tb n)) - (let ([c (string-ref str i)]) - (string-set! buf n c) - (if (char=? c #\newline) - (loop! (fx+ i 1) (fx+ n 1) (fx+ line 1) 1) - (loop! (fx+ i 1) (fx+ n 1) line (fx+ column 1))))))) - cnt) - (define (gp) (string-buffer-n tb)) - (let ([op (make-custom-textual-output-port "positional-string-output-port" w! gp #f #f)]) - (define (line) (flush-output-port op) (position-line pos)) - (define (column) (flush-output-port op) (position-column pos)) - (define (p) (flush-output-port op) (extract-string-and-reset! tb)) - (values op p line column)))) - - ;; scan forward for blanks, and if it leads you to a new-line, strip - ;; the previous blanks back to the new line. - (define (finish-strip ip stack bfp start-bfp) - (let ([node-to-strip (car stack)]) - (if (string? node-to-strip) - (let loop ([i (string-length node-to-strip)]) - (if (fx= i 0) - (values (cdr stack) bfp) - (let ([i (fx- i 1)]) - (let ([c (string-ref node-to-strip i)]) - (cond - [(char=? c #\newline) - (values (cons (substring node-to-strip 0 (fx+ i 1)) (cdr stack)) bfp)] - [(char-whitespace? c) (loop i)] - [else (set-port-position! ip start-bfp) (values stack start-bfp)]))))) - (begin (set-port-position! ip start-bfp) (values stack start-bfp))))) - (define (strip-blanks ip stack start-bfp) - (let gather-blanks ([bfp start-bfp]) - (let ([c (read-char ip)]) - (cond - [(eof-object? c) (finish-strip ip stack bfp start-bfp)] - [(char=? c #\newline) (finish-strip ip stack (fx+ bfp 1) start-bfp)] - [(char-whitespace? c) (gather-blanks (fx+ bfp 1))] - [else (set-port-position! ip start-bfp) (values stack start-bfp)]))))) - -(library (template) - (export include-template define-template-extension optional @if @elif @else @endif @for @endfor @num) - (import (chezscheme) (template-helpers)) - - (define-syntax optional (lambda (x) (syntax-violation #f "misplaced aux keyword" x))) - - (define check-string-and-indent - (lambda (s at indent) - (unless (string? s) - (errorf 'include-template "unexpected non-string value ~s of expression ~s" s at)) - (if (= indent 0) - s - (let ([ip (open-string-input-port s)]) - (let ([first-line (get-line ip)]) - (if (eof-object? first-line) - s - (let-values ([(op p) (open-string-output-port)]) - (display first-line op) - (let ([indent (make-string indent #\space)]) - (let loop () - (let ([line (get-line ip)]) - (if (eof-object? line) - (begin - (when (char=? (string-ref s (fx- (string-length s) 1)) #\newline) (newline op)) - (p)) - (begin - (newline op) - (display indent op) - (display line op) - (loop))))))))))))) - - (define-syntax include-template - (lambda (x) - (define (process-template-file r fn k) - (let* ([bip (open-file-input-port fn)] - [sfd (make-source-file-descriptor fn bip #t)] - [ip (transcoded-port bip (native-transcoder))] - [tb (make-string-buffer)]) - (define (s0 a bfp) - (let ([c (read-char ip)]) - (cond - [(eof-object? c) - (close-input-port ip) - (reverse (cons (extract-string-and-reset! tb) a))] - [(char=? c #\@) (s1 a (+ bfp 1))] - [else (extend-string-buffer! tb c) (s0 a (+ bfp 1))]))) - (define (s1 a bfp) - (let ([c (read-char ip)]) - (cond - [(eof-object? c) (source-error sfd bfp "expected open paren or @ following @")] - [(eqv? c #\@) (extend-string-buffer! tb c) (s0 a (+ bfp 1))] - [(eqv? c #\() - (unread-char c ip) - (let-values ([(e* new-bfp) (read-scheme k ip sfd bfp)]) - (syntax-case e* () - [(e) - (s0 - (cons* - #`(check-string-and-indent e #,(source-string sfd bfp) (fx- (column) 1)) - (extract-string-and-reset! tb) - a) - new-bfp)] - [else (source-error sfd bfp "found more than one expression within @(---)")]))] - [(initial-id-char? c) - (let ([str (extract-string-and-reset! tb)]) - (extend-string-buffer! tb #\@) - (extend-string-buffer! tb c) - (s2 (cons str a) (+ bfp 1) bfp))] - [else (source-error sfd bfp "expected open paren or @ following @")]))) - (define (s2 a bfp token-start-bfp) - (let ([c (read-char ip)]) - (cond - [(eof-object? c) (close-input-port ip) (finish-identifier a bfp token-start-bfp)] - [(id-char? c) (extend-string-buffer! tb c) (s2 a (+ bfp 1) token-start-bfp)] - [else (unread-char c ip) (finish-identifier a bfp token-start-bfp)]))) - (define (finish-identifier a bfp token-bfp) - (let* ([token (extract-string-and-reset! tb)] - [@kw (datum->syntax k (string->symbol token))] - [p (r @kw)]) - (unless p (source-error sfd token-bfp "unrecognized token ~a" token)) - (call-with-values (lambda () (p k ip sfd a bfp token-bfp)) s0))) - (s0 '() 0))) - (syntax-case x () - [(k fn) - (string? (datum fn)) - (lambda (r) - (with-syntax ([(e ...) (process-template-file r (datum fn) #'k)]) - #'(let ([filename fn]) - (let-values ([(op p line column) (open-positional-string-output-port)]) - (display e op) ... - (p)))))]))) - - (define-syntax define-template-extension - (lambda (x) - (define who 'define-template-extension) - (define (make-prefix-id prefix kw) - (datum->syntax kw - (string->symbol - (string-append prefix (symbol->string (syntax->datum kw)))))) - (define build-matcher - (case-lambda - [(kw) - (with-syntax ([kw kw] [@kw (make-prefix-id "@" kw)]) - #'[@kw (lambda (k ip sfd stack bfp token-bfp) - (let-values ([(stack bfp) (strip-blanks ip stack bfp)]) - (values (cons (make-incomplete-node 'kw #f token-bfp) stack) bfp)))])] - [(kw expr) - (with-syntax ([kw kw] [@kw (make-prefix-id "@" kw)] [(expr ...) expr]) - #'[@kw (lambda (k ip sfd stack bfp token-bfp) - (let-values ([(e* new-bfp) (read-scheme k ip sfd bfp)]) - (syntax-case e* () - [(expr ...) - (let-values ([(stack new-bfp) (strip-blanks ip stack new-bfp)]) - (values (cons (make-incomplete-node 'kw e* token-bfp) stack) new-bfp))] - [_ (source-error sfd token-bfp "expected @~s~s syntax, but got @~s~s" - 'kw '(expr ...) 'kw (syntax->datum e*))])))])])) - (define (check-id id) - (let* ([str (symbol->string (syntax->datum id))] - [len (string-length str)]) - (unless (and (> len 0) (initial-id-char? (string-ref str 0)) - (let loop ([len len]) - (or (= len 0) - (let ([len (- len 1)]) - (and (id-char? (string-ref str len)) (loop len)))))) - (syntax-violation who "invalid template keyword" id)))) - (define (check-unique! type ids) - (let loop ([ids ids]) - (syntax-case ids () - [(id rest ...) - (if (memq (datum id) (datum (rest ...))) - (syntax-violation who (format "one or more ~a used more than once" type) #'id #'(rest ...)) - (loop #'(rest ...)))] - [() (void)]))) - (define (check-syntax-unique! type maybe-expr*) - (check-unique! type - (let f ([stx maybe-expr*] [ids '()]) - (syntax-case stx () - [id (and (identifier? #'id) (not (memq (datum id) '(... unquote quote)))) (cons #'id ids)] - [(a . d) (f #'a (f #'d ids))] - [_ ids])))) - (define (build-check kw tmpl x) - #`(unless #,(if x #`(and #,x #,tmpl) tmpl) - (source-error sfd token-bfp "found ~s without required ~s" token '#,kw))) - (define (build-initial-values bindings list?*) - (fold-right (lambda (binding list? init-val**) - (cons - (if list? - (make-list (length binding) #''()) - (make-list (length binding) #'#f)) - init-val**)) - '() bindings list?*)) - (define (build-bodies list?* tmpls updates bindings) - (let f ([list?* list?*] [tmpls tmpls] [updates updates] [bindings bindings] [rbindings '()]) - (if (null? list?*) - '() - (with-syntax ([(checks ...) - (if (car list?*) - '() - #`((when #,(car tmpls) - (source-error token-bfp "found more @~s than expected" type))))] - [((args ...) ...) (fold-left (lambda (args binding) (cons binding args)) - (cons (car updates) (cdr bindings)) rbindings)]) - (cons #'(begin checks ... (loop (cdr stack) '() args ... ...)) - (f (cdr list?*) (cdr tmpls) (cdr updates) (cdr bindings) (cons (car bindings) rbindings))))))) - (define (process-template output pat) - (define (squawk type) - (syntax-violation who (format "extension cannot start with ~s keyword" type) pat)) - (syntax-case pat (optional) - [((optional kw (expr ...) tmpl) . rest) - (and (identifier? #'kw) (identifier? #'tmpl)) - (squawk 'optional)] - [((optional kw tmpl) . rest) - (and (identifier? #'kw) (identifier? #'tmpl)) - (squawk 'optional)] - [((kw (expr ...) tmpl) dots . rest) - (and (eq? (datum dots) '...) (identifier? #'kw) (identifier? #'tmpl)) - (squawk 'list)] - [((kw tmpl) dots . rest) - (and (eq? (datum dots) '...) (identifier? #'kw) (identifier? #'tmpl)) - (squawk 'optional)] - [(kw (expr ...) tmpl . rest) - (and (identifier? #'kw) (identifier? #'tmpl)) - (process-rest output #'kw #'rest - (list (build-matcher #'kw #'(expr ...))) - #'([tmpl #`(string-append #,@rstack)] - [(expr ...) (incomplete-node-e* item)]))] - [(kw tmpl . rest) - (and (identifier? #'kw) (identifier? #'tmpl)) - (process-rest output #'kw #'rest (list (build-matcher #'kw)) - #'([tmpl #`(string-append #,@rstack)]))] - [(kw (expr ...)) - (with-syntax ([@kw (make-prefix-id "@" #'kw)] [output output]) - #'([@kw (lambda (k ip sfd stack bfp token-bfp) - (let-values ([(e* new-bfp) (read-scheme k ip sfd bfp)]) - (syntax-case e* () - [(expr ...) (values (cons #`output stack) new-bfp)] - [_ (source-error sfd token-bfp "expected @~s~s syntax, but got @~s~s" - 'kw '(expr ...) 'kw (syntax->datum e*))])))]))] - [(kw) - (with-syntax ([@kw (make-prefix-id "@" #'kw)] [output output]) - #'([@kw (lambda (k ip sfd stack bfp indent token-bfp) - (values (cons #`output stack) bfp indent))]))])) - (define (process-rest output first-kw rest as* matches) - (let f ([pat rest] - [as* as*] - [checks '()] - [kws '()] - [tmpls '()] - [list?* '()] - [bindings '()] - [updates '()] - [exprs '()] - [matches matches]) - (syntax-case pat (optional) - [((optional kw (expr ...) tmpl) . rest) - (and (identifier? #'kw) (identifier? #'tmpl)) - (with-syntax ([(t) (generate-temporaries '(t))]) - (f #'rest - (cons (build-matcher #'kw #'(expr ...)) as*) checks - (cons #'kw kws) (cons #'tmpl tmpls) (cons #f list?*) - (cons (list #'tmpl #'t) bindings) - (cons (list #'#`(string-append #,@rstack) #'(incomplete-node-e* item)) updates) - (cons #'(expr ...) exprs) (cons* #'[tmpl tmpl] #'[(expr ...) #'t] matches)))] - [((optional kw tmpl) . rest) - (and (identifier? #'kw) (identifier? #'tmpl)) - (f #'rest - (cons (build-matcher #'kw) as*) checks - (cons #'kw kws) (cons #'tmpl tmpls) (cons #f list?*) (cons (list #'tmpl) bindings) - (cons (list #'#`(string-append #,@rstack)) updates) - (cons #f exprs) (cons #'[tmpl tmpl] matches))] - [((kw (expr ...) tmpl) dots . rest) - (and (eq? (datum dots) '...) (identifier? #'kw) (identifier? #'tmpl)) - (with-syntax ([(t*) (generate-temporaries '(t*))]) - (f #'rest - (cons (build-matcher #'kw #'(expr ...)) as*) checks - (cons #'kw kws) (cons #'tmpl tmpls) (cons #t list?*) (cons (list #'tmpl #'t*) bindings) - (cons (list #'(cons #`(string-append #,@rstack) tmpl) #'(cons (incomplete-node-e* item) t*)) updates) - (cons #'(expr ...) exprs) (cons* #'[(tmpl (... ...)) tmpl] #'[((expr ...) (... ...)) t*] matches)))] - [((kw tmpl) dots . rest) - (and (eq? (datum dots) '...) (identifier? #'kw) (identifier? #'tmpl)) - (f #'rest - (cons (build-matcher #'kw) as*) checks - (cons #'kw kws) (cons #'tmpl tmpls) (cons #t list?*) (cons (list #'tmpl) bindings) - (cons (list #'(cons #`(string-append #,@rstack) tmpl)) updates) - (cons #f exprs) (cons* #'[(tmpl (... ...)) tmpl] matches))] - [(kw (expr ...) tmpl . rest) - (and (identifier? #'kw) (identifier? #'tmpl)) - (with-syntax ([(t) (generate-temporaries '(t))]) - (f #'rest - (cons (build-matcher #'kw #'(expr ...)) as*) - (cons (build-check #'kw #'tmpl #'t) checks) - (cons #'kw kws) (cons #'tmpl tmpls) (cons #f list?*) (cons (list #'tmpl #'t) bindings) - (cons (list #'#`(string-append #,@rstack) #'(incomplete-node-e* item)) updates) - (cons #'(expr ...) exprs) (cons* #'[tmpl tmpl] #'[(expr ...) #'t] matches)))] - [(kw tmpl . rest) - (and (identifier? #'kw) (identifier? #'tmpl)) - (f #'rest - (cons (build-matcher #'kw) as*) - (cons (build-check #'kw #'tmpl #f) checks) - (cons #'kw kws) (cons #'tmpl tmpls) (cons #f list?*) (cons (list #'tmpl) bindings) - (cons (list #'#`(string-append #,@rstack)) updates) - (cons #f exprs) (cons #'[tmpl tmpl] matches))] - [() - (begin - (for-each check-id kws) - (check-unique! "keyword" kws) - (check-unique! "template bindings" tmpls) - (check-syntax-unique! "scheme syntax matching expressions" exprs) - (cons - (with-syntax ([startkw first-kw] - [endkw (make-prefix-id "end" first-kw)] - [@endkw (make-prefix-id "@end" first-kw)] - [output output] - [(matches ...) matches] - [(checks ...) checks] - [((x ...) ...) bindings] - [((init-val ...) ...) (build-initial-values bindings list?*)] - [(kw ...) kws] - [(body ...) (build-bodies list?* tmpls updates bindings)]) - #'[@endkw (lambda (k ip sfd stack bfp token-bfp) - (let-values ([(stack bfp) (strip-blanks ip stack bfp)]) - (let loop ([stack stack] [rstack '()] [x init-val] ... ...) - (if (null? stack) - (source-error sfd token-bfp "found @~s with no initial @~s" 'endkw 'startkw) - (let ([item (car stack)]) - (if (incomplete-node? item) - (let ([type (incomplete-node-type item)]) - (case type - [(startkw) checks ... - (with-syntax (matches ...) - (values (cons #`output (cdr stack)) bfp))] - [(kw) body] ... - [else (source-error sfd token-bfp - "found unexpected @~s (~a) instead of expected @~s before @~s" - type (source-string sfd (incomplete-node-bfp item)) 'startkw 'endkw)])) - (loop (cdr stack) (cons item rstack) x ... ...)))))))]) - as*))] - [_ (syntax-violation who "unrecognized pattern" pat)]))) - (syntax-case x () - [(_ pat output) - (with-syntax ([([@kw proc] ...) (process-template #'output #'pat)]) - #'(begin (define-syntax @kw (make-compile-time-value proc)) ...))]))) - - (define-template-extension (num (e)) (number->string e)) - - (define-template-extension (for ([binding e] [bindings es] ...) tmpl) - (with-output-to-string - (lambda () - (for-each (lambda (binding bindings ...) (display tmpl)) e es ...)))) - - (define-template-extension (if (expr) tmpl (elif (exprs) tmpls) ... (optional else else-tmpl)) - (if expr - tmpl - #,(let f ([exprs #'(exprs ...)] [tmpls #'(tmpls ...)]) - (if (null? exprs) - (or #'else-tmpl #'"") - (with-syntax ([expr (car exprs)] [tmpl (car tmpls)] [else (f (cdr exprs) (cdr tmpls))]) - #'(if expr - tmpl - else))))))) -#!eof --------- saving remainder of file to /tmp/t and running /tmp/t should produce only "end of tests" -------- -#!/bin/tcsh - -cat >! /tmp/spam.h << END -extern void @(name)(void); -END - -cat >! /tmp/spam.c << END -#include - -@((include-template "/tmp/spam.h")) - -void @(name)() { - @(name)(); -} -END -scheme -q << END -(import (template)) -(unless (equal? - (let ([name "bob"]) (include-template "/tmp/spam.c")) - "#include \n\nextern void bob(void);\n\n\nvoid bob() {\n bob();\n}\n") - (error #f "test 1 failed")) -END - -cat >! /tmp/spam.c << END -(import (template)) -(unless (equal? - (guard (c [else (with-output-to-string (lambda () (display-condition c)))]) - (expand '(let ([name "bob"]) (include-template "/tmp/spam.c")))) - "Exception in get-datum/annotations: unexpected end-of-file reading list at line 6, char 4 of /tmp/spam.c") - (error #f "test 2 failed")) -END - -cat >! /tmp/spam.c << END -#include - -@((include-template "/tmp/spam.h")) - -void @(name)() { - @(name)(); - @ -} -END -scheme -q << END -(import (template)) -(unless (equal? - (guard (c [else (with-output-to-string (lambda () (display-condition c)))]) - (expand '(let ([name "bob"]) (include-template "/tmp/spam.c")))) - "Exception in include-template: expected open paren or @ following @ at line 7, char 4 of /tmp/spam.c") - (error #f "test 3 failed")) -END - -cat >! /tmp/spam.c << END -#include - -@((include-template "/tmp/spam.h")) - -void @(name)() { - @(name)(); -} -END -echo -n "@" >> /tmp/spam.c -scheme -q << END -(import (template)) -(unless (equal? - (guard (c [else (with-output-to-string (lambda () (display-condition c)))]) - (expand '(let ([name "bob"]) (include-template "/tmp/spam.c")))) - "Exception in include-template: expected open paren or @ following @ at line 8, char 2 of /tmp/spam.c") - (error #f "test 4 failed")) -END - -cat >! /tmp/spam.c << END -#include - -@((include-template #xGO! "/tmp/spam.h")) - -void @(name)() { - @(name)(); -} -END -echo -n "@" >> /tmp/spam.c -scheme -q << END -(import (template)) -(unless (equal? - (guard (c [else (with-output-to-string (lambda () (display-condition c)))]) - (expand '(let ([name "bob"]) (include-template "/tmp/spam.c")))) - "Exception in get-datum/annotations: invalid number syntax #xGO! at line 3, char 21 of /tmp/spam.c") - (error #f "test 5 failed")) -END - -cat >! /tmp/spam.c << END -#include - -@((include-template)) - -void @(name)() { - @(name)(); -} -END -scheme -q << END -(import (template)) -(unless (equal? - (guard (c [else (with-output-to-string (lambda () (display-condition c)))]) - (expand '(let ([name "bob"]) (include-template "/tmp/spam.c")))) - "Exception: invalid syntax (include-template) at line 3, char 3 of /tmp/spam.c") - (error #f "test 6 failed")) -END - -cat >! /tmp/spam.c < - -/* function: @(name) - * - * @@param: @(name) - */ -@((include-template "/tmp/spam.h")) - -void @(name)() { - @(name)(); -} -END -scheme -q << END -(import (template)) -(unless (equal? (let ([name "bob"]) (include-template "/tmp/spam.c")) - "#include \n\n/* function: bob\n *\n * @param: bob\n */\nextern void bob(void);\n\n\nvoid bob() {\n bob();\n}\n") - (error #f "test 7 failed")) -END - -cat >! /tmp/rockets <> /tmp/rockets <> /tmp/rockets <! /tmp/indent-test.c << END -#include - -int main(int argc, char *argv[]) { - @(body) -} -END -scheme -q << END -(import (template)) -(unless (equal? (let ([body "printf(\"Hello, world!\\\\n\");\nprintf(\"So... uh, what's going on?\\\\n\");\nprintf(\"Well, goodbye then.\\\\n\");"]) - (include-template "/tmp/indent-test.c")) - "#include \n\nint main(int argc, char *argv[]) {\n printf(\"Hello, world!\\\\n\");\n printf(\"So... uh, what's going on?\\\\n\");\n printf(\"Well, goodbye then.\\\\n\");\n}\n") - (error #f "test 17 failed")) -END -cat >! /tmp/hygeine << END -Hygiene test: - -@for([t i*]) - got @(t) . -@endfor - -@for([x j*]) - got @(x) and t is @(t). -@endfor - -@let([outer-t t]) - @for([x i*] [t j*]) - got @(x) and @(t) and @(outer-t). - @endfor -@endlet -END -scheme -q << END -(import (template)) -(let () - (define-template-extension (for ([x e] [xs es] ...) tmpl) - (let ([t e]) - (apply string-append (map (lambda (x xs ...) tmpl) t es ...)))) - (define-template-extension (let ([x e] [xs es] ...) tmpl) - (let ([x e] [xs es] ...) tmpl)) - (unless (equal? (let ([t "10"] [i* '("1" "2" "3")] [j* '("a" "b" "c")]) - (include-template "/tmp/hygeine")) - "Hygiene test:\n\n got 1 .\n got 2 .\n got 3 .\n\n got a and t is 10.\n got b and t is 10.\n got c and t is 10.\n\n got 1 and a and 10.\n got 2 and b and 10.\n got 3 and c and 10.\n") - (error #f "test 18 failed"))) -END -cat >! /tmp/indent << END -This is to test indents: - simple indent: @(x) - - nested indents: @(y) @(x) -END -scheme -q << END -(import (template)) -(unless (equal? (let ([x "a\nb\nc\n"] [y "x\ny\nz"]) - (include-template "/tmp/indent")) - "This is to test indents:\n simple indent: a\n b\n c\n\n\n nested indents: x\n y\n z a\n b\n c\n\n") - (error #f "test 19 failed")) -END -echo "end of tests" - diff --git a/ta6ob/examples/unify.ss b/ta6ob/examples/unify.ss deleted file mode 100644 index 756c27f..0000000 --- a/ta6ob/examples/unify.ss +++ /dev/null @@ -1,91 +0,0 @@ -;;; unify.ss -;;; Copyright (C) 1996 R. Kent Dybvig -;;; from "The Scheme Programming Language, 2ed" by R. Kent Dybvig - -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -(define unify #f) -(let () - ;; occurs? returns true if and only if u occurs in v - (define occurs? - (lambda (u v) - (and (pair? v) - (let f ((l (cdr v))) - (and (pair? l) - (or (eq? u (car l)) - (occurs? u (car l)) - (f (cdr l)))))))) - - ;; sigma returns a new substitution procedure extending s by - ;; the substitution of u with v - (define sigma - (lambda (u v s) - (lambda (x) - (let f ((x (s x))) - (if (symbol? x) - (if (eq? x u) v x) - (cons (car x) (map f (cdr x)))))))) - - ;; try-subst tries to substitute u for v but may require a - ;; full unification if (s u) is not a variable, and it may - ;; fail if it sees that u occurs in v. - (define try-subst - (lambda (u v s ks kf) - (let ((u (s u))) - (if (not (symbol? u)) - (uni u v s ks kf) - (let ((v (s v))) - (cond - ((eq? u v) (ks s)) - ((occurs? u v) (kf "cycle")) - (else (ks (sigma u v s))))))))) - - ;; uni attempts to unify u and v with a continuation-passing - ;; style that returns a substitution to the success argument - ;; ks or an error message to the failure argument kf. The - ;; substitution itself is represented by a procedure from - ;; variables to terms. - (define uni - (lambda (u v s ks kf) - (cond - ((symbol? u) (try-subst u v s ks kf)) - ((symbol? v) (try-subst v u s ks kf)) - ((and (eq? (car u) (car v)) - (= (length u) (length v))) - (let f ((u (cdr u)) (v (cdr v)) (s s)) - (if (null? u) - (ks s) - (uni (car u) - (car v) - s - (lambda (s) (f (cdr u) (cdr v) s)) - kf)))) - (else (kf "clash"))))) - - ;; unify shows one possible interface to uni, where the initial - ;; substitution is the identity procedure, the initial success - ;; continuation returns the unified term, and the initial failure - ;; continuation returns the error message. - (set! unify - (lambda (u v) - (uni u - v - (lambda (x) x) - (lambda (s) (s u)) - (lambda (msg) msg))))) diff --git a/ta6ob/installsh b/ta6ob/installsh deleted file mode 100755 index 95d85fb..0000000 --- a/ta6ob/installsh +++ /dev/null @@ -1,79 +0,0 @@ -#! /bin/sh -if [ -x /bin/true ]; then TRUE=/bin/true; -elif [ -x /usr/bin/true ]; then TRUE=/usr/bin/true; -elif command -v true &> /dev/null; then TRUE=true; -else echo "Can't find /bin/true or /usr/bin/true and no true command" ; exit 1; -fi - -while ${TRUE} ; do - mkdirs=0 - ifdiff=0 - - while [ $# -ge 0 ] ; do - case $1 in - -d) mkdirs=1 ;; - -o) shift; owner=$1 ;; - -g) shift; group=$1 ;; - -m) shift; mode=$1 ;; - --ifdiff) ifdiff=1 ;; - -*) break 2 ;; - *) break ;; - esac - shift - done - - if [ $mkdirs -eq 1 ] && [ $ifdiff -eq 1 ] ; then - break - fi - - if [ $mkdirs -eq 1 ] ; then - dirs=$* - - for dir in $dirs ; do - stack="" - while [ "$dir" != "/" -a "$dir" != "." -a "$dir" != ".." ] ; do - stack="$dir $stack" - dir=`dirname $dir` - done - - for dir in $stack ; do - if [ ! -d $dir ] ; then - if mkdir $dir ; then - if [ "$owner" != "" ] ; then chown $owner $dir ; fi - if [ "$group" != "" ] ; then chgrp $group $dir ; fi - if [ "$mode" != "" ] ; then chmod $mode $dir ; fi - fi - fi - done - done - else - nargs=$# - if [ $nargs -lt 2 ] ; then break ; fi - - files="" - while [ $# -ne 1 ] ; do - files="$files $1" - shift - done - dest=$1 - - if [ ! -d $dest -a $nargs -ne 2 ] ; then break ; fi - - for file in $files ; do - destfile=$dest - if [ -d $destfile ] ; then destfile=$destfile/`basename $file` ; fi - if [ $ifdiff -eq 1 ] && cmp -s $file $destfile || cp -f -p $file $destfile ; then - if [ "$owner" != "" ] ; then chown $owner $destfile ; fi - if [ "$group" != "" ] ; then chgrp $group $destfile ; fi - if [ "$mode" != "" ] ; then chmod $mode $destfile ; fi - fi - done - fi - - exit 0 -done - -echo "usage: $0 [ -o owner] [ -g group ] [ -m mode ] [ --ifdiff] file dest" -echo " $0 [ -o owner] [ -g group ] [ -m mode ] [ --ifdiff] file file ... dir" -echo " $0 -d [ -o owner] [ -g group ] [ -m mode ] dir dir ..." -exit 1 diff --git a/ta6ob/lz4/.circleci/config.yml b/ta6ob/lz4/.circleci/config.yml deleted file mode 100644 index 7f03d1a..0000000 --- a/ta6ob/lz4/.circleci/config.yml +++ /dev/null @@ -1,75 +0,0 @@ -# This configuration was automatically generated from a CircleCI 1.0 config. -# It should include any build commands you had along with commands that CircleCI -# inferred from your project structure. We strongly recommend you read all the -# comments in this file to understand the structure of CircleCI 2.0, as the idiom -# for configuration has changed substantially in 2.0 to allow arbitrary jobs rather -# than the prescribed lifecycle of 1.0. In general, we recommend using this generated -# configuration as a reference rather than using it in production, though in most -# cases it should duplicate the execution of your original 1.0 config. -version: 2 -jobs: - build: - working_directory: ~/lz4/lz4 - # Parallelism is broken in this file : it just plays the same tests twice. - # The script will have to be modified to support parallelism properly - # In the meantime, set it to 1. - parallelism: 1 - shell: /bin/bash --login - # CircleCI 2.0 does not support environment variables that refer to each other the same way as 1.0 did. - # If any of these refer to each other, rewrite them so that they don't or see https://circleci.com/docs/2.0/env-vars/#interpolating-environment-variables-to-set-other-environment-variables . - environment: - CIRCLE_ARTIFACTS: /tmp/circleci-artifacts - CIRCLE_TEST_REPORTS: /tmp/circleci-test-results - # In CircleCI 1.0 we used a pre-configured image with a large number of languages and other packages. - # In CircleCI 2.0 you can now specify your own image, or use one of our pre-configured images. - # The following configuration line tells CircleCI to use the specified docker image as the runtime environment for you job. - # We have selected a pre-built image that mirrors the build environment we use on - # the 1.0 platform, but we recommend you choose an image more tailored to the needs - # of each job. For more information on choosing an image (or alternatively using a - # VM instead of a container) see https://circleci.com/docs/2.0/executor-types/ - # To see the list of pre-built images that CircleCI provides for most common languages see - # https://circleci.com/docs/2.0/circleci-images/ - docker: - - image: fbopensource/lz4-circleci-primary:0.0.4 - steps: - # Machine Setup - # If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each - # The following `checkout` command checks out your code to your working directory. In 1.0 we did this implicitly. In 2.0 you can choose where in the course of a job your code should be checked out. - - checkout - # Prepare for artifact and test results collection equivalent to how it was done on 1.0. - # In many cases you can simplify this from what is generated here. - # 'See docs on artifact collection here https://circleci.com/docs/2.0/artifacts/' - - run: mkdir -p $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS - # Test - # This would typically be a build job when using workflows, possibly combined with build - # This is based on your 1.0 configuration file or project settings - - run: CFLAGS= make clangtest && make clean - - run: g++ -v; make gpptest && make clean - - run: gcc -v; g++ -v; make ctocpptest && make clean - - run: gcc-5 -v; CC=gcc-5 CFLAGS="-O2 -Werror" make check && make clean - - run: gcc-5 -v; CC=gcc-5 CFLAGS="-O2 -m32 -Werror" CPPFLAGS=-I/usr/include/x86_64-linux-gnu make check && make clean - - run: gcc-6 -v; CC=gcc-6 MOREFLAGS="-O2 -Werror" make check && make clean - - run: make cmake && make clean - - run: make -C tests test-lz4 - - run: make -C tests test-lz4c - - run: make -C tests test-frametest - - run: make -C tests test-fuzzer && make clean - - run: make -C lib all && make clean - - run: pyenv global 3.4.4; make versionsTest MOREFLAGS=-I/usr/include/x86_64-linux-gnu && make clean - - run: make travis-install && make clean - - run: gcc -v; CFLAGS="-O2 -m32 -Werror" CPPFLAGS=-I/usr/include/x86_64-linux-gnu make check && make clean - - run: clang -v; make staticAnalyze && make clean - - run: make platformTest CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc-static && make clean - - run: make platformTest CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc64-static MOREFLAGS=-m64 && make clean - - run: make platformTest CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static && make clean - - run: make platformTest CC=aarch64-linux-gnu-gcc QEMU_SYS=qemu-aarch64-static && make clean - # Teardown - # If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each - # Save test results - - store_test_results: - path: /tmp/circleci-test-results - # Save artifacts - - store_artifacts: - path: /tmp/circleci-artifacts - - store_artifacts: - path: /tmp/circleci-test-results diff --git a/ta6ob/lz4/.circleci/images/primary/Dockerfile b/ta6ob/lz4/.circleci/images/primary/Dockerfile deleted file mode 100644 index 7767014..0000000 --- a/ta6ob/lz4/.circleci/images/primary/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM circleci/buildpack-deps:bionic - -RUN sudo apt-get -y -qq update -RUN sudo apt-get -y install software-properties-common -RUN sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test -RUN sudo apt-get -y install cmake -RUN sudo apt-get -y install qemu-system-ppc qemu-user-static qemu-system-arm -RUN sudo apt-get -y install libc6-dev-armel-cross libc6-dev-arm64-cross libc6-dev-i386 -RUN sudo apt-get -y install clang clang-tools -RUN sudo apt-get -y install gcc-5 gcc-5-multilib gcc-6 -RUN sudo apt-get -y install valgrind -RUN sudo apt-get -y install gcc-multilib-powerpc-linux-gnu gcc-powerpc-linux-gnu gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu diff --git a/ta6ob/lz4/.cirrus.yml b/ta6ob/lz4/.cirrus.yml deleted file mode 100644 index 0c0e7a7..0000000 --- a/ta6ob/lz4/.cirrus.yml +++ /dev/null @@ -1,5 +0,0 @@ -freebsd_instance: - image_family: freebsd-12-1 - -task: - script: pkg install -y gmake && gmake test diff --git a/ta6ob/lz4/.gitattributes b/ta6ob/lz4/.gitattributes deleted file mode 100644 index 6212bd4..0000000 --- a/ta6ob/lz4/.gitattributes +++ /dev/null @@ -1,21 +0,0 @@ -# Set the default behavior -* text eol=lf - -# Explicitly declare source files -*.c text eol=lf -*.h text eol=lf - -# Denote files that should not be modified. -*.odt binary -*.png binary - -# Visual Studio -*.sln text eol=crlf -*.vcxproj* text eol=crlf -*.vcproj* text eol=crlf -*.suo binary -*.rc text eol=crlf - -# Windows -*.bat text eol=crlf -*.cmd text eol=crlf diff --git a/ta6ob/lz4/.github/ISSUE_TEMPLATE/bug_report.md b/ta6ob/lz4/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 86b7696..0000000 --- a/ta6ob/lz4/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**Expected behavior** -Please describe what you expected to happen. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error '...' -If applicable, add screenshots to help explain your problem. - -**System (please complete the following information):** - - OS: [e.g. Mac] - - Version [e.g. 22] - - Compiler [e.g. gcc] - - Build System [e.g. Makefile] - - Other hardware specs [e.g Core 2 duo...] - -**Additional context** -Add any other context about the problem here. diff --git a/ta6ob/lz4/.github/ISSUE_TEMPLATE/feature_request.md b/ta6ob/lz4/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bbcbbe7..0000000 --- a/ta6ob/lz4/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/ta6ob/lz4/.gitignore b/ta6ob/lz4/.gitignore deleted file mode 100644 index d7ba96e..0000000 --- a/ta6ob/lz4/.gitignore +++ /dev/null @@ -1,41 +0,0 @@ -# Object files -*.o -*.ko - -# Libraries -*.lib -*.a - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib -*.dSYM # apple - -# Executables -*.exe -*.out -*.app -lz4 - -# IDE / editors files -.clang_complete -_codelite/ -_codelite_lz4/ -bin/ -*.zip - -# analyzers -infer-out - -# Mac -.DS_Store -*.dSYM - -# Windows / Msys -nul -ld.exe* - -# test files -*.lz4 diff --git a/ta6ob/lz4/.travis.yml b/ta6ob/lz4/.travis.yml deleted file mode 100644 index f201d52..0000000 --- a/ta6ob/lz4/.travis.yml +++ /dev/null @@ -1,236 +0,0 @@ -language: c - -matrix: - fast_finish: true - include: - # OS X Mavericks - - name: (macOS) General Test - os: osx - compiler: clang - script: - - make # test library build - - make clean - - make test MOREFLAGS='-Werror -Wconversion -Wno-sign-conversion' | tee # test scenario where `stdout` is not the console - - # Container-based 12.04 LTS Server Edition 64 bit (doesn't support 32-bit includes) - - name: (Precise) benchmark test - dist: precise - script: - - make -C tests test-lz4 test-lz4c test-fullbench - - - name: (Precise) frame and fuzzer test - dist: precise - install: - - sudo sysctl -w vm.mmap_min_addr=4096 - script: - - make -C tests test-frametest test-fuzzer - - - name: ASAN tests with fuzzer and frametest - install: - - sudo sysctl -w vm.mmap_min_addr=4096 - script: - - CC=clang MOREFLAGS=-fsanitize=address make -C tests test-frametest test-fuzzer - - - name: Custom LZ4_DISTANCE_MAX ; lz4-wlib (CLI linked to dynamic library); LZ4_USER_MEMORY_FUNCTIONS - script: - - MOREFLAGS=-DLZ4_DISTANCE_MAX=8000 make check - - make clean - - make -C programs lz4-wlib - - make clean - - make -C tests fullbench-wmalloc # test LZ4_USER_MEMORY_FUNCTIONS - - make clean - - CC="c++ -Wno-deprecated" make -C tests fullbench-wmalloc # stricter function signature check - - - name: (Precise) g++ and clang CMake test - dist: precise - script: - - make gpptest - - make clean - - make examples - - make clean cmake - - make clean travis-install - - make clean clangtest - - - name: x32 compatibility test - addons: - apt: - packages: - - gcc-multilib - script: - - make -C tests test MOREFLAGS=-mx32 - - # 14.04 LTS Server Edition 64 bit - # presume clang >= v3.9.0 - - name: (Trusty) USan test - dist: trusty - compiler: clang - script: - - make usan MOREFLAGS=-Wcomma -Werror - - - name: (Trusty) valgrind test - dist: trusty - install: - - sudo apt-get install -qq valgrind - script: - - make c_standards - - make -C tests test-lz4 test-mem - - - name: (Trusty) c-to-c++ test - dist: trusty - script: - - make ctocpptest - - - name: (Trusty) i386 benchmark + version test - dist: trusty - install: - - sudo apt-get install -qq python3 libc6-dev-i386 gcc-multilib - script: - - make -C tests test-lz4c32 test-fullbench32 versionsTest - - - name: (Trusty) i386 frame + fuzzer test - dist: trusty - install: - - sudo apt-get install -qq libc6-dev-i386 gcc-multilib - - sudo sysctl -w vm.mmap_min_addr=4096 - script: - - make -C tests test-frametest32 test-fuzzer32 - - - name: (Trusty) gcc-6 standard C compilation - dist: trusty - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-6 - env: - - CC=gcc-6 - script: - - make c_standards - - make -C tests test-lz4 MOREFLAGS=-Werror - - - name: (Trusty) arm + aarch64 compilation - dist: trusty - install: - - sudo apt-get install -qq - qemu-system-arm - qemu-user-static - gcc-arm-linux-gnueabi - libc6-dev-armel-cross - gcc-aarch64-linux-gnu - libc6-dev-arm64-cross - script: - - make platformTest CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static - - make platformTest CC=aarch64-linux-gnu-gcc QEMU_SYS=qemu-aarch64-static - - - name: aarch64 real-hw tests - arch: arm64 - script: - - make test - - - name: PPC64LE real-hw tests - arch: ppc64le - script: - - make test - - - name: IBM s390x real-hw tests - arch: s390x - script: - - make test - - - name: (Xenial) gcc-5 compilation - dist: xenial - install: - - sudo apt-get install -qq libc6-dev-i386 gcc-multilib - script: - - make -C tests test-lz4 clean test-lz4c32 MOREFLAGS=-Werror - - - name: (Trusty) clang-3.8 compilation - dist: trusty - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-precise-3.8 - packages: - - clang-3.8 - script: - - make -C tests test-lz4 CC=clang-3.8 - - - name: (Trusty) PowerPC + PPC64 compilation - dist: trusty - install: - - sudo apt-get install -qq qemu-system-ppc qemu-user-static gcc-powerpc-linux-gnu - script: - - make platformTest CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc-static - - make platformTest CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc64-static MOREFLAGS=-m64 - - - name: (Trusty) scan-build + cppcheck - dist: trusty - compiler: clang - install: - - sudo apt-get install -qq cppcheck - script: - - make staticAnalyze - - make cppcheck - - - name: (Trusty) gcc-4.4 compilation - dist: trusty - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - libc6-dev-i386 - - gcc-multilib - - gcc-4.4 - script: - - make clean all CC=gcc-4.4 MOREFLAGS=-Werror - - make clean - - CFLAGS=-fPIC LDFLAGS='-pie -fPIE -D_FORTIFY_SOURCE=2' make -C programs - - # tag-specific test - - name: tag build - if: tag =~ ^v[0-9]\.[0-9] - os: linux - script: - - make -C tests checkTag - - tests/checkTag "$TRAVIS_BRANCH" - - - name: (Xenial) Meson + clang build - #env: ALLOW_FAILURES=true - dist: xenial - language: cpp - compiler: clang - install: - - sudo apt-get install -qq python3 tree - - | - travis_retry curl -o ~/ninja.zip -L 'https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-linux.zip' && - unzip ~/ninja.zip -d ~/.local/bin - - | - travis_retry curl -o ~/get-pip.py 'https://bootstrap.pypa.io/get-pip.py' && - python3 ~/get-pip.py --user && - pip3 install --user meson - script: - - | - meson setup \ - --buildtype=debug \ - -Db_lundef=false \ - -Dauto_features=enabled \ - -Ddefault_library=both \ - -Dbin_programs=true \ - -Dbin_contrib=true \ - -Dbin_tests=true \ - -Dbin_examples=true \ - contrib/meson build - - pushd build - - DESTDIR=./staging ninja install - - tree ./staging - - # oss-fuzz compilation test - - name: Compile OSS-Fuzz targets - script: - - ./ossfuzz/travisoss.sh - - allow_failures: - - env: ALLOW_FAILURES=true diff --git a/ta6ob/lz4/INSTALL b/ta6ob/lz4/INSTALL deleted file mode 100644 index 6aab067..0000000 --- a/ta6ob/lz4/INSTALL +++ /dev/null @@ -1,16 +0,0 @@ -Installation -============= - -``` -make -make install # this command may require root access -``` - -LZ4's `Makefile` supports standard [Makefile conventions], -including [staged installs], [redirection], or [command redefinition]. -It is compatible with parallel builds (`-j#`). - -[Makefile conventions]: https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html -[staged installs]: https://www.gnu.org/prep/standards/html_node/DESTDIR.html -[redirection]: https://www.gnu.org/prep/standards/html_node/Directory-Variables.html -[command redefinition]: https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html diff --git a/ta6ob/lz4/LICENSE b/ta6ob/lz4/LICENSE deleted file mode 100644 index c221aeb..0000000 --- a/ta6ob/lz4/LICENSE +++ /dev/null @@ -1,11 +0,0 @@ -This repository uses 2 different licenses : -- all files in the `lib` directory use a BSD 2-Clause license -- all other files use a GPLv2 license, unless explicitly stated otherwise - -Relevant license is reminded at the top of each source file, -and with presence of COPYING or LICENSE file in associated directories. - -This model is selected to emphasize that -files in the `lib` directory are designed to be included into 3rd party applications, -while all other files, in `programs`, `tests` or `examples`, -receive more limited attention and support for such scenario. diff --git a/ta6ob/lz4/Makefile b/ta6ob/lz4/Makefile deleted file mode 100644 index 744005f..0000000 --- a/ta6ob/lz4/Makefile +++ /dev/null @@ -1,208 +0,0 @@ -# ################################################################ -# LZ4 - Makefile -# Copyright (C) Yann Collet 2011-present -# All rights reserved. -# -# BSD license -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, this -# list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# You can contact the author at : -# - LZ4 source repository : https://github.com/lz4/lz4 -# - LZ4 forum froup : https://groups.google.com/forum/#!forum/lz4c -# ################################################################ - -LZ4DIR = lib -PRGDIR = programs -TESTDIR = tests -EXDIR = examples -FUZZDIR = ossfuzz - -include Makefile.inc - -.PHONY: default -default: lib-release lz4-release - -.PHONY: all -all: allmost examples manuals build_tests - -.PHONY: allmost -allmost: lib lz4 - -.PHONY: lib lib-release liblz4.a -lib: liblz4.a -lib lib-release liblz4.a: - @$(MAKE) -C $(LZ4DIR) $@ - -.PHONY: lz4 lz4-release -lz4 : liblz4.a -lz4-release : lib-release -lz4 lz4-release : - @$(MAKE) -C $(PRGDIR) $@ - @cp $(PRGDIR)/lz4$(EXT) . - -.PHONY: examples -examples: liblz4.a - $(MAKE) -C $(EXDIR) all - -.PHONY: manuals -manuals: - @$(MAKE) -C contrib/gen_manual $@ - -.PHONY: build_tests -build_tests: - @$(MAKE) -C $(TESTDIR) all - -.PHONY: clean -clean: - @$(MAKE) -C $(LZ4DIR) $@ > $(VOID) - @$(MAKE) -C $(PRGDIR) $@ > $(VOID) - @$(MAKE) -C $(TESTDIR) $@ > $(VOID) - @$(MAKE) -C $(EXDIR) $@ > $(VOID) - @$(MAKE) -C $(FUZZDIR) $@ > $(VOID) - @$(MAKE) -C contrib/gen_manual $@ > $(VOID) - @$(RM) lz4$(EXT) - @echo Cleaning completed - - -#----------------------------------------------------------------------------- -# make install is validated only for Linux, OSX, BSD, Hurd and Solaris targets -#----------------------------------------------------------------------------- -ifeq ($(POSIX_ENV),Yes) -HOST_OS = POSIX - -.PHONY: install uninstall -install uninstall: - @$(MAKE) -C $(LZ4DIR) $@ - @$(MAKE) -C $(PRGDIR) $@ - -travis-install: - $(MAKE) -j1 install DESTDIR=~/install_test_dir - -cmake: - @cd build/cmake; cmake $(CMAKE_PARAMS) CMakeLists.txt; $(MAKE) - -endif - - -ifneq (,$(filter MSYS%,$(shell uname))) -HOST_OS = MSYS -CMAKE_PARAMS = -G"MSYS Makefiles" -endif - - -#------------------------------------------------------------------------ -#make tests validated only for MSYS, Linux, OSX, kFreeBSD and Hurd targets -#------------------------------------------------------------------------ -ifneq (,$(filter $(HOST_OS),MSYS POSIX)) - -.PHONY: list -list: - @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs - -.PHONY: check -check: - $(MAKE) -C $(TESTDIR) test-lz4-essentials - -.PHONY: test -test: - CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" $(MAKE) -C $(TESTDIR) $@ - CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" $(MAKE) -C $(EXDIR) $@ - -clangtest: CFLAGS ?= -O3 -clangtest: CFLAGS += -Werror -Wconversion -Wno-sign-conversion -clangtest: CC = clang -clangtest: clean - $(CC) -v - @CFLAGS="$(CFLAGS)" $(MAKE) -C $(LZ4DIR) all CC=$(CC) - @CFLAGS="$(CFLAGS)" $(MAKE) -C $(PRGDIR) all CC=$(CC) - @CFLAGS="$(CFLAGS)" $(MAKE) -C $(TESTDIR) all CC=$(CC) - -clangtest-native: clean - clang -v - @CFLAGS="-O3 -Werror -Wconversion -Wno-sign-conversion" $(MAKE) -C $(LZ4DIR) all CC=clang - @CFLAGS="-O3 -Werror -Wconversion -Wno-sign-conversion" $(MAKE) -C $(PRGDIR) native CC=clang - @CFLAGS="-O3 -Werror -Wconversion -Wno-sign-conversion" $(MAKE) -C $(TESTDIR) native CC=clang - -usan: CC = clang -usan: CFLAGS = -O3 -g -fsanitize=undefined -fno-sanitize-recover=undefined -fsanitize-recover=pointer-overflow -usan: LDFLAGS = $(CFLAGS) -usan: clean - CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" $(MAKE) test FUZZER_TIME="-T30s" NB_LOOPS=-i1 - -usan32: clean - CFLAGS="-m32 -O3 -g -fsanitize=undefined" $(MAKE) test FUZZER_TIME="-T30s" NB_LOOPS=-i1 - -SCANBUILD ?= scan-build -SCANBUILD_FLAGS += --status-bugs -v --force-analyze-debug-code -.PHONY: staticAnalyze -staticAnalyze: clean - CPPFLAGS=-DLZ4_DEBUG=1 CFLAGS=-g $(SCANBUILD) $(SCANBUILD_FLAGS) $(MAKE) all V=1 DEBUGLEVEL=1 - -.PHONY: cppcheck -cppcheck: - cppcheck . --force --enable=warning,portability,performance,style --error-exitcode=1 > /dev/null - -platformTest: clean - @echo "\n ---- test lz4 with $(CC) compiler ----" - @$(CC) -v - CFLAGS="-O3 -Werror" $(MAKE) -C $(LZ4DIR) all - CFLAGS="-O3 -Werror -static" $(MAKE) -C $(PRGDIR) all - CFLAGS="-O3 -Werror -static" $(MAKE) -C $(TESTDIR) all - $(MAKE) -C $(TESTDIR) test-platform - -.PHONY: versionsTest -versionsTest: clean - $(MAKE) -C $(TESTDIR) $@ - -gpptest gpptest32: CC = "$(CXX) -Wno-deprecated" -gpptest gpptest32: CFLAGS = -O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror -gpptest32: CFLAGS += -m32 -gpptest gpptest32: clean - $(CXX) -v - CC=$(CC) $(MAKE) -C $(LZ4DIR) all CFLAGS="$(CFLAGS)" - CC=$(CC) $(MAKE) -C $(PRGDIR) all CFLAGS="$(CFLAGS)" - CC=$(CC) $(MAKE) -C $(TESTDIR) all CFLAGS="$(CFLAGS)" - -cxx17build : CC = "$(CXX) -Wno-deprecated" -cxx17build : CFLAGS = -std=c++17 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror -pedantic -cxx17build : clean - $(CXX) -v - CC=$(CC) $(MAKE) -C $(LZ4DIR) all CFLAGS="$(CFLAGS)" - CC=$(CC) $(MAKE) -C $(PRGDIR) all CFLAGS="$(CFLAGS)" - CC=$(CC) $(MAKE) -C $(TESTDIR) all CFLAGS="$(CFLAGS)" - -ctocpptest: LIBCC="$(CC)" -ctocpptest: TESTCC="$(CXX)" -ctocpptest: CFLAGS="" -ctocpptest: clean - CC=$(LIBCC) $(MAKE) -C $(LZ4DIR) CFLAGS="$(CFLAGS)" all - CC=$(LIBCC) $(MAKE) -C $(TESTDIR) CFLAGS="$(CFLAGS)" lz4.o lz4hc.o lz4frame.o - CC=$(TESTCC) $(MAKE) -C $(TESTDIR) CFLAGS="$(CFLAGS)" all - -c_standards: clean - $(MAKE) clean; CFLAGS="-std=c90 -Werror -pedantic -Wno-long-long -Wno-variadic-macros" $(MAKE) allmost - $(MAKE) clean; CFLAGS="-std=gnu90 -Werror -pedantic -Wno-long-long -Wno-variadic-macros" $(MAKE) allmost - $(MAKE) clean; CFLAGS="-std=c99 -Werror -pedantic" $(MAKE) all - $(MAKE) clean; CFLAGS="-std=gnu99 -Werror -pedantic" $(MAKE) all - $(MAKE) clean; CFLAGS="-std=c11 -Werror" $(MAKE) all - -endif diff --git a/ta6ob/lz4/Makefile.inc b/ta6ob/lz4/Makefile.inc deleted file mode 100644 index 2d64405..0000000 --- a/ta6ob/lz4/Makefile.inc +++ /dev/null @@ -1,87 +0,0 @@ -ifeq ($(V), 1) -Q = -else -Q = @ -endif - -TARGET_OS ?= $(shell uname) -ifeq ($(TARGET_OS),) - TARGET_OS ?= $(OS) -endif - -ifneq (,$(filter Windows%,$(TARGET_OS))) -LIBLZ4 = liblz4-$(LIBVER_MAJOR) -LIBLZ4_EXP = liblz4.lib -WINBASED = yes -else -LIBLZ4_EXP = liblz4.dll.a - ifneq (,$(filter MINGW%,$(TARGET_OS))) -LIBLZ4 = liblz4 -WINBASED = yes - else - ifneq (,$(filter MSYS%,$(TARGET_OS))) -LIBLZ4 = msys-lz4-$(LIBVER_MAJOR) -WINBASED = yes - else - ifneq (,$(filter CYGWIN%,$(TARGET_OS))) -LIBLZ4 = cyglz4-$(LIBVER_MAJOR) -WINBASED = yes - else -LIBLZ4 = liblz4.$(SHARED_EXT_VER) -WINBASED = no -EXT = - endif - endif - endif -endif - -ifeq ($(WINBASED),yes) -EXT = .exe -WINDRES = windres -endif - -#determine if dev/nul based on host environment -ifneq (,$(filter MINGW% MSYS% CYGWIN%,$(shell uname))) -VOID := /dev/null -else - ifneq (,$(filter Windows%,$(OS))) -VOID := nul - else -VOID := /dev/null - endif -endif - -ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS Haiku MidnightBSD MINGW% CYGWIN% MSYS%,$(shell uname))) -POSIX_ENV = Yes -else -POSIX_ENV = No -endif - -# Avoid symlinks when targetting Windows or building on a Windows host -ifeq ($(WINBASED),yes) -LN_S = cp -p -LN_SF = cp -p -else - ifneq (,$(filter MINGW% MSYS% CYGWIN%,$(shell uname))) -LN_S = cp -p -LN_SF = cp -p - else - ifneq (,$(filter Windows%,$(OS))) -LN_S = cp -p -LN_SF = cp -p - else -LN_S = ln -s -LN_SF = ln -sf - endif - endif -endif - -ifneq (,$(filter $(shell uname),SunOS)) -INSTALL ?= ginstall -else -INSTALL ?= install -endif - -INSTALL_PROGRAM ?= $(INSTALL) -m 755 -INSTALL_DATA ?= $(INSTALL) -m 644 -INSTALL_DIR ?= $(INSTALL) -d -m 755 diff --git a/ta6ob/lz4/NEWS b/ta6ob/lz4/NEWS deleted file mode 100644 index 401931e..0000000 --- a/ta6ob/lz4/NEWS +++ /dev/null @@ -1,320 +0,0 @@ -v1.9.3 -perf: highly improved speed in kernel space, by @terrelln -perf: faster speed with Visual Studio, thanks to @wolfpld and @remittor -perf: improved dictionary compression speed, by @felixhandte -perf: fixed LZ4_compress_HC_destSize() ratio, detected by @hsiangkao -perf: reduced stack usage in high compression mode, by @Yanpas -api : LZ4_decompress_safe_partial() supports unknown compressed size, requested by @jfkthame -api : improved LZ4F_compressBound() with automatic flushing, by Christopher Harvie -api : can (de)compress to/from NULL without UBs -api : fix alignment test on 32-bit systems (state initialization) -api : fix LZ4_saveDictHC() in corner case scenario, detected by @IgorKorkin -cli : `-l` legacy format is now compatible with `-m` multiple files, by Filipe Calasans -cli : benchmark mode supports dictionary, by @rkoradi -cli : fix --fast with large argument, detected by @picoHz -build: link to user-defined memory functions with LZ4_USER_MEMORY_FUNCTIONS, suggested by Yuriy Levchenko -build: contrib/cmake_unofficial/ moved to build/cmake/ -build: visual/* moved to build/ -build: updated meson script, by @neheb -build: tinycc support, by Anton Kochkov -install: Haiku support, by Jerome Duval -doc : updated LZ4 frame format, clarify EndMark - -v1.9.2 -fix : out-of-bound read in exceptional circumstances when using decompress_partial(), by @terrelln -fix : slim opportunity for out-of-bound write with compress_fast() with a large enough input and when providing an output smaller than recommended (< LZ4_compressBound(inputSize)), by @terrelln -fix : rare data corruption bug with LZ4_compress_destSize(), by @terrelln -fix : data corruption bug when Streaming with an Attached Dict in HC Mode, by @felixhandte -perf: enable LZ4_FAST_DEC_LOOP on aarch64/GCC by default, by @prekageo -perf: improved lz4frame streaming API speed, by @dreambottle -perf: speed up lz4hc on slow patterns when using external dictionary, by @terrelln -api: better in-place decompression and compression support -cli : --list supports multi-frames files, by @gstedman -cli: --version outputs to stdout -cli : add option --best as an alias of -12 , by @Low-power -misc: Integration into oss-fuzz by @cmeister2, expanded list of scenarios by @terrelln - -v1.9.1 -fix : decompression functions were reading a few bytes beyond input size (introduced in v1.9.0, reported by @ppodolsky and @danlark1) -api : fix : lz4frame initializers compatibility with c++, reported by @degski -cli : added command --list, based on a patch by @gabrielstedman -build: improved Windows build, by @JPeterMugaas -build: AIX, by Norman Green - -v1.9.0 -perf: large decompression speed improvement on x86/x64 (up to +20%) by @djwatson -api : changed : _destSize() compression variants are promoted to stable API -api : new : LZ4_initStream(HC), replacing LZ4_resetStream(HC) -api : changed : LZ4_resetStream(HC) as recommended reset function, for better performance on small data -cli : support custom block sizes, by @blezsan -build: source code can be amalgamated, by Bing Xu -build: added meson build, by @lzutao -build: new build macros : LZ4_DISTANCE_MAX, LZ4_FAST_DEC_LOOP -install: MidnightBSD, by @laffer1 -install: msys2 on Windows 10, by @vtorri - -v1.8.3 -perf: minor decompression speed improvement (~+2%) with gcc -fix : corruption in v1.8.2 at level 9 for files > 64KB under rare conditions (#560) -cli : new command --fast, by @jennifermliu -cli : fixed elapsed time, and added cpu load indicator (on -vv) (#555) -api : LZ4_decompress_safe_partial() now decodes exactly the nb of bytes requested (feature request #566) -build : added Haiku target, by @fbrosson, and MidnightBSD, by @laffer1 -doc : updated documentation regarding dictionary compression - -v1.8.2 -perf: *much* faster dictionary compression on small files, by @felixhandte -perf: improved decompression speed and binary size, by Alexey Tourbin (@svpv) -perf: slightly faster HC compression and decompression speed -perf: very small compression ratio improvement -fix : compression compatible with low memory addresses (< 0xFFFF) -fix : decompression segfault when provided with NULL input, by @terrelln -cli : new command --favor-decSpeed -cli : benchmark mode more accurate for small inputs -fullbench : can bench _destSize() variants, by @felixhandte -doc : clarified block format parsing restrictions, by Alexey Tourbin (@svpv) - -v1.8.1 -perf : faster and stronger ultra modes (levels 10+) -perf : slightly faster compression and decompression speed -perf : fix bad degenerative case, reported by @c-morgenstern -fix : decompression failed when using a combination of extDict + low memory address (#397), reported and fixed by Julian Scheid (@jscheid) -cli : support for dictionary compression (`-D`), by Felix Handte @felixhandte -cli : fix : `lz4 -d --rm` preserves timestamp (#441) -cli : fix : do not modify /dev/null permission as root, by @aliceatlas -api : `_destSize()` variant supported for all compression levels -build : `make` and `make test` compatible with `-jX`, reported by @mwgamera -build : can control LZ4LIB_VISIBILITY macro, by @mikir -install: fix man page directory (#387), reported by Stuart Cardall (@itoffshore) - -v1.8.0 -cli : fix : do not modify /dev/null permissions, reported by @Maokaman1 -cli : added GNU separator -- specifying that all following arguments are files -API : added LZ4_compress_HC_destSize(), by Oleg (@remittor) -API : added LZ4F_resetDecompressionContext() -API : lz4frame : negative compression levels trigger fast acceleration, request by Lawrence Chan -API : lz4frame : can control block checksum and dictionary ID -API : fix : expose obsolete decoding functions, reported by Chen Yufei -API : experimental : lz4frame_static : new dictionary compression API -build : fix : static lib installation, by Ido Rosen -build : dragonFlyBSD, OpenBSD, NetBSD supported -build : LZ4_MEMORY_USAGE can be modified at compile time, through external define -doc : Updated LZ4 Frame format to v1.6.0, restoring Dictionary-ID field -doc : lz4 api manual, by Przemyslaw Skibinski - -v1.7.5 -lz4hc : new high compression mode : levels 10-12 compress more and slower, by Przemyslaw Skibinski -lz4cat : fix : works with relative path (#284) and stdin (#285) (reported by @beiDei8z) -cli : fix minor notification when using -r recursive mode -API : lz4frame : LZ4F_frameBound(0) gives upper bound of *flush() and *End() operations (#290, #280) -doc : markdown version of man page, by Takayuki Matsuoka (#279) -build : Makefile : fix make -jX lib+exe concurrency (#277) -build : cmake : improvements by MichaÅ‚ Górny (#296) - -v1.7.4.2 -fix : Makefile : release build compatible with PIE and customized compilation directives provided through environment variables (#274, reported by Antoine Martin) - -v1.7.4 -Improved : much better speed in -mx32 mode -cli : fix : Large file support in 32-bits mode on Mac OS-X -fix : compilation on gcc 4.4 (#272), reported by Antoine Martin - -v1.7.3 -Changed : moved to versioning; package, cli and library have same version number -Improved: Small decompression speed boost -Improved: Small compression speed improvement on 64-bits systems -Improved: Small compression ratio and speed improvement on small files -Improved: Significant speed boost on ARMv6 and ARMv7 -Fix : better ratio on 64-bits big-endian targets -Improved cmake build script, by Evan Nemerson -New liblz4-dll project, by Przemyslaw Skibinki -Makefile: Generates object files (*.o) for faster (re)compilation on low power systems -cli : new : --rm and --help commands -cli : new : preserved file attributes, by Przemyslaw Skibinki -cli : fix : crash on some invalid inputs -cli : fix : -t correctly validates lz4-compressed files, by Nick Terrell -cli : fix : detects and reports fread() errors, thanks to Hiroshi Fujishima report #243 -cli : bench : new : -r recursive mode -lz4cat : can cat multiple files in a single command line (#184) -Added : doc/lz4_manual.html, by Przemyslaw Skibinski -Added : dictionary compression and frame decompression examples, by Nick Terrell -Added : Debianization, by Evgeniy Polyakov - -r131 -New : Dos/DJGPP target, thanks to Louis Santillan (#114) -Added : Example using lz4frame library, by Zbigniew JÄ™drzejewski-Szmek (#118) -Changed: xxhash symbols are modified (namespace emulation) within liblz4 - -r130: -Fixed : incompatibility sparse mode vs console, reported by Yongwoon Cho (#105) -Fixed : LZ4IO exits too early when frame crc not present, reported by Yongwoon Cho (#106) -Fixed : incompatibility sparse mode vs append mode, reported by Takayuki Matsuoka (#110) -Performance fix : big compression speed boost for clang (+30%) -New : cross-version test, by Takayuki Matsuoka - -r129: -Added : LZ4_compress_fast(), LZ4_compress_fast_continue() -Added : LZ4_compress_destSize() -Changed: New lz4 and lz4hc compression API. Previous function prototypes still supported. -Changed: Sparse file support enabled by default -New : LZ4 CLI improved performance compressing/decompressing multiple files (#86, kind contribution from Kyle J. Harper & Takayuki Matsuoka) -Fixed : GCC 4.9+ optimization bug - Reported by Markus Trippelsdorf, Greg Slazinski & Evan Nemerson -Changed: Enums converted to LZ4F_ namespace convention - by Takayuki Matsuoka -Added : AppVeyor CI environment, for Visual tests - Suggested by Takayuki Matsuoka -Modified:Obsolete functions generate warnings - Suggested by Evan Nemerson, contributed by Takayuki Matsuoka -Fixed : Bug #75 (unfinished stream), reported by Yongwoon Cho -Updated: Documentation converted to MarkDown format - -r128: -New : lz4cli sparse file support (Requested by Neil Wilson, and contributed by Takayuki Matsuoka) -New : command -m, to compress multiple files in a single command (suggested by Kyle J. Harper) -Fixed : Restored lz4hc compression ratio (slightly lower since r124) -New : lz4 cli supports long commands (suggested by Takayuki Matsuoka) -New : lz4frame & lz4cli frame content size support -New : lz4frame supports skippable frames, as requested by Sergey Cherepanov -Changed: Default "make install" directory is /usr/local, as notified by Ron Johnson -New : lz4 cli supports "pass-through" mode, requested by Neil Wilson -New : datagen can generate sparse files -New : scan-build tests, thanks to kind help by Takayuki Matsuoka -New : g++ compatibility tests -New : arm cross-compilation test, thanks to kind help by Takayuki Matsuoka -Fixed : Fuzzer + frametest compatibility with NetBSD (issue #48, reported by Thomas Klausner) -Added : Visual project directory -Updated: Man page & Specification - -r127: -N/A : added a file on SVN - -r126: -New : lz4frame API is now integrated into liblz4 -Fixed : GCC 4.9 bug on highest performance settings, reported by Greg Slazinski -Fixed : bug within LZ4 HC streaming mode, reported by James Boyle -Fixed : older compiler don't like nameless unions, reported by Cheyi Lin -Changed : lz4 is C90 compatible -Changed : added -pedantic option, fixed a few mminor warnings - -r125: -Changed : endian and alignment code -Changed : directory structure : new "lib" directory -Updated : lz4io, now uses lz4frame -Improved: slightly improved decoding speed -Fixed : LZ4_compress_limitedOutput(); Special thanks to Christopher Speller ! -Fixed : some alignment warnings under clang -Fixed : deprecated function LZ4_slideInputBufferHC() - -r124: -New : LZ4 HC streaming mode -Fixed : LZ4F_compressBound() using null preferencesPtr -Updated : xxHash to r38 -Updated library number, to 1.4.0 - -r123: -Added : experimental lz4frame API, thanks to Takayuki Matsuoka and Christopher Jackson for testings -Fix : s390x support, thanks to Nobuhiro Iwamatsu -Fix : test mode (-t) no longer requires confirmation, thanks to Thary Nguyen - -r122: -Fix : AIX & AIX64 support (SamG) -Fix : mips 64-bits support (lew van) -Added : Examples directory, using code examples from Takayuki Matsuoka -Updated : Framing specification, to v1.4.1 -Updated : xxHash, to r36 - -r121: -Added : Makefile : install for kFreeBSD and Hurd (Nobuhiro Iwamatsu) -Fix : Makefile : install for OS-X and BSD, thanks to Takayuki Matsuoka - -r120: -Modified : Streaming API, using strong types -Added : LZ4_versionNumber(), thanks to Takayuki Matsuoka -Fix : OS-X : library install name, thanks to Clemens Lang -Updated : Makefile : synchronize library version number with lz4.h, thanks to Takayuki Matsuoka -Updated : Makefile : stricter compilation flags -Added : pkg-config, thanks to Zbigniew JÄ™drzejewski-Szmek (issue 135) -Makefile : lz4-test only test native binaries, as suggested by MichaÅ‚ Górny (issue 136) -Updated : xxHash to r35 - -r119: -Fix : Issue 134 : extended malicious address space overflow in 32-bits mode for some specific configurations - -r118: -New : LZ4 Streaming API (Fast version), special thanks to Takayuki Matsuoka -New : datagen : parametrable synthetic data generator for tests -Improved : fuzzer, support more test cases, more parameters, ability to jump to specific test -fix : support ppc64le platform (issue 131) -fix : Issue 52 (malicious address space overflow in 32-bits mode when using large custom format) -fix : Makefile : minor issue 130 : header files permissions - -r117: -Added : man pages for lz4c and lz4cat -Added : automated tests on Travis, thanks to Takayuki Matsuoka ! -fix : block-dependency command line (issue 127) -fix : lz4fullbench (issue 128) - -r116: -hotfix (issue 124 & 125) - -r115: -Added : lz4cat utility, installed on POSX systems (issue 118) -OS-X compatible compilation of dynamic library (issue 115) - -r114: -Makefile : library correctly compiled with -O3 switch (issue 114) -Makefile : library compilation compatible with clang -Makefile : library is versioned and linked (issue 119) -lz4.h : no more static inline prototypes (issue 116) -man : improved header/footer (issue 111) -Makefile : Use system default $(CC) & $(MAKE) variables (issue 112) -xxhash : updated to r34 - -r113: -Large decompression speed improvement for GCC 32-bits. Thanks to Valery Croizier ! -LZ4HC : Compression Level is now a programmable parameter (CLI from 4 to 9) -Separated IO routines from command line (lz4io.c) -Version number into lz4.h (suggested by Francesc Alted) - -r112: -quickfix - -r111 : -Makefile : added capability to install libraries -Modified Directory tree, to better separate libraries from programs. - -r110 : -lz4 & lz4hc : added capability to allocate state & stream state with custom allocator (issue 99) -fuzzer & fullbench : updated to test new functions -man : documented -l command (Legacy format, for Linux kernel compression) (issue 102) -cmake : improved version by Mika Attila, building programs and libraries (issue 100) -xxHash : updated to r33 -Makefile : clean also delete local package .tar.gz - -r109 : -lz4.c : corrected issue 98 (LZ4_compress_limitedOutput()) -Makefile : can specify version number from makefile - -r108 : -lz4.c : corrected compression efficiency issue 97 in 64-bits chained mode (-BD) for streams > 4 GB (thanks Roman Strashkin for reporting) - -r107 : -Makefile : support DESTDIR for staged installs. Thanks Jorge Aparicio. -Makefile : make install installs both lz4 and lz4c (Jorge Aparicio) -Makefile : removed -Wno-implicit-declaration compilation switch -lz4cli.c : include for isatty() (Luca Barbato) -lz4.h : introduced LZ4_MAX_INPUT_SIZE constant (Shay Green) -lz4.h : LZ4_compressBound() : unified macro and inline definitions (Shay Green) -lz4.h : LZ4_decompressSafe_partial() : clarify comments (Shay Green) -lz4.c : LZ4_compress() verify input size condition (Shay Green) -bench.c : corrected a bug in free memory size evaluation -cmake : install into bin/ directory (Richard Yao) -cmake : check for just C compiler (Elan Ruusamae) - -r106 : -Makefile : make dist modify text files in the package to respect Unix EoL convention -lz4cli.c : corrected small display bug in HC mode - -r105 : -Makefile : New install script and man page, contributed by Prasad Pandit -lz4cli.c : Minor modifications, for easier extensibility -COPYING : added license file -LZ4_Streaming_Format.odt : modified file name to remove white space characters -Makefile : .exe suffix now properly added only for Windows target diff --git a/ta6ob/lz4/README.md b/ta6ob/lz4/README.md deleted file mode 100644 index bdb028c..0000000 --- a/ta6ob/lz4/README.md +++ /dev/null @@ -1,120 +0,0 @@ -LZ4 - Extremely fast compression -================================ - -LZ4 is lossless compression algorithm, -providing compression speed > 500 MB/s per core, -scalable with multi-cores CPU. -It features an extremely fast decoder, -with speed in multiple GB/s per core, -typically reaching RAM speed limits on multi-core systems. - -Speed can be tuned dynamically, selecting an "acceleration" factor -which trades compression ratio for faster speed. -On the other end, a high compression derivative, LZ4_HC, is also provided, -trading CPU time for improved compression ratio. -All versions feature the same decompression speed. - -LZ4 is also compatible with [dictionary compression](https://github.com/facebook/zstd#the-case-for-small-data-compression), -both at [API](https://github.com/lz4/lz4/blob/v1.8.3/lib/lz4frame.h#L481) and [CLI](https://github.com/lz4/lz4/blob/v1.8.3/programs/lz4.1.md#operation-modifiers) levels. -It can ingest any input file as dictionary, though only the final 64KB are used. -This capability can be combined with the [Zstandard Dictionary Builder](https://github.com/facebook/zstd/blob/v1.3.5/programs/zstd.1.md#dictionary-builder), -in order to drastically improve compression performance on small files. - - -LZ4 library is provided as open-source software using BSD 2-Clause license. - - -|Branch |Status | -|------------|---------| -|dev | [![Build Status][travisDevBadge]][travisLink] [![Build status][AppveyorDevBadge]][AppveyorLink] | - -[travisDevBadge]: https://travis-ci.org/lz4/lz4.svg?branch=dev "Continuous Integration test suite" -[travisLink]: https://travis-ci.org/lz4/lz4 -[AppveyorDevBadge]: https://ci.appveyor.com/api/projects/status/github/lz4/lz4?branch=dev&svg=true "Windows test suite" -[AppveyorLink]: https://ci.appveyor.com/project/YannCollet/lz4-1lndh - - -Benchmarks -------------------------- - -The benchmark uses [lzbench], from @inikep -compiled with GCC v8.2.0 on Linux 64-bits (Ubuntu 4.18.0-17). -The reference system uses a Core i7-9700K CPU @ 4.9GHz (w/ turbo boost). -Benchmark evaluates the compression of reference [Silesia Corpus] -in single-thread mode. - -[lzbench]: https://github.com/inikep/lzbench -[Silesia Corpus]: http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia - -| Compressor | Ratio | Compression | Decompression | -| ---------- | ----- | ----------- | ------------- | -| memcpy | 1.000 | 13700 MB/s | 13700 MB/s | -|**LZ4 default (v1.9.0)** |**2.101**| **780 MB/s**| **4970 MB/s** | -| LZO 2.09 | 2.108 | 670 MB/s | 860 MB/s | -| QuickLZ 1.5.0 | 2.238 | 575 MB/s | 780 MB/s | -| Snappy 1.1.4 | 2.091 | 565 MB/s | 1950 MB/s | -| [Zstandard] 1.4.0 -1 | 2.883 | 515 MB/s | 1380 MB/s | -| LZF v3.6 | 2.073 | 415 MB/s | 910 MB/s | -| [zlib] deflate 1.2.11 -1| 2.730 | 100 MB/s | 415 MB/s | -|**LZ4 HC -9 (v1.9.0)** |**2.721**| 41 MB/s | **4900 MB/s** | -| [zlib] deflate 1.2.11 -6| 3.099 | 36 MB/s | 445 MB/s | - -[zlib]: http://www.zlib.net/ -[Zstandard]: http://www.zstd.net/ - -LZ4 is also compatible and optimized for x32 mode, -for which it provides additional speed performance. - - -Installation -------------------------- - -``` -make -make install # this command may require root permissions -``` - -LZ4's `Makefile` supports standard [Makefile conventions], -including [staged installs], [redirection], or [command redefinition]. -It is compatible with parallel builds (`-j#`). - -[Makefile conventions]: https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html -[staged installs]: https://www.gnu.org/prep/standards/html_node/DESTDIR.html -[redirection]: https://www.gnu.org/prep/standards/html_node/Directory-Variables.html -[command redefinition]: https://www.gnu.org/prep/standards/html_node/Utilities-in-Makefiles.html - -Building LZ4 - Using vcpkg - -You can download and install LZ4 using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: - - git clone https://github.com/Microsoft/vcpkg.git - cd vcpkg - ./bootstrap-vcpkg.sh - ./vcpkg integrate install - vcpkg install lz4 - -The LZ4 port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. - -Documentation -------------------------- - -The raw LZ4 block compression format is detailed within [lz4_Block_format]. - -Arbitrarily long files or data streams are compressed using multiple blocks, -for streaming requirements. These blocks are organized into a frame, -defined into [lz4_Frame_format]. -Interoperable versions of LZ4 must also respect the frame format. - -[lz4_Block_format]: doc/lz4_Block_format.md -[lz4_Frame_format]: doc/lz4_Frame_format.md - - -Other source versions -------------------------- - -Beyond the C reference source, -many contributors have created versions of lz4 in multiple languages -(Java, C#, Python, Perl, Ruby, etc.). -A list of known source ports is maintained on the [LZ4 Homepage]. - -[LZ4 Homepage]: http://www.lz4.org diff --git a/ta6ob/lz4/appveyor.yml b/ta6ob/lz4/appveyor.yml deleted file mode 100644 index b4c27ef..0000000 --- a/ta6ob/lz4/appveyor.yml +++ /dev/null @@ -1,147 +0,0 @@ -version: 1.0.{build} -environment: - matrix: - - COMPILER: "gcc" - PLATFORM: "mingw64" - - COMPILER: "gcc" - PLATFORM: "mingw32" - - COMPILER: "visual" - CONFIGURATION: "Debug" - PLATFORM: "x64" - - COMPILER: "visual" - CONFIGURATION: "Debug" - PLATFORM: "Win32" - - COMPILER: "visual" - CONFIGURATION: "Release" - PLATFORM: "x64" - - COMPILER: "visual" - CONFIGURATION: "Release" - PLATFORM: "Win32" - - COMPILER: "gcc" - PLATFORM: "clang" - -install: - - ECHO Installing %COMPILER% %PLATFORM% %CONFIGURATION% - - MKDIR bin - - if [%COMPILER%]==[gcc] SET PATH_ORIGINAL=%PATH% - - if [%COMPILER%]==[gcc] ( - SET "PATH_MINGW32=c:\MinGW\bin;c:\MinGW\usr\bin" && - SET "PATH_MINGW64=c:\msys64\mingw64\bin;c:\msys64\usr\bin" && - COPY C:\MinGW\bin\mingw32-make.exe C:\MinGW\bin\make.exe && - COPY C:\MinGW\bin\gcc.exe C:\MinGW\bin\cc.exe - ) else ( - IF [%PLATFORM%]==[x64] (SET ADDITIONALPARAM=/p:LibraryPath="C:\Program Files\Microsoft SDKs\Windows\v7.1\lib\x64;c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\amd64;C:\Program Files (x86)\Microsoft Visual Studio 10.0\;C:\Program Files (x86)\Microsoft Visual Studio 10.0\lib\amd64;") - ) - -build_script: - - if [%PLATFORM%]==[mingw32] SET PATH=%PATH_MINGW32%;%PATH_ORIGINAL% - - if [%PLATFORM%]==[mingw64] SET PATH=%PATH_MINGW64%;%PATH_ORIGINAL% - - if [%PLATFORM%]==[clang] SET PATH=%PATH_MINGW64%;%PATH_ORIGINAL% - - ECHO *** && - ECHO Building %COMPILER% %PLATFORM% %CONFIGURATION% && - ECHO *** - - if [%PLATFORM%]==[clang] (clang -v) - - if [%COMPILER%]==[gcc] (gcc -v) - - if [%COMPILER%]==[gcc] ( - echo ----- && - make -v && - echo ----- && - if not [%PLATFORM%]==[clang] ( - make -C programs lz4 && - make -C tests fullbench && - make -C tests fuzzer && - make -C lib lib V=1 - ) ELSE ( - make -C programs lz4 CC=clang MOREFLAGS="--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion" && - make -C tests fullbench CC=clang MOREFLAGS="--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion" && - make -C tests fuzzer CC=clang MOREFLAGS="--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion" && - make -C lib lib CC=clang MOREFLAGS="--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion" - ) - ) - - if [%COMPILER%]==[gcc] if not [%PLATFORM%]==[clang] ( - MKDIR bin\dll bin\static bin\example bin\include && - COPY tests\fullbench.c bin\example\ && - COPY lib\xxhash.c bin\example\ && - COPY lib\xxhash.h bin\example\ && - COPY lib\lz4.h bin\include\ && - COPY lib\lz4hc.h bin\include\ && - COPY lib\lz4frame.h bin\include\ && - COPY lib\liblz4.a bin\static\liblz4_static.lib && - COPY lib\dll\* bin\dll\ && - COPY lib\dll\example\Makefile bin\example\ && - COPY lib\dll\example\fullbench-dll.* bin\example\ && - COPY lib\dll\example\README.md bin\ && - COPY programs\lz4.exe bin\lz4.exe - ) - - if [%COMPILER%]==[gcc] if [%PLATFORM%]==[mingw64] ( - 7z.exe a -bb1 bin\lz4_x64.zip NEWS .\bin\lz4.exe .\bin\README.md .\bin\example .\bin\dll .\bin\static .\bin\include && - appveyor PushArtifact bin\lz4_x64.zip - ) - - if [%COMPILER%]==[gcc] if [%PLATFORM%]==[mingw32] ( - 7z.exe a -bb1 bin\lz4_x86.zip NEWS .\bin\lz4.exe .\bin\README.md .\bin\example .\bin\dll .\bin\static .\bin\include && - appveyor PushArtifact bin\lz4_x86.zip - ) - - if [%COMPILER%]==[gcc] (COPY tests\*.exe programs\) - - if [%COMPILER%]==[visual] ( - ECHO *** && - ECHO *** Building Visual Studio 2010 %PLATFORM%\%CONFIGURATION% && - ECHO *** && - msbuild "build\VS2010\lz4.sln" %ADDITIONALPARAM% /m /verbosity:minimal /property:PlatformToolset=v100 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /p:EnableWholeProgramOptimization=true /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" && - ECHO *** && - ECHO *** Building Visual Studio 2012 %PLATFORM%\%CONFIGURATION% && - ECHO *** && - msbuild "build\VS2010\lz4.sln" /m /verbosity:minimal /property:PlatformToolset=v110 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" && - ECHO *** && - ECHO *** Building Visual Studio 2013 %PLATFORM%\%CONFIGURATION% && - ECHO *** && - msbuild "build\VS2010\lz4.sln" /m /verbosity:minimal /property:PlatformToolset=v120 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" && - ECHO *** && - ECHO *** Building Visual Studio 2015 %PLATFORM%\%CONFIGURATION% && - ECHO *** && - msbuild "build\VS2010\lz4.sln" /m /verbosity:minimal /property:PlatformToolset=v140 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" && - COPY build\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe programs\ - ) - -test_script: - - ECHO *** && - ECHO Testing %COMPILER% %PLATFORM% %CONFIGURATION% && - ECHO *** - - if not [%COMPILER%]==[unknown] ( - CD programs && - lz4 -h && - lz4 -i1b lz4.exe && - lz4 -i1b5 lz4.exe && - lz4 -i1b10 lz4.exe && - lz4 -i1b15 lz4.exe && - echo ------- lz4 tested ------- && - fullbench.exe -i1 fullbench.exe && - echo trying to launch fuzzer.exe && - fuzzer.exe -v -T30s - ) - -artifacts: - - path: bin\lz4_x64.zip - - path: bin\lz4_x86.zip - -deploy: -- provider: GitHub - artifact: bin\lz4_x64.zip - auth_token: - secure: w6UJaGie0qbZvffr/fqyhO/Vj8rMiQWnv9a8qm3gxfngdHDTMT42wYupqJpIExId - force_update: true - prerelease: true - on: - COMPILER: gcc - PLATFORM: "mingw64" - appveyor_repo_tag: true - -- provider: GitHub - artifact: bin\lz4_x86.zip - auth_token: - secure: w6UJaGie0qbZvffr/fqyhO/Vj8rMiQWnv9a8qm3gxfngdHDTMT42wYupqJpIExId - force_update: true - prerelease: true - on: - COMPILER: gcc - PLATFORM: "mingw32" - appveyor_repo_tag: true diff --git a/ta6ob/lz4/build/.gitignore b/ta6ob/lz4/build/.gitignore deleted file mode 100644 index 69e1111..0000000 --- a/ta6ob/lz4/build/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -# Visual C++ -.vs/ -*Copy -*.db -*.opensdf -*.sdf -*.suo -*.user -ver*/ -VS2010/bin/ -VS2017/bin/ -ipch - -# Fixup for lz4 project directories -!VS2010/lz4 -!VS2017/lz4 diff --git a/ta6ob/lz4/build/README.md b/ta6ob/lz4/build/README.md deleted file mode 100644 index d416aeb..0000000 --- a/ta6ob/lz4/build/README.md +++ /dev/null @@ -1,55 +0,0 @@ -Projects for various integrated development environments (IDE) -============================================================== - -#### Included projects - -The following projects are included with the lz4 distribution: -- `cmake` - CMake project -- `VS2010` - Visual Studio 2010 project (which also works well with Visual Studio 2012, 2013, 2015) -- `VS2017` - Visual Studio 2017 project - - -#### How to compile lz4 with Visual Studio - -1. Install Visual Studio e.g. VS 2015 Community Edition (it's free). -2. Download the latest version of lz4 from https://github.com/lz4/lz4/releases -3. Decompress ZIP archive. -4. Go to decompressed directory then to `build` then `VS2010` and open `lz4.sln` -5. Visual Studio will ask about converting VS2010 project to VS2015 and you should agree. -6. Change `Debug` to `Release` and if you have 64-bit Windows change also `Win32` to `x64`. -7. Press F7 on keyboard or select `BUILD` from the menu bar and choose `Build Solution`. -8. If compilation will be fine a compiled executable will be in `build\VS2010\bin\x64_Release\lz4.exe` - - -#### Projects available within lz4.sln - -The Visual Studio solution file `lz4.sln` contains many projects that will be compiled to the -`build\VS2010\bin\$(Platform)_$(Configuration)` directory. For example `lz4` set to `x64` and -`Release` will be compiled to `build\VS2010\bin\x64_Release\lz4.exe`. The solution file contains the -following projects: - -- `lz4` : Command Line Utility, supporting gzip-like arguments -- `datagen` : Synthetic and parametrable data generator, for tests -- `frametest` : Test tool that checks lz4frame integrity on target platform -- `fullbench` : Precisely measure speed for each lz4 inner functions -- `fuzzer` : Test tool, to check lz4 integrity on target platform -- `liblz4` : A static LZ4 library compiled to `liblz4_static.lib` -- `liblz4-dll` : A dynamic LZ4 library (DLL) compiled to `liblz4.dll` with the import library `liblz4.lib` -- `fullbench-dll` : The fullbench program compiled with the import library; the executable requires LZ4 DLL - - -#### Using LZ4 DLL with Microsoft Visual C++ project - -The header files `lib\lz4.h`, `lib\lz4hc.h`, `lib\lz4frame.h` and the import library -`build\VS2010\bin\$(Platform)_$(Configuration)\liblz4.lib` are required to -compile a project using Visual C++. - -1. The path to header files should be added to `Additional Include Directories` that can - be found in Project Properties of Visual Studio IDE in the `C/C++` Property Pages on the `General` page. -2. The import library has to be added to `Additional Dependencies` that can - be found in Project Properties in the `Linker` Property Pages on the `Input` page. - If one will provide only the name `liblz4.lib` without a full path to the library - then the directory has to be added to `Linker\General\Additional Library Directories`. - -The compiled executable will require LZ4 DLL which is available at -`build\VS2010\bin\$(Platform)_$(Configuration)\liblz4.dll`. diff --git a/ta6ob/lz4/build/VS2010/datagen/datagen.vcxproj b/ta6ob/lz4/build/VS2010/datagen/datagen.vcxproj deleted file mode 100644 index e24f961..0000000 --- a/ta6ob/lz4/build/VS2010/datagen/datagen.vcxproj +++ /dev/null @@ -1,169 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {D745AE2F-596A-403A-9B91-81A8C6779243} - Win32Proj - datagen - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - Unicode - true - - - Application - false - Unicode - true - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - diff --git a/ta6ob/lz4/build/VS2010/frametest/frametest.vcxproj b/ta6ob/lz4/build/VS2010/frametest/frametest.vcxproj deleted file mode 100644 index 3196768..0000000 --- a/ta6ob/lz4/build/VS2010/frametest/frametest.vcxproj +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7} - Win32Proj - frametest - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - Unicode - true - - - Application - false - Unicode - true - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/ta6ob/lz4/build/VS2010/fullbench-dll/fullbench-dll.vcxproj b/ta6ob/lz4/build/VS2010/fullbench-dll/fullbench-dll.vcxproj deleted file mode 100644 index 8f503f5..0000000 --- a/ta6ob/lz4/build/VS2010/fullbench-dll/fullbench-dll.vcxproj +++ /dev/null @@ -1,180 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {13992FD2-077E-4954-B065-A428198201A9} - Win32Proj - fullbench-dll - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - Unicode - true - - - Application - false - Unicode - true - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/VS2010/fullbench/fullbench.vcxproj b/ta6ob/lz4/build/VS2010/fullbench/fullbench.vcxproj deleted file mode 100644 index aa67431..0000000 --- a/ta6ob/lz4/build/VS2010/fullbench/fullbench.vcxproj +++ /dev/null @@ -1,176 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E} - Win32Proj - fullbench - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - Unicode - true - - - Application - false - Unicode - true - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/ta6ob/lz4/build/VS2010/fuzzer/fuzzer.vcxproj b/ta6ob/lz4/build/VS2010/fuzzer/fuzzer.vcxproj deleted file mode 100644 index 21cbf56..0000000 --- a/ta6ob/lz4/build/VS2010/fuzzer/fuzzer.vcxproj +++ /dev/null @@ -1,173 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {18B9F1A7-9C66-4352-898B-30804DADE0FD} - Win32Proj - fuzzer - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - Unicode - true - - - Application - false - Unicode - true - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - - - - - diff --git a/ta6ob/lz4/build/VS2010/liblz4-dll/liblz4-dll.rc b/ta6ob/lz4/build/VS2010/liblz4-dll/liblz4-dll.rc deleted file mode 100644 index b1871fe..0000000 --- a/ta6ob/lz4/build/VS2010/liblz4-dll/liblz4-dll.rc +++ /dev/null @@ -1,51 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// - -#include "lz4.h" /* LZ4_VERSION_STRING */ -#define APSTUDIO_READONLY_SYMBOLS -#include "verrsrc.h" -#undef APSTUDIO_READONLY_SYMBOLS - - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE 9, 1 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION LZ4_VERSION_MAJOR,LZ4_VERSION_MINOR,LZ4_VERSION_RELEASE,0 - PRODUCTVERSION LZ4_VERSION_MAJOR,LZ4_VERSION_MINOR,LZ4_VERSION_RELEASE,0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "Yann Collet" - VALUE "FileDescription", "Extremely fast compression" - VALUE "FileVersion", LZ4_VERSION_STRING - VALUE "InternalName", "lz4.dll" - VALUE "LegalCopyright", "Copyright (C) 2013-2016, Yann Collet" - VALUE "OriginalFilename", "lz4.dll" - VALUE "ProductName", "LZ4" - VALUE "ProductVersion", LZ4_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1200 - END -END - -#endif diff --git a/ta6ob/lz4/build/VS2010/liblz4-dll/liblz4-dll.vcxproj b/ta6ob/lz4/build/VS2010/liblz4-dll/liblz4-dll.vcxproj deleted file mode 100644 index 56ec3b9..0000000 --- a/ta6ob/lz4/build/VS2010/liblz4-dll/liblz4-dll.vcxproj +++ /dev/null @@ -1,179 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {9800039D-4AAA-43A4-BB78-FEF6F4836927} - Win32Proj - liblz4-dll - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - liblz4-dll - - - - DynamicLibrary - true - Unicode - - - DynamicLibrary - true - Unicode - - - DynamicLibrary - false - Unicode - true - - - DynamicLibrary - false - Unicode - true - - - - - - - - - - - - - - - - - - - true - liblz4 - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - liblz4 - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - liblz4 - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - liblz4 - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - true - true - true - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/VS2010/liblz4/liblz4.vcxproj b/ta6ob/lz4/build/VS2010/liblz4/liblz4.vcxproj deleted file mode 100644 index 61ea159..0000000 --- a/ta6ob/lz4/build/VS2010/liblz4/liblz4.vcxproj +++ /dev/null @@ -1,175 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476} - Win32Proj - liblz4 - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - StaticLibrary - true - Unicode - - - StaticLibrary - true - Unicode - - - StaticLibrary - false - Unicode - true - - - StaticLibrary - false - Unicode - true - - - - - - - - - - - - - - - - - - - true - liblz4_static - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - liblz4_static - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - liblz4_static - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - liblz4_static - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - true - true - true - - - - - - - - - - - - - - - - - - - diff --git a/ta6ob/lz4/build/VS2010/lz4.sln b/ta6ob/lz4/build/VS2010/lz4.sln deleted file mode 100644 index 78f223b..0000000 --- a/ta6ob/lz4/build/VS2010/lz4.sln +++ /dev/null @@ -1,98 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2012 for Windows Desktop -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lz4", "lz4\lz4.vcxproj", "{E30329AC-0057-4FE0-8FDA-7F650D398C4C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblz4-dll", "liblz4-dll\liblz4-dll.vcxproj", "{9800039D-4AAA-43A4-BB78-FEF6F4836927}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblz4", "liblz4\liblz4.vcxproj", "{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fuzzer", "fuzzer\fuzzer.vcxproj", "{18B9F1A7-9C66-4352-898B-30804DADE0FD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench", "fullbench\fullbench.vcxproj", "{6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "frametest", "frametest\frametest.vcxproj", "{39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "datagen", "datagen\datagen.vcxproj", "{D745AE2F-596A-403A-9B91-81A8C6779243}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench-dll", "fullbench-dll\fullbench-dll.vcxproj", "{13992FD2-077E-4954-B065-A428198201A9}" - ProjectSection(ProjectDependencies) = postProject - {9800039D-4AAA-43A4-BB78-FEF6F4836927} = {9800039D-4AAA-43A4-BB78-FEF6F4836927} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E30329AC-0057-4FE0-8FDA-7F650D398C4C}.Debug|Win32.ActiveCfg = Debug|Win32 - {E30329AC-0057-4FE0-8FDA-7F650D398C4C}.Debug|Win32.Build.0 = Debug|Win32 - {E30329AC-0057-4FE0-8FDA-7F650D398C4C}.Debug|x64.ActiveCfg = Debug|x64 - {E30329AC-0057-4FE0-8FDA-7F650D398C4C}.Debug|x64.Build.0 = Debug|x64 - {E30329AC-0057-4FE0-8FDA-7F650D398C4C}.Release|Win32.ActiveCfg = Release|Win32 - {E30329AC-0057-4FE0-8FDA-7F650D398C4C}.Release|Win32.Build.0 = Release|Win32 - {E30329AC-0057-4FE0-8FDA-7F650D398C4C}.Release|x64.ActiveCfg = Release|x64 - {E30329AC-0057-4FE0-8FDA-7F650D398C4C}.Release|x64.Build.0 = Release|x64 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Debug|Win32.ActiveCfg = Debug|Win32 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Debug|Win32.Build.0 = Debug|Win32 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Debug|x64.ActiveCfg = Debug|x64 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Debug|x64.Build.0 = Debug|x64 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Release|Win32.ActiveCfg = Release|Win32 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Release|Win32.Build.0 = Release|Win32 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Release|x64.ActiveCfg = Release|x64 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Release|x64.Build.0 = Release|x64 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|Win32.ActiveCfg = Debug|Win32 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|Win32.Build.0 = Debug|Win32 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|x64.ActiveCfg = Debug|x64 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|x64.Build.0 = Debug|x64 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|Win32.ActiveCfg = Release|Win32 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|Win32.Build.0 = Release|Win32 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|x64.ActiveCfg = Release|x64 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|x64.Build.0 = Release|x64 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Debug|Win32.ActiveCfg = Debug|Win32 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Debug|Win32.Build.0 = Debug|Win32 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Debug|x64.ActiveCfg = Debug|x64 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Debug|x64.Build.0 = Debug|x64 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Release|Win32.ActiveCfg = Release|Win32 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Release|Win32.Build.0 = Release|Win32 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Release|x64.ActiveCfg = Release|x64 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Release|x64.Build.0 = Release|x64 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Debug|Win32.ActiveCfg = Debug|Win32 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Debug|Win32.Build.0 = Debug|Win32 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Debug|x64.ActiveCfg = Debug|x64 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Debug|x64.Build.0 = Debug|x64 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Release|Win32.ActiveCfg = Release|Win32 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Release|Win32.Build.0 = Release|Win32 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Release|x64.ActiveCfg = Release|x64 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Release|x64.Build.0 = Release|x64 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Debug|Win32.ActiveCfg = Debug|Win32 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Debug|Win32.Build.0 = Debug|Win32 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Debug|x64.ActiveCfg = Debug|x64 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Debug|x64.Build.0 = Debug|x64 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Release|Win32.ActiveCfg = Release|Win32 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Release|Win32.Build.0 = Release|Win32 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Release|x64.ActiveCfg = Release|x64 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Release|x64.Build.0 = Release|x64 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Debug|Win32.ActiveCfg = Debug|Win32 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Debug|Win32.Build.0 = Debug|Win32 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Debug|x64.ActiveCfg = Debug|x64 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Debug|x64.Build.0 = Debug|x64 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Release|Win32.ActiveCfg = Release|Win32 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Release|Win32.Build.0 = Release|Win32 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Release|x64.ActiveCfg = Release|x64 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Release|x64.Build.0 = Release|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|Win32.ActiveCfg = Debug|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|Win32.Build.0 = Debug|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|x64.ActiveCfg = Debug|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|x64.Build.0 = Debug|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Release|Win32.ActiveCfg = Release|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Release|Win32.Build.0 = Release|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Release|x64.ActiveCfg = Release|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/ta6ob/lz4/build/VS2010/lz4/lz4.rc b/ta6ob/lz4/build/VS2010/lz4/lz4.rc deleted file mode 100644 index c593edf..0000000 --- a/ta6ob/lz4/build/VS2010/lz4/lz4.rc +++ /dev/null @@ -1,51 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// - -#include "lz4.h" /* LZ4_VERSION_STRING */ -#define APSTUDIO_READONLY_SYMBOLS -#include "verrsrc.h" -#undef APSTUDIO_READONLY_SYMBOLS - - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE 9, 1 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION LZ4_VERSION_MAJOR,LZ4_VERSION_MINOR,LZ4_VERSION_RELEASE,0 - PRODUCTVERSION LZ4_VERSION_MAJOR,LZ4_VERSION_MINOR,LZ4_VERSION_RELEASE,0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "Yann Collet" - VALUE "FileDescription", "Extremely fast compression" - VALUE "FileVersion", LZ4_VERSION_STRING - VALUE "InternalName", "lz4.exe" - VALUE "LegalCopyright", "Copyright (C) 2013-2016, Yann Collet" - VALUE "OriginalFilename", "lz4.exe" - VALUE "ProductName", "LZ4" - VALUE "ProductVersion", LZ4_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1200 - END -END - -#endif diff --git a/ta6ob/lz4/build/VS2010/lz4/lz4.vcxproj b/ta6ob/lz4/build/VS2010/lz4/lz4.vcxproj deleted file mode 100644 index de7a714..0000000 --- a/ta6ob/lz4/build/VS2010/lz4/lz4.vcxproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {E30329AC-0057-4FE0-8FDA-7F650D398C4C} - Win32Proj - lz4 - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - Unicode - true - - - Application - false - Unicode - true - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - setargv.obj;%(AdditionalDependencies) - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - setargv.obj;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - setargv.obj;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - setargv.obj;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/VS2017/datagen/datagen.vcxproj b/ta6ob/lz4/build/VS2017/datagen/datagen.vcxproj deleted file mode 100644 index 30e159e..0000000 --- a/ta6ob/lz4/build/VS2017/datagen/datagen.vcxproj +++ /dev/null @@ -1,173 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {D745AE2F-596A-403A-9B91-81A8C6779243} - Win32Proj - datagen - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - v141 - - - Application - true - Unicode - v141 - - - Application - false - Unicode - true - v141 - - - Application - false - Unicode - true - v141 - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\programs;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/VS2017/frametest/frametest.vcxproj b/ta6ob/lz4/build/VS2017/frametest/frametest.vcxproj deleted file mode 100644 index a3a403d..0000000 --- a/ta6ob/lz4/build/VS2017/frametest/frametest.vcxproj +++ /dev/null @@ -1,180 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7} - Win32Proj - frametest - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - v141 - - - Application - true - Unicode - v141 - - - Application - false - Unicode - true - v141 - - - Application - false - Unicode - true - v141 - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/VS2017/fullbench-dll/fullbench-dll.vcxproj b/ta6ob/lz4/build/VS2017/fullbench-dll/fullbench-dll.vcxproj deleted file mode 100644 index d54a8d7..0000000 --- a/ta6ob/lz4/build/VS2017/fullbench-dll/fullbench-dll.vcxproj +++ /dev/null @@ -1,184 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {13992FD2-077E-4954-B065-A428198201A9} - Win32Proj - fullbench-dll - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - v141 - - - Application - true - Unicode - v141 - - - Application - false - Unicode - true - v141 - - - Application - false - Unicode - true - v141 - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - $(SolutionDir)bin\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/VS2017/fullbench/fullbench.vcxproj b/ta6ob/lz4/build/VS2017/fullbench/fullbench.vcxproj deleted file mode 100644 index 54c9743..0000000 --- a/ta6ob/lz4/build/VS2017/fullbench/fullbench.vcxproj +++ /dev/null @@ -1,180 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E} - Win32Proj - fullbench - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - v141 - - - Application - true - Unicode - v141 - - - Application - false - Unicode - true - v141 - - - Application - false - Unicode - true - v141 - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/VS2017/fuzzer/fuzzer.vcxproj b/ta6ob/lz4/build/VS2017/fuzzer/fuzzer.vcxproj deleted file mode 100644 index aa6fe42..0000000 --- a/ta6ob/lz4/build/VS2017/fuzzer/fuzzer.vcxproj +++ /dev/null @@ -1,177 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {18B9F1A7-9C66-4352-898B-30804DADE0FD} - Win32Proj - fuzzer - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - v141 - - - Application - true - Unicode - v141 - - - Application - false - Unicode - true - v141 - - - Application - false - Unicode - true - v141 - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - Console - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - Console - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - Console - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - Console - true - true - true - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/VS2017/liblz4-dll/liblz4-dll.rc b/ta6ob/lz4/build/VS2017/liblz4-dll/liblz4-dll.rc deleted file mode 100644 index b1871fe..0000000 --- a/ta6ob/lz4/build/VS2017/liblz4-dll/liblz4-dll.rc +++ /dev/null @@ -1,51 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// - -#include "lz4.h" /* LZ4_VERSION_STRING */ -#define APSTUDIO_READONLY_SYMBOLS -#include "verrsrc.h" -#undef APSTUDIO_READONLY_SYMBOLS - - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE 9, 1 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION LZ4_VERSION_MAJOR,LZ4_VERSION_MINOR,LZ4_VERSION_RELEASE,0 - PRODUCTVERSION LZ4_VERSION_MAJOR,LZ4_VERSION_MINOR,LZ4_VERSION_RELEASE,0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "Yann Collet" - VALUE "FileDescription", "Extremely fast compression" - VALUE "FileVersion", LZ4_VERSION_STRING - VALUE "InternalName", "lz4.dll" - VALUE "LegalCopyright", "Copyright (C) 2013-2016, Yann Collet" - VALUE "OriginalFilename", "lz4.dll" - VALUE "ProductName", "LZ4" - VALUE "ProductVersion", LZ4_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1200 - END -END - -#endif diff --git a/ta6ob/lz4/build/VS2017/liblz4-dll/liblz4-dll.vcxproj b/ta6ob/lz4/build/VS2017/liblz4-dll/liblz4-dll.vcxproj deleted file mode 100644 index 8e7ee3b..0000000 --- a/ta6ob/lz4/build/VS2017/liblz4-dll/liblz4-dll.vcxproj +++ /dev/null @@ -1,183 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {9800039D-4AAA-43A4-BB78-FEF6F4836927} - Win32Proj - liblz4-dll - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - liblz4-dll - - - - DynamicLibrary - true - Unicode - v141 - - - DynamicLibrary - true - Unicode - v141 - - - DynamicLibrary - false - Unicode - true - v141 - - - DynamicLibrary - false - Unicode - true - v141 - - - - - - - - - - - - - - - - - - - true - liblz4 - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - liblz4 - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - liblz4 - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - liblz4 - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - true - true - true - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/VS2017/liblz4/liblz4.vcxproj b/ta6ob/lz4/build/VS2017/liblz4/liblz4.vcxproj deleted file mode 100644 index 948f7db..0000000 --- a/ta6ob/lz4/build/VS2017/liblz4/liblz4.vcxproj +++ /dev/null @@ -1,179 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476} - Win32Proj - liblz4 - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - StaticLibrary - true - Unicode - v141 - - - StaticLibrary - true - Unicode - v141 - - - StaticLibrary - false - Unicode - true - v141 - - - StaticLibrary - false - Unicode - true - v141 - - - - - - - - - - - - - - - - - - - true - liblz4_static - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - liblz4_static - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - liblz4_static - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - liblz4_static - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - true - false - MultiThreadedDebug - - - true - - - - - - - Level4 - Disabled - WIN32;_DEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreadedDebug - - - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - false - false - MultiThreaded - - - true - true - true - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;LZ4_DLL_EXPORT=1;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - MultiThreaded - - - true - true - true - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/VS2017/lz4.sln b/ta6ob/lz4/build/VS2017/lz4.sln deleted file mode 100644 index 6a2779f..0000000 --- a/ta6ob/lz4/build/VS2017/lz4.sln +++ /dev/null @@ -1,103 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.271 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblz4-dll", "liblz4-dll\liblz4-dll.vcxproj", "{9800039D-4AAA-43A4-BB78-FEF6F4836927}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblz4", "liblz4\liblz4.vcxproj", "{9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fuzzer", "fuzzer\fuzzer.vcxproj", "{18B9F1A7-9C66-4352-898B-30804DADE0FD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench", "fullbench\fullbench.vcxproj", "{6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "frametest", "frametest\frametest.vcxproj", "{39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "datagen", "datagen\datagen.vcxproj", "{D745AE2F-596A-403A-9B91-81A8C6779243}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench-dll", "fullbench-dll\fullbench-dll.vcxproj", "{13992FD2-077E-4954-B065-A428198201A9}" - ProjectSection(ProjectDependencies) = postProject - {9800039D-4AAA-43A4-BB78-FEF6F4836927} = {9800039D-4AAA-43A4-BB78-FEF6F4836927} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lz4", "lz4\lz4.vcxproj", "{60A3115E-B988-41EE-8815-F4D4F253D866}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Debug|Win32.ActiveCfg = Debug|Win32 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Debug|Win32.Build.0 = Debug|Win32 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Debug|x64.ActiveCfg = Debug|x64 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Debug|x64.Build.0 = Debug|x64 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Release|Win32.ActiveCfg = Release|Win32 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Release|Win32.Build.0 = Release|Win32 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Release|x64.ActiveCfg = Release|x64 - {9800039D-4AAA-43A4-BB78-FEF6F4836927}.Release|x64.Build.0 = Release|x64 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|Win32.ActiveCfg = Debug|Win32 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|Win32.Build.0 = Debug|Win32 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|x64.ActiveCfg = Debug|x64 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Debug|x64.Build.0 = Debug|x64 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|Win32.ActiveCfg = Release|Win32 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|Win32.Build.0 = Release|Win32 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|x64.ActiveCfg = Release|x64 - {9092C5CC-3E71-41B3-BF68-4A7BDD8A5476}.Release|x64.Build.0 = Release|x64 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Debug|Win32.ActiveCfg = Debug|Win32 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Debug|Win32.Build.0 = Debug|Win32 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Debug|x64.ActiveCfg = Debug|x64 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Debug|x64.Build.0 = Debug|x64 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Release|Win32.ActiveCfg = Release|Win32 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Release|Win32.Build.0 = Release|Win32 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Release|x64.ActiveCfg = Release|x64 - {18B9F1A7-9C66-4352-898B-30804DADE0FD}.Release|x64.Build.0 = Release|x64 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Debug|Win32.ActiveCfg = Debug|Win32 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Debug|Win32.Build.0 = Debug|Win32 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Debug|x64.ActiveCfg = Debug|x64 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Debug|x64.Build.0 = Debug|x64 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Release|Win32.ActiveCfg = Release|Win32 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Release|Win32.Build.0 = Release|Win32 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Release|x64.ActiveCfg = Release|x64 - {6A4DF4EF-C77F-43C6-8901-DDCD20879E4E}.Release|x64.Build.0 = Release|x64 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Debug|Win32.ActiveCfg = Debug|Win32 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Debug|Win32.Build.0 = Debug|Win32 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Debug|x64.ActiveCfg = Debug|x64 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Debug|x64.Build.0 = Debug|x64 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Release|Win32.ActiveCfg = Release|Win32 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Release|Win32.Build.0 = Release|Win32 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Release|x64.ActiveCfg = Release|x64 - {39AD6ECC-8BAD-4368-95E4-A1AA2F077BB7}.Release|x64.Build.0 = Release|x64 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Debug|Win32.ActiveCfg = Debug|Win32 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Debug|Win32.Build.0 = Debug|Win32 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Debug|x64.ActiveCfg = Debug|x64 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Debug|x64.Build.0 = Debug|x64 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Release|Win32.ActiveCfg = Release|Win32 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Release|Win32.Build.0 = Release|Win32 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Release|x64.ActiveCfg = Release|x64 - {D745AE2F-596A-403A-9B91-81A8C6779243}.Release|x64.Build.0 = Release|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|Win32.ActiveCfg = Debug|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|Win32.Build.0 = Debug|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|x64.ActiveCfg = Debug|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|x64.Build.0 = Debug|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Release|Win32.ActiveCfg = Release|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Release|Win32.Build.0 = Release|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Release|x64.ActiveCfg = Release|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Release|x64.Build.0 = Release|x64 - {60A3115E-B988-41EE-8815-F4D4F253D866}.Debug|Win32.ActiveCfg = Debug|Win32 - {60A3115E-B988-41EE-8815-F4D4F253D866}.Debug|Win32.Build.0 = Debug|Win32 - {60A3115E-B988-41EE-8815-F4D4F253D866}.Debug|x64.ActiveCfg = Debug|x64 - {60A3115E-B988-41EE-8815-F4D4F253D866}.Debug|x64.Build.0 = Debug|x64 - {60A3115E-B988-41EE-8815-F4D4F253D866}.Release|Win32.ActiveCfg = Release|Win32 - {60A3115E-B988-41EE-8815-F4D4F253D866}.Release|Win32.Build.0 = Release|Win32 - {60A3115E-B988-41EE-8815-F4D4F253D866}.Release|x64.ActiveCfg = Release|x64 - {60A3115E-B988-41EE-8815-F4D4F253D866}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {BBC259B2-BABF-47CD-8A6A-7B8318A803AC} - EndGlobalSection -EndGlobal diff --git a/ta6ob/lz4/build/VS2017/lz4/lz4.rc b/ta6ob/lz4/build/VS2017/lz4/lz4.rc deleted file mode 100644 index c593edf..0000000 --- a/ta6ob/lz4/build/VS2017/lz4/lz4.rc +++ /dev/null @@ -1,51 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// - -#include "lz4.h" /* LZ4_VERSION_STRING */ -#define APSTUDIO_READONLY_SYMBOLS -#include "verrsrc.h" -#undef APSTUDIO_READONLY_SYMBOLS - - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE 9, 1 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION LZ4_VERSION_MAJOR,LZ4_VERSION_MINOR,LZ4_VERSION_RELEASE,0 - PRODUCTVERSION LZ4_VERSION_MAJOR,LZ4_VERSION_MINOR,LZ4_VERSION_RELEASE,0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "Yann Collet" - VALUE "FileDescription", "Extremely fast compression" - VALUE "FileVersion", LZ4_VERSION_STRING - VALUE "InternalName", "lz4.exe" - VALUE "LegalCopyright", "Copyright (C) 2013-2016, Yann Collet" - VALUE "OriginalFilename", "lz4.exe" - VALUE "ProductName", "LZ4" - VALUE "ProductVersion", LZ4_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1200 - END -END - -#endif diff --git a/ta6ob/lz4/build/VS2017/lz4/lz4.vcxproj b/ta6ob/lz4/build/VS2017/lz4/lz4.vcxproj deleted file mode 100644 index b4fed24..0000000 --- a/ta6ob/lz4/build/VS2017/lz4/lz4.vcxproj +++ /dev/null @@ -1,164 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 15.0 - {60A3115E-B988-41EE-8815-F4D4F253D866} - lz4 - 8.1 - - - - Application - true - v141 - Unicode - - - Application - false - v141 - false - Unicode - - - Application - true - v141 - MultiByte - - - Application - false - v141 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(SolutionDir)..\..\programs;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - false - - - - Level4 - Disabled - true - true - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - true - Console - false - false - - - - - Level3 - Disabled - true - true - - - - - Level3 - MaxSpeed - true - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - true - true - true - Console - - - - - Level3 - MaxSpeed - true - true - true - true - - - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/build/cmake/.gitignore b/ta6ob/lz4/build/cmake/.gitignore deleted file mode 100644 index d39505d..0000000 --- a/ta6ob/lz4/build/cmake/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# cmake artefact - -CMakeCache.txt -CMakeFiles -*.cmake -Makefile -liblz4.pc -lz4c -install_manifest.txt diff --git a/ta6ob/lz4/build/cmake/CMakeLists.txt b/ta6ob/lz4/build/cmake/CMakeLists.txt deleted file mode 100644 index 57501ee..0000000 --- a/ta6ob/lz4/build/cmake/CMakeLists.txt +++ /dev/null @@ -1,235 +0,0 @@ -# CMake support for LZ4 -# -# To the extent possible under law, the author(s) have dedicated all -# copyright and related and neighboring rights to this software to -# the public domain worldwide. This software is distributed without -# any warranty. -# -# For details, see . -# -# LZ4's CMake support is maintained by Evan Nemerson; when filing -# bugs please mention @nemequ to make sure I see it. - -set(LZ4_TOP_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../..") - -option(LZ4_BUILD_CLI "Build lz4 program" ON) -option(LZ4_BUILD_LEGACY_LZ4C "Build lz4c progam with legacy argument support" ON) - -# Parse version information -file(STRINGS "${LZ4_TOP_SOURCE_DIR}/lib/lz4.h" LZ4_VERSION_MAJOR REGEX "^#define LZ4_VERSION_MAJOR +([0-9]+) +.*$") -string(REGEX REPLACE "^#define LZ4_VERSION_MAJOR +([0-9]+) +.*$" "\\1" LZ4_VERSION_MAJOR "${LZ4_VERSION_MAJOR}") -file(STRINGS "${LZ4_TOP_SOURCE_DIR}/lib/lz4.h" LZ4_VERSION_MINOR REGEX "^#define LZ4_VERSION_MINOR +([0-9]+) +.*$") -string(REGEX REPLACE "^#define LZ4_VERSION_MINOR +([0-9]+) +.*$" "\\1" LZ4_VERSION_MINOR "${LZ4_VERSION_MINOR}") -file(STRINGS "${LZ4_TOP_SOURCE_DIR}/lib/lz4.h" LZ4_VERSION_RELEASE REGEX "^#define LZ4_VERSION_RELEASE +([0-9]+) +.*$") -string(REGEX REPLACE "^#define LZ4_VERSION_RELEASE +([0-9]+) +.*$" "\\1" LZ4_VERSION_RELEASE "${LZ4_VERSION_RELEASE}") -set(LZ4_VERSION_STRING "${LZ4_VERSION_MAJOR}.${LZ4_VERSION_MINOR}.${LZ4_VERSION_RELEASE}") -mark_as_advanced(LZ4_VERSION_STRING LZ4_VERSION_MAJOR LZ4_VERSION_MINOR LZ4_VERSION_RELEASE) - -if("${CMAKE_VERSION}" VERSION_LESS "3.0") - project(LZ4 C) -else() - cmake_policy (SET CMP0048 NEW) - project(LZ4 - VERSION ${LZ4_VERSION_STRING} - LANGUAGES C) -endif() - -cmake_minimum_required (VERSION 2.8.6) - -# If LZ4 is being bundled in another project, we don't want to -# install anything. However, we want to let people override this, so -# we'll use the LZ4_BUNDLED_MODE variable to let them do that; just -# set it to OFF in your project before you add_subdirectory(lz4/contrib/cmake_unofficial). -get_directory_property(LZ4_PARENT_DIRECTORY PARENT_DIRECTORY) -if("${LZ4_BUNDLED_MODE}" STREQUAL "") - # Bundled mode hasn't been set one way or the other, set the default - # depending on whether or not we are the top-level project. - if("${LZ4_PARENT_DIRECTORY}" STREQUAL "") - set(LZ4_BUNDLED_MODE OFF) - else() - set(LZ4_BUNDLED_MODE ON) - endif() -endif() -mark_as_advanced(LZ4_BUNDLED_MODE) - -# CPack -if(NOT LZ4_BUNDLED_MODE AND NOT CPack_CMake_INCLUDED) - set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LZ4 compression library") - set(CPACK_PACKAGE_DESCRIPTION_FILE "${LZ4_TOP_SOURCE_DIR}/README.md") - set(CPACK_RESOURCE_FILE_LICENSE "${LZ4_TOP_SOURCE_DIR}/LICENSE") - set(CPACK_PACKAGE_VERSION_MAJOR ${LZ4_VERSION_MAJOR}) - set(CPACK_PACKAGE_VERSION_MINOR ${LZ4_VERSION_MINOR}) - set(CPACK_PACKAGE_VERSION_PATCH ${LZ4_VERSION_RELEASE}) - include(CPack) -endif(NOT LZ4_BUNDLED_MODE AND NOT CPack_CMake_INCLUDED) - -# Allow people to choose whether to build shared or static libraries -# via the BUILD_SHARED_LIBS option unless we are in bundled mode, in -# which case we always use static libraries. -include(CMakeDependentOption) -CMAKE_DEPENDENT_OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON "NOT LZ4_BUNDLED_MODE" OFF) -CMAKE_DEPENDENT_OPTION(BUILD_STATIC_LIBS "Build static libraries" OFF "BUILD_SHARED_LIBS" ON) - -if(NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS) - message(FATAL_ERROR "Both BUILD_SHARED_LIBS and BUILD_STATIC_LIBS have been disabled") -endif() - -set(LZ4_LIB_SOURCE_DIR "${LZ4_TOP_SOURCE_DIR}/lib") -set(LZ4_PROG_SOURCE_DIR "${LZ4_TOP_SOURCE_DIR}/programs") - -include_directories("${LZ4_LIB_SOURCE_DIR}") - -# CLI sources -set(LZ4_SOURCES - "${LZ4_LIB_SOURCE_DIR}/lz4.c" - "${LZ4_LIB_SOURCE_DIR}/lz4hc.c" - "${LZ4_LIB_SOURCE_DIR}/lz4.h" - "${LZ4_LIB_SOURCE_DIR}/lz4hc.h" - "${LZ4_LIB_SOURCE_DIR}/lz4frame.c" - "${LZ4_LIB_SOURCE_DIR}/lz4frame.h" - "${LZ4_LIB_SOURCE_DIR}/xxhash.c") -set(LZ4_CLI_SOURCES - "${LZ4_PROG_SOURCE_DIR}/bench.c" - "${LZ4_PROG_SOURCE_DIR}/lz4cli.c" - "${LZ4_PROG_SOURCE_DIR}/lz4io.c" - "${LZ4_PROG_SOURCE_DIR}/datagen.c") - -# Whether to use position independent code for the static library. If -# we're building a shared library this is ignored and PIC is always -# used. -option(LZ4_POSITION_INDEPENDENT_LIB "Use position independent code for static library (if applicable)" ON) - -# liblz4 -set(LZ4_LIBRARIES_BUILT) -if(BUILD_SHARED_LIBS) - add_library(lz4_shared SHARED ${LZ4_SOURCES}) - set_target_properties(lz4_shared PROPERTIES - OUTPUT_NAME lz4 - SOVERSION "${LZ4_VERSION_MAJOR}" - VERSION "${LZ4_VERSION_STRING}") - if(MSVC) - target_compile_definitions(lz4_shared PRIVATE - LZ4_DLL_EXPORT=1) - endif() - list(APPEND LZ4_LIBRARIES_BUILT lz4_shared) -endif() -if(BUILD_STATIC_LIBS) - add_library(lz4_static STATIC ${LZ4_SOURCES}) - set_target_properties(lz4_static PROPERTIES - OUTPUT_NAME lz4 - POSITION_INDEPENDENT_CODE ${LZ4_POSITION_INDEPENDENT_LIB}) - list(APPEND LZ4_LIBRARIES_BUILT lz4_static) -endif() - -# link to shared whenever possible, to static otherwise -if(BUILD_SHARED_LIBS) - set(LZ4_LINK_LIBRARY lz4_shared) -else() - set(LZ4_LINK_LIBRARY lz4_static) -endif() - -# lz4 -if (LZ4_BUILD_CLI) - set(LZ4_PROGRAMS_BUILT lz4cli) - add_executable(lz4cli ${LZ4_CLI_SOURCES}) - set_target_properties(lz4cli PROPERTIES OUTPUT_NAME lz4) - target_link_libraries(lz4cli ${LZ4_LINK_LIBRARY}) -endif() - -# lz4c -if (LZ4_BUILD_LEGACY_LZ4C) - list(APPEND LZ4_PROGRAMS_BUILT lz4c) - add_executable(lz4c ${LZ4_CLI_SOURCES}) - set_target_properties(lz4c PROPERTIES COMPILE_DEFINITIONS "ENABLE_LZ4C_LEGACY_OPTIONS") - target_link_libraries(lz4c ${LZ4_LINK_LIBRARY}) -endif() - -# Extra warning flags -include (CheckCCompilerFlag) -foreach (flag - # GCC-style - -Wall - -Wextra - -Wundef - -Wcast-qual - -Wcast-align - -Wshadow - -Wswitch-enum - -Wdeclaration-after-statement - -Wstrict-prototypes - -Wpointer-arith - - # MSVC-style - /W4) - # Because https://gcc.gnu.org/wiki/FAQ#wnowarning - string(REGEX REPLACE "\\-Wno\\-(.+)" "-W\\1" flag_to_test "${flag}") - string(REGEX REPLACE "[^a-zA-Z0-9]+" "_" test_name "CFLAG_${flag_to_test}") - - check_c_compiler_flag("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${test_name}) - - if(${test_name}) - set(CMAKE_C_FLAGS "${flag} ${CMAKE_C_FLAGS}") - endif() - - unset(test_name) - unset(flag_to_test) -endforeach (flag) - -if(NOT LZ4_BUNDLED_MODE) - include(GNUInstallDirs) - - install(TARGETS ${LZ4_PROGRAMS_BUILT} - BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}" - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") - install(TARGETS ${LZ4_LIBRARIES_BUILT} - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") - install(FILES - "${LZ4_LIB_SOURCE_DIR}/lz4.h" - "${LZ4_LIB_SOURCE_DIR}/lz4frame.h" - "${LZ4_LIB_SOURCE_DIR}/lz4hc.h" - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") - install(FILES "${LZ4_PROG_SOURCE_DIR}/lz4.1" - DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/liblz4.pc" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") - - # install lz4cat and unlz4 symlinks on *nix - if(UNIX AND LZ4_BUILD_CLI) - install(CODE " - foreach(f lz4cat unlz4) - set(dest \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/\${f}\") - message(STATUS \"Symlinking: \${dest} -> lz4\") - execute_process( - COMMAND \"${CMAKE_COMMAND}\" -E create_symlink lz4 \"\${dest}\") - endforeach() - ") - - # create manpage aliases - foreach(f lz4cat unlz4) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${f}.1" ".so man1/lz4.1\n") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${f}.1" - DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") - endforeach() - endif(UNIX AND LZ4_BUILD_CLI) -endif(NOT LZ4_BUNDLED_MODE) - -# pkg-config -set(PREFIX "${CMAKE_INSTALL_PREFIX}") - -if("${CMAKE_INSTALL_FULL_LIBDIR}" STREQUAL "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") - set(LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}") -else() - set(LIBDIR "${CMAKE_INSTALL_FULL_LIBDIR}") -endif() - -if("${CMAKE_INSTALL_FULL_INCLUDEDIR}" STREQUAL "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") - set(INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") -else() - set(INCLUDEDIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}") -endif() - -# for liblz4.pc substitution -set(VERSION ${LZ4_VERSION_STRING}) -configure_file(${LZ4_LIB_SOURCE_DIR}/liblz4.pc.in liblz4.pc @ONLY) diff --git a/ta6ob/lz4/contrib/debian/changelog b/ta6ob/lz4/contrib/debian/changelog deleted file mode 100644 index 87ac016..0000000 --- a/ta6ob/lz4/contrib/debian/changelog +++ /dev/null @@ -1,10 +0,0 @@ -liblz4 (1.7.2) unstable; urgency=low - - * Changed : moved to versioning; package, cli and library have same version number - * Improved: Small decompression speed boost (+4%) - * Improved: Performance on ARMv6 and ARMv7 - * Added : Debianization, by Evgeniy Polyakov - * Makefile: Generates object files (*.o) for faster (re)compilation on low power systems - * Fix : cli : crash on some invalid inputs - - -- Yann Collet Sun, 28 Jun 2015 01:00:00 +0000 diff --git a/ta6ob/lz4/contrib/debian/compat b/ta6ob/lz4/contrib/debian/compat deleted file mode 100644 index 7f8f011..0000000 --- a/ta6ob/lz4/contrib/debian/compat +++ /dev/null @@ -1 +0,0 @@ -7 diff --git a/ta6ob/lz4/contrib/debian/control b/ta6ob/lz4/contrib/debian/control deleted file mode 100644 index ac3b460..0000000 --- a/ta6ob/lz4/contrib/debian/control +++ /dev/null @@ -1,23 +0,0 @@ -Source: liblz4 -Section: devel -Priority: optional -Maintainer: Evgeniy Polyakov -Build-Depends: - cmake (>= 2.6), - debhelper (>= 7.0.50~), - cdbs -Standards-Version: 3.8.0 -Homepage: http://www.lz4.org/ -Vcs-Git: git://github.com/lz4/lz4.git -Vcs-Browser: https://github.com/lz4/lz4 - -Package: liblz4 -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: Extremely Fast Compression algorithm http://www.lz4.org - -Package: liblz4-dev -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: Extremely Fast Compression algorithm http://www.lz4.org - Development files. diff --git a/ta6ob/lz4/contrib/debian/copyright b/ta6ob/lz4/contrib/debian/copyright deleted file mode 100644 index 0914768..0000000 --- a/ta6ob/lz4/contrib/debian/copyright +++ /dev/null @@ -1,9 +0,0 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: liblz4 -Upstream-Contact: Yann Collet -Source: https://github.com/lz4/lz4 - -Files: * -Copyright: (C) 2011-2020 Yann Collet -License: GPL-2+ - The full text of license: https://github.com/lz4/lz4/blob/dev/lib/LICENSE diff --git a/ta6ob/lz4/contrib/debian/dirs b/ta6ob/lz4/contrib/debian/dirs deleted file mode 100644 index e772481..0000000 --- a/ta6ob/lz4/contrib/debian/dirs +++ /dev/null @@ -1 +0,0 @@ -usr/bin diff --git a/ta6ob/lz4/contrib/debian/docs b/ta6ob/lz4/contrib/debian/docs deleted file mode 100644 index e69de29..0000000 diff --git a/ta6ob/lz4/contrib/debian/liblz4-dev.install b/ta6ob/lz4/contrib/debian/liblz4-dev.install deleted file mode 100644 index 3a02909..0000000 --- a/ta6ob/lz4/contrib/debian/liblz4-dev.install +++ /dev/null @@ -1,2 +0,0 @@ -usr/include/lz4* -usr/lib/liblz4.so diff --git a/ta6ob/lz4/contrib/debian/liblz4.install b/ta6ob/lz4/contrib/debian/liblz4.install deleted file mode 100644 index e444956..0000000 --- a/ta6ob/lz4/contrib/debian/liblz4.install +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/liblz4.so.* -usr/bin/* diff --git a/ta6ob/lz4/contrib/debian/rules b/ta6ob/lz4/contrib/debian/rules deleted file mode 100755 index c897bc5..0000000 --- a/ta6ob/lz4/contrib/debian/rules +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/make -f - -include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/class/cmake.mk - - -DEB_CMAKE_EXTRA_FLAGS := -DCMAKE_BUILD_TYPE=RelWithDebInfo ../../build/cmake diff --git a/ta6ob/lz4/contrib/djgpp/LICENSE b/ta6ob/lz4/contrib/djgpp/LICENSE deleted file mode 100644 index fee0d3b..0000000 --- a/ta6ob/lz4/contrib/djgpp/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2014, lpsantil -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/ta6ob/lz4/contrib/djgpp/Makefile b/ta6ob/lz4/contrib/djgpp/Makefile deleted file mode 100644 index 8cd3580..0000000 --- a/ta6ob/lz4/contrib/djgpp/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (c) 2015, Louis P. Santillan -# All rights reserved. -# See LICENSE for licensing details. -DESTDIR ?= /opt/local - -# Pulled the code below from lib/Makefile. Might be nicer to derive this somehow without sed -# Version numbers -VERSION ?= 129 -RELEASE ?= r$(VERSION) -LIBVER_MAJOR=$(shell sed -n '/define LZ4_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < lib/lz4.h) -LIBVER_MINOR=$(shell sed -n '/define LZ4_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < lib/lz4.h) -LIBVER_PATCH=$(shell sed -n '/define LZ4_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < lib/lz4.h) -LIBVER=$(LIBVER_MAJOR).$(LIBVER_MINOR).$(LIBVER_PATCH) - -###################################################################### - -CROSS ?= i586-pc-msdosdjgpp -CC = $(CROSS)-gcc -AR = $(CROSS)-ar -LD = $(CROSS)-gcc - -CFLAGS ?= -O3 -std=gnu99 -Wall -Wextra -Wundef -Wshadow -Wcast-qual -Wcast-align -Wstrict-prototypes -pedantic -DLZ4_VERSION=\"$(RELEASE)\" -LDFLAGS ?= -s -SRC = programs/bench.c programs/lz4io.c programs/lz4cli.c -OBJ = $(SRC:.c=.o) -SDEPS = $(SRC:.c=.d) -IDIR = lib -EDIR = . -EXE = lz4.exe -LNK = lz4 -LDIR = lib -LSRC = lib/lz4.c lib/lz4hc.c lib/lz4frame.c lib/xxhash.c -INC = $(LSRC:.c=.h) -LOBJ = $(LSRC:.c=.o) -LSDEPS = $(LSRC:.c=.d) -LIB = $(LDIR)/lib$(LNK).a - -# Since LDFLAGS defaults to "-s", probably better to override unless -# you have a default you would like to maintain -ifeq ($(WITH_DEBUG), 1) - CFLAGS += -g - LDFLAGS += -g -endif - -# Since LDFLAGS defaults to "-s", probably better to override unless -# you have a default you would like to maintain -ifeq ($(WITH_PROFILING), 1) - CFLAGS += -pg - LDFLAGS += -pg -endif - -%.o: %.c $(INC) Makefile - $(CC) $(CFLAGS) -MMD -MP -I$(IDIR) -c $< -o $@ - -%.exe: %.o $(LIB) Makefile - $(LD) $< -L$(LDIR) -l$(LNK) $(LDFLAGS) $(LIBDEP) -o $@ - -###################################################################### -######################## DO NOT MODIFY BELOW ######################### -###################################################################### - -.PHONY: all install uninstall showconfig gstat gpush - -all: $(LIB) $(EXE) - -$(LIB): $(LOBJ) - $(AR) -rcs $@ $^ - -$(EXE): $(LOBJ) $(OBJ) - $(LD) $(LDFLAGS) $(LOBJ) $(OBJ) -o $(EDIR)/$@ - -clean: - rm -f $(OBJ) $(EXE) $(LOBJ) $(LIB) *.tmp $(SDEPS) $(LSDEPS) $(TSDEPS) - -install: $(INC) $(LIB) $(EXE) - mkdir -p $(DESTDIR)/bin $(DESTDIR)/include $(DESTDIR)/lib - rm -f .footprint - echo $(DESTDIR)/bin/$(EXE) >> .footprint - cp -v $(EXE) $(DESTDIR)/bin/ - @for T in $(LIB); \ - do ( \ - echo $(DESTDIR)/$$T >> .footprint; \ - cp -v --parents $$T $(DESTDIR) \ - ); done - @for T in $(INC); \ - do ( \ - echo $(DESTDIR)/include/`basename -a $$T` >> .footprint; \ - cp -v $$T $(DESTDIR)/include/ \ - ); done - -uninstall: .footprint - @for T in $(shell cat .footprint); do rm -v $$T; done - --include $(SDEPS) $(LSDEPS) - -showconfig: - @echo "PWD="$(PWD) - @echo "VERSION="$(VERSION) - @echo "RELEASE="$(RELEASE) - @echo "LIBVER_MAJOR="$(LIBVER_MAJOR) - @echo "LIBVER_MINOR="$(LIBVER_MINOR) - @echo "LIBVER_PATCH="$(LIBVER_PATCH) - @echo "LIBVER="$(LIBVER) - @echo "CROSS="$(CROSS) - @echo "CC="$(CC) - @echo "AR="$(AR) - @echo "LD="$(LD) - @echo "DESTDIR="$(DESTDIR) - @echo "CFLAGS="$(CFLAGS) - @echo "LDFLAGS="$(LDFLAGS) - @echo "SRC="$(SRC) - @echo "OBJ="$(OBJ) - @echo "IDIR="$(IDIR) - @echo "INC="$(INC) - @echo "EDIR="$(EDIR) - @echo "EXE="$(EXE) - @echo "LDIR="$(LDIR) - @echo "LSRC="$(LSRC) - @echo "LOBJ="$(LOBJ) - @echo "LNK="$(LNK) - @echo "LIB="$(LIB) - @echo "SDEPS="$(SDEPS) - @echo "LSDEPS="$(LSDEPS) - -gstat: - git status - -gpush: - git commit - git push diff --git a/ta6ob/lz4/contrib/djgpp/README.MD b/ta6ob/lz4/contrib/djgpp/README.MD deleted file mode 100644 index 0f4cae6..0000000 --- a/ta6ob/lz4/contrib/djgpp/README.MD +++ /dev/null @@ -1,21 +0,0 @@ -# lz4 for DOS/djgpp -This file details on how to compile lz4.exe, and liblz4.a for use on DOS/djgpp using -Andrew Wu's build-djgpp cross compilers ([GH][0], [Binaries][1]) on OSX, Linux. - -## Setup -* Download a djgpp tarball [binaries][1] for your platform. -* Extract and install it (`tar jxvf djgpp-linux64-gcc492.tar.bz2`). Note the path. We'll assume `/home/user/djgpp`. -* Add the `bin` folder to your `PATH`. In bash, do `export PATH=/home/user/djgpp/bin:$PATH`. -* The `Makefile` in `contrib/djgpp/` sets up `CC`, `AR`, `LD` for you. So, `CC=i586-pc-msdosdjgpp-gcc`, `AR=i586-pc-msdosdjgpp-ar`, `LD=i586-pc-msdosdjgpp-gcc`. - -## Building LZ4 for DOS -In the base dir of lz4 and with `contrib/djgpp/Makefile`, try: -Try: -* `make -f contrib/djgpp/Makefile` -* `make -f contrib/djgpp/Makefile liblz4.a` -* `make -f contrib/djgpp/Makefile lz4.exe` -* `make -f contrib/djgpp/Makefile DESTDIR=/home/user/dos install`, however it doesn't make much sense on a \*nix. -* You can also do `make -f contrib/djgpp/Makefile uninstall` - -[0]: https://github.com/andrewwutw/build-djgpp -[1]: https://github.com/andrewwutw/build-djgpp/releases diff --git a/ta6ob/lz4/contrib/gen_manual/.gitignore b/ta6ob/lz4/contrib/gen_manual/.gitignore deleted file mode 100644 index 6ea967f..0000000 --- a/ta6ob/lz4/contrib/gen_manual/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# build artefact -gen_manual diff --git a/ta6ob/lz4/contrib/gen_manual/Makefile b/ta6ob/lz4/contrib/gen_manual/Makefile deleted file mode 100644 index 95abe2e..0000000 --- a/ta6ob/lz4/contrib/gen_manual/Makefile +++ /dev/null @@ -1,76 +0,0 @@ -# ################################################################ -# Copyright (C) Przemyslaw Skibinski 2016-present -# All rights reserved. -# -# BSD license -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, this -# list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# You can contact the author at : -# - LZ4 source repository : https://github.com/Cyan4973/lz4 -# - LZ4 forum froup : https://groups.google.com/forum/#!forum/lz4c -# ################################################################ - - -CXXFLAGS ?= -O3 -CXXFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow -Wstrict-aliasing=1 -Wswitch-enum -Wno-comment -CXXFLAGS += $(MOREFLAGS) -FLAGS = $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) - -LZ4API = ../../lib/lz4.h -LZ4MANUAL = ../../doc/lz4_manual.html -LZ4FAPI = ../../lib/lz4frame.h -LZ4FMANUAL = ../../doc/lz4frame_manual.html -LIBVER_MAJOR_SCRIPT:=`sed -n '/define LZ4_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LZ4API)` -LIBVER_MINOR_SCRIPT:=`sed -n '/define LZ4_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LZ4API)` -LIBVER_PATCH_SCRIPT:=`sed -n '/define LZ4_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LZ4API)` -LIBVER_SCRIPT:= $(LIBVER_MAJOR_SCRIPT).$(LIBVER_MINOR_SCRIPT).$(LIBVER_PATCH_SCRIPT) -LZ4VER := $(shell echo $(LIBVER_SCRIPT)) - -# Define *.exe as extension for Windows systems -ifneq (,$(filter Windows%,$(OS))) -EXT =.exe -else -EXT = -endif - - -.PHONY: default -default: gen_manual - -gen_manual: gen_manual.cpp - $(CXX) $(FLAGS) $^ -o $@$(EXT) - -$(LZ4MANUAL) : gen_manual $(LZ4API) - echo "Update lz4 manual in /doc" - ./gen_manual $(LZ4VER) $(LZ4API) $@ - -$(LZ4FMANUAL) : gen_manual $(LZ4FAPI) - echo "Update lz4frame manual in /doc" - ./gen_manual $(LZ4VER) $(LZ4FAPI) $@ - -.PHONY: manuals -manuals: gen_manual $(LZ4MANUAL) $(LZ4FMANUAL) - -.PHONY: clean -clean: - @$(RM) gen_manual$(EXT) - @echo Cleaning completed diff --git a/ta6ob/lz4/contrib/gen_manual/README.md b/ta6ob/lz4/contrib/gen_manual/README.md deleted file mode 100644 index 7664ac6..0000000 --- a/ta6ob/lz4/contrib/gen_manual/README.md +++ /dev/null @@ -1,31 +0,0 @@ -gen_manual - a program for automatic generation of manual from source code -========================================================================== - -#### Introduction - -This simple C++ program generates a single-page HTML manual from `lz4.h`. - -The format of recognized comment blocks is following: -- comments of type `/*!` mean: this is a function declaration; switch comments with declarations -- comments of type `/**` and `/*-` mean: this is a comment; use a `

` header for the first line -- comments of type `/*=` and `/**=` mean: use a `

` header and show also all functions until first empty line -- comments of type `/*X` where `X` is different from above-mentioned are ignored - -Moreover: -- `LZ4LIB_API` is removed to improve readability -- `typedef` are detected and included even if uncommented -- comments of type `/**<` and `/*!<` are detected and only function declaration is highlighted (bold) - - -#### Usage - -The program requires 3 parameters: -``` -gen_manual [lz4_version] [input_file] [output_html] -``` - -To compile program and generate lz4 manual we have used: -``` -make -./gen_manual.exe 1.7.3 ../../lib/lz4.h lz4_manual.html -``` diff --git a/ta6ob/lz4/contrib/gen_manual/gen-lz4-manual.sh b/ta6ob/lz4/contrib/gen_manual/gen-lz4-manual.sh deleted file mode 100644 index 73a7214..0000000 --- a/ta6ob/lz4/contrib/gen_manual/gen-lz4-manual.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -LIBVER_MAJOR_SCRIPT=`sed -n '/define LZ4_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ../../lib/lz4.h` -LIBVER_MINOR_SCRIPT=`sed -n '/define LZ4_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ../../lib/lz4.h` -LIBVER_PATCH_SCRIPT=`sed -n '/define LZ4_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ../../lib/lz4.h` -LIBVER_SCRIPT=$LIBVER_MAJOR_SCRIPT.$LIBVER_MINOR_SCRIPT.$LIBVER_PATCH_SCRIPT - -echo LZ4_VERSION=$LIBVER_SCRIPT -./gen_manual "lz4 $LIBVER_SCRIPT" ../../lib/lz4.h ./lz4_manual.html -./gen_manual "lz4frame $LIBVER_SCRIPT" ../../lib/lz4frame.h ./lz4frame_manual.html diff --git a/ta6ob/lz4/contrib/gen_manual/gen_manual.cpp b/ta6ob/lz4/contrib/gen_manual/gen_manual.cpp deleted file mode 100644 index d5fe702..0000000 --- a/ta6ob/lz4/contrib/gen_manual/gen_manual.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* -Copyright (c) 2016-present, Przemyslaw Skibinski -All rights reserved. - -BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -You can contact the author at : -- LZ4 homepage : http://www.lz4.org -- LZ4 source repository : https://github.com/lz4/lz4 -*/ - -#include -#include -#include -#include -using namespace std; - - -/* trim string at the beginning and at the end */ -void trim(string& s, string characters) -{ - size_t p = s.find_first_not_of(characters); - s.erase(0, p); - - p = s.find_last_not_of(characters); - if (string::npos != p) - s.erase(p+1); -} - - -/* trim C++ style comments */ -void trim_comments(string &s) -{ - size_t spos, epos; - - spos = s.find("/*"); - epos = s.find("*/"); - s = s.substr(spos+3, epos-(spos+3)); -} - - -/* get lines until a given terminator */ -vector get_lines(vector& input, int& linenum, string terminator) -{ - vector out; - string line; - - while ((size_t)linenum < input.size()) { - line = input[linenum]; - - if (terminator.empty() && line.empty()) { linenum--; break; } - - size_t const epos = line.find(terminator); - if (!terminator.empty() && epos!=string::npos) { - out.push_back(line); - break; - } - out.push_back(line); - linenum++; - } - return out; -} - - -/* print line with LZ4LIB_API removed and C++ comments not bold */ -void print_line(stringstream &sout, string line) -{ - size_t spos, epos; - - if (line.substr(0,11) == "LZ4LIB_API ") line = line.substr(11); - if (line.substr(0,12) == "LZ4FLIB_API ") line = line.substr(12); - spos = line.find("/*"); - epos = line.find("*/"); - if (spos!=string::npos && epos!=string::npos) { - sout << line.substr(0, spos); - sout << "" << line.substr(spos) << "" << '\n'; - } else { - sout << line << '\n'; - } -} - - -int main(int argc, char *argv[]) { - char exclam; - int linenum, chapter = 1; - vector input, lines, comments, chapters; - string line, version; - size_t spos, l; - stringstream sout; - ifstream istream; - ofstream ostream; - - if (argc < 4) { - cout << "usage: " << argv[0] << " [lz4_version] [input_file] [output_html]" << endl; - return 1; - } - - version = string(argv[1]) + " Manual"; - - istream.open(argv[2], ifstream::in); - if (!istream.is_open()) { - cout << "Error opening file " << argv[2] << endl; - return 1; - } - - ostream.open(argv[3], ifstream::out); - if (!ostream.is_open()) { - cout << "Error opening file " << argv[3] << endl; - return 1; - } - - while (getline(istream, line)) { - input.push_back(line); - } - - for (linenum=0; (size_t)linenum < input.size(); linenum++) { - line = input[linenum]; - - /* typedefs are detected and included even if uncommented */ - if (line.substr(0,7) == "typedef" && line.find("{")!=string::npos) { - lines = get_lines(input, linenum, "}"); - sout << "
";
-            for (l=0; l

" << endl; - continue; - } - - /* comments of type / * * < and / * ! < are detected, and only function declaration is highlighted (bold) */ - if ((line.find("/**<")!=string::npos || line.find("/*!<")!=string::npos) - && line.find("*/")!=string::npos) { - sout << "
";
-            print_line(sout, line);
-            sout << "

" << endl; - continue; - } - - spos = line.find("/**="); - if (spos==string::npos) { - spos = line.find("/*!"); - if (spos==string::npos) - spos = line.find("/**"); - if (spos==string::npos) - spos = line.find("/*-"); - if (spos==string::npos) - spos = line.find("/*="); - if (spos==string::npos) - continue; - exclam = line[spos+2]; - } - else exclam = '='; - - comments = get_lines(input, linenum, "*/"); - if (!comments.empty()) comments[0] = line.substr(spos+3); - if (!comments.empty()) - comments[comments.size()-1] = comments[comments.size()-1].substr(0, comments[comments.size()-1].find("*/")); - for (l=0; l"; - for (l=0; l

"; - for (l=0; l
" << endl << endl; - } else if (exclam == '=') { /* comments of type / * = and / * * = mean: use a

header and show also all functions until first empty line */ - trim(comments[0], " "); - sout << "

" << comments[0] << "

";
-            for (l=1; l
";
-            lines = get_lines(input, ++linenum, "");
-            for (l=0; l
" << endl; - } else { /* comments of type / * * and / * - mean: this is a comment; use a

header for the first line */ - if (comments.empty()) continue; - - trim(comments[0], " "); - sout << "

" << comments[0] << "

";
-            chapters.push_back(comments[0]);
-            chapter++;
-
-            for (l=1; l 1)
-                sout << "
" << endl << endl; - else - sout << "
" << endl << endl; - } - } - - ostream << "\n\n\n" << version << "\n\n" << endl; - ostream << "

" << version << "

\n"; - - ostream << "
\n

Contents

\n
    \n"; - for (size_t i=0; i" << chapters[i].c_str() << "\n"; - ostream << "
\n
\n"; - - ostream << sout.str(); - ostream << "" << endl << "" << endl; - - return 0; -} diff --git a/ta6ob/lz4/contrib/meson/README.md b/ta6ob/lz4/contrib/meson/README.md deleted file mode 100644 index a44850a..0000000 --- a/ta6ob/lz4/contrib/meson/README.md +++ /dev/null @@ -1,34 +0,0 @@ -Meson build system for lz4 -========================== - -Meson is a build system designed to optimize programmer productivity. -It aims to do this by providing simple, out-of-the-box support for -modern software development tools and practices, such as unit tests, -coverage reports, Valgrind, CCache and the like. - -This Meson build system is provided with no guarantee. - -## How to build - -`cd` to this meson directory (`contrib/meson`) - -```sh -meson setup --buildtype=release -Ddefault_library=shared -Dbin_programs=true builddir -cd builddir -ninja # to build -ninja install # to install -``` - -You might want to install it in staging directory: - -```sh -DESTDIR=./staging ninja install -``` - -To configure build options, use: - -```sh -meson configure -``` - -See [man meson(1)](https://manpages.debian.org/testing/meson/meson.1.en.html). diff --git a/ta6ob/lz4/contrib/meson/meson.build b/ta6ob/lz4/contrib/meson/meson.build deleted file mode 100644 index d1e97d9..0000000 --- a/ta6ob/lz4/contrib/meson/meson.build +++ /dev/null @@ -1,21 +0,0 @@ -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# - -# This is a dummy meson file. -# The intention is that it can be easily moved to the root of the project -# (together with meson_options.txt) and packaged for wrapdb. - -project('lz4', ['c'], - license: ['BSD', 'GPLv2'], - default_options : ['c_std=c99', - 'buildtype=release'], - version: 'DUMMY', - meson_version: '>=0.47.0') - -subdir('meson') diff --git a/ta6ob/lz4/contrib/meson/meson/GetLz4LibraryVersion.py b/ta6ob/lz4/contrib/meson/meson/GetLz4LibraryVersion.py deleted file mode 100644 index d8abfcb..0000000 --- a/ta6ob/lz4/contrib/meson/meson/GetLz4LibraryVersion.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python3 -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# -import re - - -def find_version_tuple(filepath): - version_file_data = None - with open(filepath) as fd: - version_file_data = fd.read() - - patterns = r"""#\s*define\s+LZ4_VERSION_MAJOR\s+([0-9]+).*$ -#\s*define\s+LZ4_VERSION_MINOR\s+([0-9]+).*$ -#\s*define\s+LZ4_VERSION_RELEASE\s+([0-9]+).*$ -""" - regex = re.compile(patterns, re.MULTILINE) - version_match = regex.search(version_file_data) - if version_match: - return version_match.groups() - raise Exception("Unable to find version string.") - - -def main(): - import argparse - parser = argparse.ArgumentParser(description='Print lz4 version from lib/lz4.h') - parser.add_argument('file', help='path to lib/lz4.h') - args = parser.parse_args() - version_tuple = find_version_tuple(args.file) - print('.'.join(version_tuple)) - - -if __name__ == '__main__': - main() diff --git a/ta6ob/lz4/contrib/meson/meson/InstallSymlink.py b/ta6ob/lz4/contrib/meson/meson/InstallSymlink.py deleted file mode 100644 index 3f2998c..0000000 --- a/ta6ob/lz4/contrib/meson/meson/InstallSymlink.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# -# This file should be synced with https://github.com/lzutao/meson-symlink - -import os -import pathlib # since Python 3.4 - - -def install_symlink(src, dst, install_dir, dst_is_dir=False, dir_mode=0o777): - if not install_dir.exists(): - install_dir.mkdir(mode=dir_mode, parents=True, exist_ok=True) - if not install_dir.is_dir(): - raise NotADirectoryError(install_dir) - - new_dst = install_dir.joinpath(dst) - if new_dst.is_symlink() and os.readlink(new_dst) == src: - print('File exists: {!r} -> {!r}'.format(new_dst, src)) - return - print('Installing symlink {!r} -> {!r}'.format(new_dst, src)) - new_dst.symlink_to(src, target_is_directory=dst_is_dir) - - -def main(): - import argparse - parser = argparse.ArgumentParser(description='Install a symlink', - usage='{0} [-h] [-d] [-m MODE] source dest install_dir\n\n' - 'example:\n' - ' {0} dash sh /bin'.format(pathlib.Path(__file__).name)) - parser.add_argument('source', help='target to link') - parser.add_argument('dest', help='link name') - parser.add_argument('install_dir', help='installation directory') - parser.add_argument('-d', '--isdir', - action='store_true', - help='dest is a directory') - parser.add_argument('-m', '--mode', - help='directory mode on creating if not exist', - default='0o755') - args = parser.parse_args() - - dir_mode = int(args.mode, 8) - - meson_destdir = os.environ.get('MESON_INSTALL_DESTDIR_PREFIX', default='') - install_dir = pathlib.Path(meson_destdir, args.install_dir) - install_symlink(args.source, args.dest, install_dir, args.isdir, dir_mode) - - -if __name__ == '__main__': - main() diff --git a/ta6ob/lz4/contrib/meson/meson/contrib/gen_manual/meson.build b/ta6ob/lz4/contrib/meson/meson/contrib/gen_manual/meson.build deleted file mode 100644 index a872bd6..0000000 --- a/ta6ob/lz4/contrib/meson/meson/contrib/gen_manual/meson.build +++ /dev/null @@ -1,43 +0,0 @@ -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# - -lz4_root_dir = '../../../../..' - -add_languages('cpp') -cxx = meson.get_compiler('cpp') - -gen_manual_includes = include_directories(join_paths(lz4_root_dir, 'contrib/gen_manual')) - -gen_manual_cppflags = cxx.get_supported_arguments(['-Wextra', '-Wcast-qual', - '-Wcast-align', '-Wshadow', '-Wstrict-aliasing=1', '-Wswitch-enum', - '-Wno-comment']) - -gen_manual = executable('gen_manual', - join_paths(lz4_root_dir, 'contrib/gen_manual/gen_manual.cpp'), - cpp_args: gen_manual_cppflags, - include_directories: gen_manual_includes, - native: true, - install: false) - -# Update lz4 manual -lz4_manual_html = custom_target('lz4_manual.html', - output : 'lz4_manual.html', - command : [gen_manual, - lz4_version, - join_paths(meson.current_source_dir(), lz4_root_dir, 'lib/lz4.h'), - '@OUTPUT@'], - install : false) -# Update lz4frame manual -lz4_manual_html = custom_target('lz4frame_manual.html', - output : 'lz4frame_manual.html', - command : [gen_manual, - lz4_version, - join_paths(meson.current_source_dir(), lz4_root_dir, 'lib/lz4frame.h'), - '@OUTPUT@'], - install : false) diff --git a/ta6ob/lz4/contrib/meson/meson/contrib/meson.build b/ta6ob/lz4/contrib/meson/meson/contrib/meson.build deleted file mode 100644 index 5249a4c..0000000 --- a/ta6ob/lz4/contrib/meson/meson/contrib/meson.build +++ /dev/null @@ -1,10 +0,0 @@ -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# - -subdir('gen_manual') diff --git a/ta6ob/lz4/contrib/meson/meson/examples/meson.build b/ta6ob/lz4/contrib/meson/meson/examples/meson.build deleted file mode 100644 index 493049d..0000000 --- a/ta6ob/lz4/contrib/meson/meson/examples/meson.build +++ /dev/null @@ -1,49 +0,0 @@ -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# - -lz4_root_dir = '../../../..' - -#examples_c_args = ['-Wextra', '-Wundef', '-Wshadow', '-Wcast-align', '-Wstrict-prototypes'] - -printVersion = executable('printVersion', - join_paths(lz4_root_dir, 'examples/printVersion.c'), - dependencies: liblz4_dep, - install: false) -doubleBuffer = executable('doubleBuffer', - join_paths(lz4_root_dir, 'examples/blockStreaming_doubleBuffer.c'), - dependencies: liblz4_dep, - install: false) -dictionaryRandomAccess = executable('dictionaryRandomAccess', - join_paths(lz4_root_dir, 'examples/dictionaryRandomAccess.c'), - dependencies: liblz4_dep, - install: false) -ringBuffer = executable('ringBuffer', - join_paths(lz4_root_dir, 'examples/blockStreaming_ringBuffer.c'), - dependencies: liblz4_dep, - install: false) -ringBufferHC = executable('ringBufferHC', - join_paths(lz4_root_dir, 'examples/HCStreaming_ringBuffer.c'), - dependencies: liblz4_dep, - install: false) -lineCompress = executable('lineCompress', - join_paths(lz4_root_dir, 'examples/blockStreaming_lineByLine.c'), - dependencies: liblz4_dep, - install: false) -frameCompress = executable('frameCompress', - join_paths(lz4_root_dir, 'examples/frameCompress.c'), - dependencies: liblz4_dep, - install: false) -compressFunctions = executable('compressFunctions', - join_paths(lz4_root_dir, 'examples/compress_functions.c'), - dependencies: liblz4_dep, - install: false) -simpleBuffer = executable('simpleBuffer', - join_paths(lz4_root_dir, 'examples/simple_buffer.c'), - dependencies: liblz4_dep, - install: false) diff --git a/ta6ob/lz4/contrib/meson/meson/lib/meson.build b/ta6ob/lz4/contrib/meson/meson/lib/meson.build deleted file mode 100644 index 131edcb..0000000 --- a/ta6ob/lz4/contrib/meson/meson/lib/meson.build +++ /dev/null @@ -1,57 +0,0 @@ -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# - -lz4_root_dir = '../../../..' - -liblz4_includes = [include_directories(join_paths(lz4_root_dir, 'lib'))] -liblz4_sources = [join_paths(lz4_root_dir, 'lib/lz4.c'), - join_paths(lz4_root_dir, 'lib/lz4frame.c'), - join_paths(lz4_root_dir, 'lib/lz4hc.c'), - join_paths(lz4_root_dir, 'lib/xxhash.c')] -liblz4_c_args = [] - -liblz4_debug_cflags = [] -if use_debug - liblz4_c_args += '-DLZ4_DEBUG=@0@'.format(debug_level) - if [compiler_gcc, compiler_clang].contains(cc_id) - liblz4_debug_cflags = ['-Wextra', '-Wcast-qual', '-Wcast-align', '-Wshadow', - '-Wswitch-enum', '-Wdeclaration-after-statement', '-Wstrict-prototypes', - '-Wundef', '-Wpointer-arith', '-Wstrict-aliasing=1'] - endif -endif -liblz4_c_args += cc.get_supported_arguments(liblz4_debug_cflags) - -if host_machine_os == os_windows and default_library != 'static' - liblz4_c_args += '-DLZ4_DLL_EXPORT=1' -endif - -liblz4 = library('lz4', - liblz4_sources, - include_directories: liblz4_includes, - c_args: liblz4_c_args, - install: true, - version: lz4_libversion) - -liblz4_dep = declare_dependency(link_with: liblz4, - include_directories: liblz4_includes) - -pkgconfig.generate(liblz4, - name: 'lz4', - filebase: 'liblz4', - description: 'extremely fast lossless compression algorithm library', - version: lz4_libversion, - url: 'http://www.lz4.org/') - -install_headers(join_paths(lz4_root_dir, 'lib/lz4.h'), - join_paths(lz4_root_dir, 'lib/lz4hc.h'), - join_paths(lz4_root_dir, 'lib/lz4frame.h')) - -if default_library != 'shared' - install_headers(join_paths(lz4_root_dir, 'lib/lz4frame_static.h')) -endif diff --git a/ta6ob/lz4/contrib/meson/meson/meson.build b/ta6ob/lz4/contrib/meson/meson/meson.build deleted file mode 100644 index b278b7c..0000000 --- a/ta6ob/lz4/contrib/meson/meson/meson.build +++ /dev/null @@ -1,117 +0,0 @@ -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# - -cc = meson.get_compiler('c') -pkgconfig = import('pkgconfig') -c_std = get_option('c_std') -default_library = get_option('default_library') - -host_machine_os = host_machine.system() -os_windows = 'windows' -os_linux = 'linux' -os_darwin = 'darwin' -os_freebsd = 'freebsd' -os_sun = 'sunos' - -cc_id = cc.get_id() -compiler_gcc = 'gcc' -compiler_clang = 'clang' -compiler_msvc = 'msvc' - -lz4_version = meson.project_version() - -lz4_h_file = join_paths(meson.current_source_dir(), '../../../lib/lz4.h') -GetLz4LibraryVersion_py = find_program('GetLz4LibraryVersion.py', native : true) -r = run_command(GetLz4LibraryVersion_py, lz4_h_file) -if r.returncode() == 0 - lz4_version = r.stdout().strip() - message('Project version is now: @0@'.format(lz4_version)) -else - error('Cannot find project version in @0@'.format(lz4_h_file)) -endif - -lz4_libversion = lz4_version - -# ============================================================================= -# Installation directories -# ============================================================================= - -lz4_prefix = get_option('prefix') -lz4_bindir = get_option('bindir') -lz4_datadir = get_option('datadir') -lz4_mandir = get_option('mandir') -lz4_docdir = join_paths(lz4_datadir, 'doc', meson.project_name()) - -# ============================================================================= -# Project options -# ============================================================================= - -buildtype = get_option('buildtype') - -# Built-in options -use_debug = get_option('debug') - -# Custom options -debug_level = get_option('debug_level') -use_backtrace = get_option('backtrace') - -bin_programs = get_option('bin_programs') -bin_contrib = get_option('bin_contrib') -bin_tests = get_option('bin_tests') -bin_examples = get_option('bin_examples') -#feature_multi_thread = get_option('multi_thread') - -# ============================================================================= -# Dependencies -# ============================================================================= - -#libm_dep = cc.find_library('m', required: bin_tests) -#thread_dep = dependency('threads', required: feature_multi_thread) -#use_multi_thread = thread_dep.found() - -# ============================================================================= -# Compiler flags -# ============================================================================= - -add_project_arguments(['-DXXH_NAMESPACE=LZ4_'], language: 'c') - -if [compiler_gcc, compiler_clang].contains(cc_id) - common_warning_flags = [] - # Should use Meson's own --werror build option - #common_warning_flags += ['-Werror'] - if c_std == 'c89' or c_std == 'gnu89' - common_warning_flags += ['-pedantic', '-Wno-long-long', '-Wno-variadic-macros'] - elif c_std == 'c99' or c_std == 'gnu99' - common_warning_flags += ['-pedantic'] - endif - cc_compile_flags = cc.get_supported_arguments(common_warning_flags) - add_project_arguments(cc_compile_flags, language: 'c') -endif - -# ============================================================================= -# Subdirs -# ============================================================================= - -subdir('lib') - -if bin_programs - subdir('programs') -endif - -if bin_tests - subdir('tests') -endif - -if bin_contrib - subdir('contrib') -endif - -if bin_examples - subdir('examples') -endif diff --git a/ta6ob/lz4/contrib/meson/meson/programs/meson.build b/ta6ob/lz4/contrib/meson/meson/programs/meson.build deleted file mode 100644 index 705dbf5..0000000 --- a/ta6ob/lz4/contrib/meson/meson/programs/meson.build +++ /dev/null @@ -1,52 +0,0 @@ -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# - -lz4_root_dir = '../../../..' - -lz4_includes = include_directories(join_paths(lz4_root_dir, 'programs')) -lz4_sources = [join_paths(lz4_root_dir, 'programs/bench.c'), - join_paths(lz4_root_dir, 'programs/datagen.c'), - join_paths(lz4_root_dir, 'programs/lz4cli.c'), - join_paths(lz4_root_dir, 'programs/lz4io.c')] -lz4_c_args = [] - -export_dynamic_on_windows = false -# explicit backtrace enable/disable for Linux & Darwin -if not use_backtrace - lz4_c_args += '-DBACKTRACE_ENABLE=0' -elif use_debug and host_machine_os == os_windows # MinGW target - lz4_c_args += '-DBACKTRACE_ENABLE=1' - export_dynamic_on_windows = true -endif - -lz4_deps = [ liblz4_dep ] - -lz4 = executable('lz4', - lz4_sources, - include_directories: lz4_includes, - c_args: lz4_c_args, - dependencies: lz4_deps, - export_dynamic: export_dynamic_on_windows, # Since Meson 0.45.0 - install: true) - -# ============================================================================= -# Programs and manpages installing -# ============================================================================= - -install_man(join_paths(lz4_root_dir, 'programs/lz4.1')) - -InstallSymlink_py = '../InstallSymlink.py' -lz4_man1_dir = join_paths(lz4_mandir, 'man1') -bin_EXT = host_machine_os == os_windows ? '.exe' : '' -man1_EXT = meson.version().version_compare('>=0.49.0') ? '.1' : '.1.gz' - -foreach f : ['lz4c', 'lz4cat', 'unlz4'] - meson.add_install_script(InstallSymlink_py, 'lz4' + bin_EXT, f + bin_EXT, lz4_bindir) - meson.add_install_script(InstallSymlink_py, 'lz4' + man1_EXT, f + man1_EXT, lz4_man1_dir) -endforeach diff --git a/ta6ob/lz4/contrib/meson/meson/tests/meson.build b/ta6ob/lz4/contrib/meson/meson/tests/meson.build deleted file mode 100644 index 7800475..0000000 --- a/ta6ob/lz4/contrib/meson/meson/tests/meson.build +++ /dev/null @@ -1,93 +0,0 @@ -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# - -lz4_root_dir = '../../../..' -programs_dir_inc = include_directories(join_paths(lz4_root_dir, 'programs')) -lib_dir_inc = include_directories(join_paths(lz4_root_dir, 'lib')) - -# ============================================================================= -# Test flags -# ============================================================================= - -TEST_FILES = join_paths(meson.current_source_dir(), lz4_root_dir, 'tests/COPYING') -FUZZER_TIME = '-T90s' -NB_LOOPS = '-i1' - -# ============================================================================= -# Executables -# ============================================================================= - -fullbench_sources = [join_paths(lz4_root_dir, 'tests/fullbench.c')] -fullbench = executable('fullbench', - fullbench_sources, - include_directories: programs_dir_inc, - dependencies: liblz4_dep, - install: false) - -fuzzer_sources = [join_paths(lz4_root_dir, 'tests/fuzzer.c')] -fuzzer = executable('fuzzer', - fuzzer_sources, - c_args: ['-D_DEFAULT_SOURCE', '-D_BSD_SOURCE'], # since glibc 2.19 - include_directories: programs_dir_inc, - dependencies: liblz4_dep, - install: false) - -frametest_sources = [join_paths(lz4_root_dir, 'tests/frametest.c')] -frametest = executable('frametest', - frametest_sources, - include_directories: programs_dir_inc, - dependencies: liblz4_dep, - install: false) - -roundTripTest_sources = [join_paths(lz4_root_dir, 'tests/roundTripTest.c')] -roundTripTest = executable('roundTripTest', - roundTripTest_sources, - dependencies: [ liblz4_dep ], - install: false) - -datagen_sources = [join_paths(lz4_root_dir, 'tests/datagencli.c')] -datagen = executable('datagen', - datagen_sources, - objects: lz4.extract_objects(join_paths(lz4_root_dir, 'programs/datagen.c')), - include_directories: lz4_includes, - dependencies: [ liblz4_dep ], - install: false) - -checkFrame_sources = [join_paths(lz4_root_dir, 'tests/checkFrame.c')] -checkFrame = executable('checkFrame', - checkFrame_sources, - include_directories: programs_dir_inc, - dependencies: [ liblz4_dep ], - install: false) - -checkTag_sources = [join_paths(lz4_root_dir, 'tests/checkTag.c')] -checkTag = executable('checkTag', - checkTag_sources, - include_directories: lib_dir_inc, - install: false) - -# ============================================================================= -# Tests (Use "meson test --list" to list all tests) -# ============================================================================= - -# XXX: (Need TEST) These timeouts (in seconds) when running on a HDD should be -# at least six times bigger than on a SSD - -test('test-fullbench', - fullbench, - args: ['--no-prompt', NB_LOOPS, TEST_FILES], - timeout: 420) # Should enough when running on HDD -test('test-fuzzer', - fuzzer, - args: [FUZZER_TIME], - timeout: 100) -test('test-frametest', - frametest, - args: [FUZZER_TIME], - timeout: 100) diff --git a/ta6ob/lz4/contrib/meson/meson_options.txt b/ta6ob/lz4/contrib/meson/meson_options.txt deleted file mode 100644 index a409c2d..0000000 --- a/ta6ob/lz4/contrib/meson/meson_options.txt +++ /dev/null @@ -1,24 +0,0 @@ -# ############################################################################# -# Copyright (c) 2018-present lzutao -# All rights reserved. -# -# This source code is licensed under both the BSD-style license (found in the -# LICENSE file in the root directory of this source tree) and the GPLv2 (found -# in the COPYING file in the root directory of this source tree). -# ############################################################################# - -# Read guidelines from https://wiki.gnome.org/Initiatives/GnomeGoals/MesonPorting - -option('debug_level', type: 'integer', min: 0, max: 7, value: 1, - description: 'Enable run-time debug. See lib/lz4hc.c') -option('backtrace', type: 'boolean', value: false, - description: 'Display a stack backtrace when execution generates a runtime exception') - -option('bin_programs', type: 'boolean', value: false, - description: 'Enable programs build') -option('bin_tests', type: 'boolean', value: false, - description: 'Enable tests build') -option('bin_contrib', type: 'boolean', value: false, - description: 'Enable contrib build') -option('bin_examples', type: 'boolean', value: false, - description: 'Enable examples build') diff --git a/ta6ob/lz4/contrib/snap/README.md b/ta6ob/lz4/contrib/snap/README.md deleted file mode 100644 index 612d6d7..0000000 --- a/ta6ob/lz4/contrib/snap/README.md +++ /dev/null @@ -1,29 +0,0 @@ -Snap Packaging --------------- - -This directory contains the config required to generate a snap package -of lz4. Snaps are universal Linux packages that allow you to easily -build your application from any source and ship it to any Linux -distribution by publishing it to https://snapcraft.io/. A key attribute -of a snap package is that it is (ideally) confined such that it -executes within a controlled environmenti with all its dependencies -bundled with it and does not share dependencies with of from any other -package on the system (with a couple of minor exceptions). - -The basic anatomy and workflow is: - - * ensure snap.snapcraft.yaml is up-to-date e.g. with version info - - * build the snap by installing the snapcraft package and running it - - * push snap/* changes to the repo (excluding any crud generated by a build of course) - - * register yourself as owner of lz4 name in snapstore - - * publish new snap to the snap store - - * install snap by doing 'snap install lz4' on any Linux distro - - * all installed copies of lz4 will be automatically updated to your new version - -For more information on Snaps see https://docs.snapcraft.io and https://forum.snapcraft.io/ diff --git a/ta6ob/lz4/contrib/snap/snapcraft.yaml b/ta6ob/lz4/contrib/snap/snapcraft.yaml deleted file mode 100644 index 2793c0e..0000000 --- a/ta6ob/lz4/contrib/snap/snapcraft.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: lz4 -version: 1.8.4 -summary: Extremely Fast Compression algorithm -description: > - LZ4 is lossless compression algorithm, providing compression - speed > 500 MB/s per core, scalable with multi-cores CPU. It features an - extremely fast decoder, with speed in multiple GB/s per core, typically - reaching RAM speed limits on multi-core systems. - . - Speed can be tuned dynamically, selecting an "acceleration" factor which - trades compression ratio for faster speed. On the other end, a high - compression derivative, LZ4_HC, is also provided, trading CPU time for - improved compression ratio. All versions feature the same decompression - speed. - . - LZ4 is also compatible with dictionary compression, and can ingest any - input file as dictionary, including those created by Zstandard Dictionary - Builder. (note: only the final 64KB are used). - . - LZ4 library is provided as open-source software using BSD 2-Clause license. -confinement: strict -grade: stable - -apps: - lz4: - command: usr/local/bin/lz4 - plugs: [home] -parts: - lz4: - source: ../ - plugin: make diff --git a/ta6ob/lz4/doc/lz4_Block_format.md b/ta6ob/lz4/doc/lz4_Block_format.md deleted file mode 100644 index 4344e9b..0000000 --- a/ta6ob/lz4/doc/lz4_Block_format.md +++ /dev/null @@ -1,156 +0,0 @@ -LZ4 Block Format Description -============================ -Last revised: 2019-03-30. -Author : Yann Collet - - -This specification is intended for developers -willing to produce LZ4-compatible compressed data blocks -using any programming language. - -LZ4 is an LZ77-type compressor with a fixed, byte-oriented encoding. -There is no entropy encoder back-end nor framing layer. -The latter is assumed to be handled by other parts of the system -(see [LZ4 Frame format]). -This design is assumed to favor simplicity and speed. -It helps later on for optimizations, compactness, and features. - -This document describes only the block format, -not how the compressor nor decompressor actually work. -The correctness of the decompressor should not depend -on implementation details of the compressor, and vice versa. - -[LZ4 Frame format]: lz4_Frame_format.md - - - -Compressed block format ------------------------ -An LZ4 compressed block is composed of sequences. -A sequence is a suite of literals (not-compressed bytes), -followed by a match copy. - -Each sequence starts with a `token`. -The `token` is a one byte value, separated into two 4-bits fields. -Therefore each field ranges from 0 to 15. - - -The first field uses the 4 high-bits of the token. -It provides the length of literals to follow. - -If the field value is 0, then there is no literal. -If it is 15, then we need to add some more bytes to indicate the full length. -Each additional byte then represent a value from 0 to 255, -which is added to the previous value to produce a total length. -When the byte value is 255, another byte is output. -There can be any number of bytes following `token`. There is no "size limit". -(Side note : this is why a not-compressible input block is expanded by 0.4%). - -Example 1 : A literal length of 48 will be represented as : - - - 15 : value for the 4-bits High field - - 33 : (=48-15) remaining length to reach 48 - -Example 2 : A literal length of 280 will be represented as : - - - 15 : value for the 4-bits High field - - 255 : following byte is maxed, since 280-15 >= 255 - - 10 : (=280 - 15 - 255) ) remaining length to reach 280 - -Example 3 : A literal length of 15 will be represented as : - - - 15 : value for the 4-bits High field - - 0 : (=15-15) yes, the zero must be output - -Following `token` and optional length bytes, are the literals themselves. -They are exactly as numerous as previously decoded (length of literals). -It's possible that there are zero literal. - - -Following the literals is the match copy operation. - -It starts by the `offset`. -This is a 2 bytes value, in little endian format -(the 1st byte is the "low" byte, the 2nd one is the "high" byte). - -The `offset` represents the position of the match to be copied from. -1 means "current position - 1 byte". -The maximum `offset` value is 65535, 65536 cannot be coded. -Note that 0 is an invalid value, not used. - -Then we need to extract the `matchlength`. -For this, we use the second token field, the low 4-bits. -Value, obviously, ranges from 0 to 15. -However here, 0 means that the copy operation will be minimal. -The minimum length of a match, called `minmatch`, is 4. -As a consequence, a 0 value means 4 bytes, and a value of 15 means 19+ bytes. -Similar to literal length, on reaching the highest possible value (15), -we output additional bytes, one at a time, with values ranging from 0 to 255. -They are added to total to provide the final match length. -A 255 value means there is another byte to read and add. -There is no limit to the number of optional bytes that can be output this way. -(This points towards a maximum achievable compression ratio of about 250). - -Decoding the `matchlength` reaches the end of current sequence. -Next byte will be the start of another sequence. -But before moving to next sequence, -it's time to use the decoded match position and length. -The decoder copies `matchlength` bytes from match position to current position. - -In some cases, `matchlength` is larger than `offset`. -Therefore, `match_pos + matchlength > current_pos`, -which means that later bytes to copy are not yet decoded. -This is called an "overlap match", and must be handled with special care. -A common case is an offset of 1, -meaning the last byte is repeated `matchlength` times. - - -End of block restrictions ------------------------ -There are specific rules required to terminate a block. - -1. The last sequence contains only literals. - The block ends right after them. -2. The last 5 bytes of input are always literals. - Therefore, the last sequence contains at least 5 bytes. - - Special : if input is smaller than 5 bytes, - there is only one sequence, it contains the whole input as literals. - Empty input can be represented with a zero byte, - interpreted as a final token without literal and without a match. -3. The last match must start at least 12 bytes before the end of block. - The last match is part of the penultimate sequence. - It is followed by the last sequence, which contains only literals. - - Note that, as a consequence, - an independent block < 13 bytes cannot be compressed, - because the match must copy "something", - so it needs at least one prior byte. - - When a block can reference data from another block, - it can start immediately with a match and no literal, - so a block of 12 bytes can be compressed. - -When a block does not respect these end conditions, -a conformant decoder is allowed to reject the block as incorrect. - -These rules are in place to ensure that a conformant decoder -can be designed for speed, issuing speculatively instructions, -while never reading nor writing beyond provided I/O buffers. - - -Additional notes ------------------------ -If the decoder will decompress data from an external source, -it is recommended to ensure that the decoder will not be vulnerable to -buffer overflow manipulations. -Always ensure that read and write operations -remain within the limits of provided buffers. -Test the decoder with fuzzers -to ensure it's resilient to improbable combinations. - -The format makes no assumption nor limits to the way the compressor -searches and selects matches within the source data block. -Multiple techniques can be considered, -featuring distinct time / performance trade offs. -As long as the format is respected, -the result will be compatible and decodable by any compliant decoder. -An upper compression limit can be reached, -using a technique called "full optimal parsing", at high cpu cost. diff --git a/ta6ob/lz4/doc/lz4_Frame_format.md b/ta6ob/lz4/doc/lz4_Frame_format.md deleted file mode 100644 index 7e08841..0000000 --- a/ta6ob/lz4/doc/lz4_Frame_format.md +++ /dev/null @@ -1,433 +0,0 @@ -LZ4 Frame Format Description -============================ - -### Notices - -Copyright (c) 2013-2015 Yann Collet - -Permission is granted to copy and distribute this document -for any purpose and without charge, -including translations into other languages -and incorporation into compilations, -provided that the copyright notice and this notice are preserved, -and that any substantive changes or deletions from the original -are clearly marked. -Distribution of this document is unlimited. - -### Version - -1.6.2 (12/08/2020) - - -Introduction ------------- - -The purpose of this document is to define a lossless compressed data format, -that is independent of CPU type, operating system, -file system and character set, suitable for -File compression, Pipe and streaming compression -using the [LZ4 algorithm](http://www.lz4.org). - -The data can be produced or consumed, -even for an arbitrarily long sequentially presented input data stream, -using only an a priori bounded amount of intermediate storage, -and hence can be used in data communications. -The format uses the LZ4 compression method, -and optional [xxHash-32 checksum method](https://github.com/Cyan4973/xxHash), -for detection of data corruption. - -The data format defined by this specification -does not attempt to allow random access to compressed data. - -This specification is intended for use by implementers of software -to compress data into LZ4 format and/or decompress data from LZ4 format. -The text of the specification assumes a basic background in programming -at the level of bits and other primitive data representations. - -Unless otherwise indicated below, -a compliant compressor must produce data sets -that conform to the specifications presented here. -It doesn’t need to support all options though. - -A compliant decompressor must be able to decompress -at least one working set of parameters -that conforms to the specifications presented here. -It may also ignore checksums. -Whenever it does not support a specific parameter within the compressed stream, -it must produce a non-ambiguous error code -and associated error message explaining which parameter is unsupported. - - -General Structure of LZ4 Frame format -------------------------------------- - -| MagicNb | F. Descriptor | Block | (...) | EndMark | C. Checksum | -|:-------:|:-------------:| ----- | ----- | ------- | ----------- | -| 4 bytes | 3-15 bytes | | | 4 bytes | 0-4 bytes | - -__Magic Number__ - -4 Bytes, Little endian format. -Value : 0x184D2204 - -__Frame Descriptor__ - -3 to 15 Bytes, to be detailed in its own paragraph, -as it is the most important part of the spec. - -The combined _Magic_Number_ and _Frame_Descriptor_ fields are sometimes -called ___LZ4 Frame Header___. Its size varies between 7 and 19 bytes. - -__Data Blocks__ - -To be detailed in its own paragraph. -That’s where compressed data is stored. - -__EndMark__ - -The flow of blocks ends when the last data block is followed by -the 32-bit value `0x00000000`. - -__Content Checksum__ - -_Content_Checksum_ verify that the full content has been decoded correctly. -The content checksum is the result of [xxHash-32 algorithm] -digesting the original (decoded) data as input, and a seed of zero. -Content checksum is only present when its associated flag -is set in the frame descriptor. -Content Checksum validates the result, -that all blocks were fully transmitted in the correct order and without error, -and also that the encoding/decoding process itself generated no distortion. -Its usage is recommended. - -The combined _EndMark_ and _Content_Checksum_ fields might sometimes be -referred to as ___LZ4 Frame Footer___. Its size varies between 4 and 8 bytes. - -__Frame Concatenation__ - -In some circumstances, it may be preferable to append multiple frames, -for example in order to add new data to an existing compressed file -without re-framing it. - -In such case, each frame has its own set of descriptor flags. -Each frame is considered independent. -The only relation between frames is their sequential order. - -The ability to decode multiple concatenated frames -within a single stream or file -is left outside of this specification. -As an example, the reference lz4 command line utility behavior is -to decode all concatenated frames in their sequential order. - - -Frame Descriptor ----------------- - -| FLG | BD | (Content Size) | (Dictionary ID) | HC | -| ------- | ------- |:--------------:|:---------------:| ------- | -| 1 byte | 1 byte | 0 - 8 bytes | 0 - 4 bytes | 1 byte | - -The descriptor uses a minimum of 3 bytes, -and up to 15 bytes depending on optional parameters. - -__FLG byte__ - -| BitNb | 7-6 | 5 | 4 | 3 | 2 | 1 | 0 | -| ------- |-------|-------|----------|------|----------|----------|------| -|FieldName|Version|B.Indep|B.Checksum|C.Size|C.Checksum|*Reserved*|DictID| - - -__BD byte__ - -| BitNb | 7 | 6-5-4 | 3-2-1-0 | -| ------- | -------- | ------------- | -------- | -|FieldName|*Reserved*| Block MaxSize |*Reserved*| - -In the tables, bit 7 is highest bit, while bit 0 is lowest. - -__Version Number__ - -2-bits field, must be set to `01`. -Any other value cannot be decoded by this version of the specification. -Other version numbers will use different flag layouts. - -__Block Independence flag__ - -If this flag is set to “1â€, blocks are independent. -If this flag is set to “0â€, each block depends on previous ones -(up to LZ4 window size, which is 64 KB). -In such case, it’s necessary to decode all blocks in sequence. - -Block dependency improves compression ratio, especially for small blocks. -On the other hand, it makes random access or multi-threaded decoding impossible. - -__Block checksum flag__ - -If this flag is set, each data block will be followed by a 4-bytes checksum, -calculated by using the xxHash-32 algorithm on the raw (compressed) data block. -The intention is to detect data corruption (storage or transmission errors) -immediately, before decoding. -Block checksum usage is optional. - -__Content Size flag__ - -If this flag is set, the uncompressed size of data included within the frame -will be present as an 8 bytes unsigned little endian value, after the flags. -Content Size usage is optional. - -__Content checksum flag__ - -If this flag is set, a 32-bits content checksum will be appended -after the EndMark. - -__Dictionary ID flag__ - -If this flag is set, a 4-bytes Dict-ID field will be present, -after the descriptor flags and the Content Size. - -__Block Maximum Size__ - -This information is useful to help the decoder allocate memory. -Size here refers to the original (uncompressed) data size. -Block Maximum Size is one value among the following table : - -| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | -| --- | --- | --- | --- | ----- | ------ | ---- | ---- | -| N/A | N/A | N/A | N/A | 64 KB | 256 KB | 1 MB | 4 MB | - -The decoder may refuse to allocate block sizes above any system-specific size. -Unused values may be used in a future revision of the spec. -A decoder conformant with the current version of the spec -is only able to decode block sizes defined in this spec. - -__Reserved bits__ - -Value of reserved bits **must** be 0 (zero). -Reserved bit might be used in a future version of the specification, -typically enabling new optional features. -When this happens, a decoder respecting the current specification version -shall not be able to decode such a frame. - -__Content Size__ - -This is the original (uncompressed) size. -This information is optional, and only present if the associated flag is set. -Content size is provided using unsigned 8 Bytes, for a maximum of 16 Exabytes. -Format is Little endian. -This value is informational, typically for display or memory allocation. -It can be skipped by a decoder, or used to validate content correctness. - -__Dictionary ID__ - -Dict-ID is only present if the associated flag is set. -It's an unsigned 32-bits value, stored using little-endian convention. -A dictionary is useful to compress short input sequences. -The compressor can take advantage of the dictionary context -to encode the input in a more compact manner. -It works as a kind of “known prefix†which is used by -both the compressor and the decompressor to “warm-up†reference tables. - -The decompressor can use Dict-ID identifier to determine -which dictionary must be used to correctly decode data. -The compressor and the decompressor must use exactly the same dictionary. -It's presumed that the 32-bits dictID uniquely identifies a dictionary. - -Within a single frame, a single dictionary can be defined. -When the frame descriptor defines independent blocks, -each block will be initialized with the same dictionary. -If the frame descriptor defines linked blocks, -the dictionary will only be used once, at the beginning of the frame. - -__Header Checksum__ - -One-byte checksum of combined descriptor fields, including optional ones. -The value is the second byte of `xxh32()` : ` (xxh32()>>8) & 0xFF ` -using zero as a seed, and the full Frame Descriptor as an input -(including optional fields when they are present). -A wrong checksum indicates an error in the descriptor. -Header checksum is informational and can be skipped. - - -Data Blocks ------------ - -| Block Size | data | (Block Checksum) | -|:----------:| ------ |:----------------:| -| 4 bytes | | 0 - 4 bytes | - - -__Block Size__ - -This field uses 4-bytes, format is little-endian. - -If the highest bit is set (`1`), the block is uncompressed. - -If the highest bit is not set (`0`), the block is LZ4-compressed, -using the [LZ4 block format specification](https://github.com/lz4/lz4/blob/dev/doc/lz4_Block_format.md). - -All other bits give the size, in bytes, of the data section. -The size does not include the block checksum if present. - -_Block_Size_ shall never be larger than _Block_Maximum_Size_. -Such an outcome could potentially happen for non-compressible sources. -In such a case, such data block must be passed using uncompressed format. - -A value of `0x00000000` is invalid, and signifies an _EndMark_ instead. -Note that this is different from a value of `0x80000000` (highest bit set), -which is an uncompressed block of size 0 (empty), -which is valid, and therefore doesn't end a frame. -Note that, if _Block_checksum_ is enabled, -even an empty block must be followed by a 32-bit block checksum. - -__Data__ - -Where the actual data to decode stands. -It might be compressed or not, depending on previous field indications. - -When compressed, the data must respect the [LZ4 block format specification](https://github.com/lz4/lz4/blob/dev/doc/lz4_Block_format.md). - -Note that a block is not necessarily full. -Uncompressed size of data can be any size __up to__ _Block_Maximum_Size_, -so it may contain less data than the maximum block size. - -__Block checksum__ - -Only present if the associated flag is set. -This is a 4-bytes checksum value, in little endian format, -calculated by using the [xxHash-32 algorithm] on the __raw__ (undecoded) data block, -and a seed of zero. -The intention is to detect data corruption (storage or transmission errors) -before decoding. - -_Block_checksum_ can be cumulative with _Content_checksum_. - -[xxHash-32 algorithm]: https://github.com/Cyan4973/xxHash/blob/release/doc/xxhash_spec.md - - -Skippable Frames ----------------- - -| Magic Number | Frame Size | User Data | -|:------------:|:----------:| --------- | -| 4 bytes | 4 bytes | | - -Skippable frames allow the integration of user-defined data -into a flow of concatenated frames. -Its design is pretty straightforward, -with the sole objective to allow the decoder to quickly skip -over user-defined data and continue decoding. - -For the purpose of facilitating identification, -it is discouraged to start a flow of concatenated frames with a skippable frame. -If there is a need to start such a flow with some user data -encapsulated into a skippable frame, -it’s recommended to start with a zero-byte LZ4 frame -followed by a skippable frame. -This will make it easier for file type identifiers. - - -__Magic Number__ - -4 Bytes, Little endian format. -Value : 0x184D2A5X, which means any value from 0x184D2A50 to 0x184D2A5F. -All 16 values are valid to identify a skippable frame. - -__Frame Size__ - -This is the size, in bytes, of the following User Data -(without including the magic number nor the size field itself). -4 Bytes, Little endian format, unsigned 32-bits. -This means User Data can’t be bigger than (2^32-1) Bytes. - -__User Data__ - -User Data can be anything. Data will just be skipped by the decoder. - - -Legacy frame ------------- - -The Legacy frame format was defined into the initial versions of “LZ4Demoâ€. -Newer compressors should not use this format anymore, as it is too restrictive. - -Main characteristics of the legacy format : - -- Fixed block size : 8 MB. -- All blocks must be completely filled, except the last one. -- All blocks are always compressed, even when compression is detrimental. -- The last block is detected either because - it is followed by the “EOF†(End of File) mark, - or because it is followed by a known Frame Magic Number. -- No checksum -- Convention is Little endian - -| MagicNb | B.CSize | CData | B.CSize | CData | (...) | EndMark | -| ------- | ------- | ----- | ------- | ----- | ------- | ------- | -| 4 bytes | 4 bytes | CSize | 4 bytes | CSize | x times | EOF | - - -__Magic Number__ - -4 Bytes, Little endian format. -Value : 0x184C2102 - -__Block Compressed Size__ - -This is the size, in bytes, of the following compressed data block. -4 Bytes, Little endian format. - -__Data__ - -Where the actual compressed data stands. -Data is always compressed, even when compression is detrimental. - -__EndMark__ - -End of legacy frame is implicit only. -It must be followed by a standard EOF (End Of File) signal, -wether it is a file or a stream. - -Alternatively, if the frame is followed by a valid Frame Magic Number, -it is considered completed. -This policy makes it possible to concatenate legacy frames. - -Any other value will be interpreted as a block size, -and trigger an error if it does not fit within acceptable range. - - -Version changes ---------------- - -1.6.2 : clarifies specification of _EndMark_ - -1.6.1 : introduced terms "LZ4 Frame Header" and "LZ4 Frame Footer" - -1.6.0 : restored Dictionary ID field in Frame header - -1.5.1 : changed document format to MarkDown - -1.5 : removed Dictionary ID from specification - -1.4.1 : changed wording from “stream†to “frame†- -1.4 : added skippable streams, re-added stream checksum - -1.3 : modified header checksum - -1.2 : reduced choice of “block sizeâ€, to postpone decision on “dynamic size of BlockSize Fieldâ€. - -1.1 : optional fields are now part of the descriptor - -1.0 : changed “block size†specification, adding a compressed/uncompressed flag - -0.9 : reduced scale of “block maximum size†table - -0.8 : removed : high compression flag - -0.7 : removed : stream checksum - -0.6 : settled : stream size uses 8 bytes, endian convention is little endian - -0.5: added copyright notice - -0.4 : changed format to Google Doc compatible OpenDocument diff --git a/ta6ob/lz4/doc/lz4_manual.html b/ta6ob/lz4/doc/lz4_manual.html deleted file mode 100644 index 47fe18d..0000000 --- a/ta6ob/lz4/doc/lz4_manual.html +++ /dev/null @@ -1,597 +0,0 @@ - - - -1.9.3 Manual - - -

1.9.3 Manual

-
-

Contents

-
    -
  1. Introduction
  2. -
  3. Version
  4. -
  5. Tuning parameter
  6. -
  7. Simple Functions
  8. -
  9. Advanced Functions
  10. -
  11. Streaming Compression Functions
  12. -
  13. Streaming Decompression Functions
  14. -
  15. Experimental section
  16. -
  17. Private Definitions
  18. -
  19. Obsolete Functions
  20. -
-
-

Introduction

-  LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core,
-  scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
-  multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
-
-  The LZ4 compression library provides in-memory compression and decompression functions.
-  It gives full buffer control to user.
-  Compression can be done in:
-    - a single step (described as Simple Functions)
-    - a single step, reusing a context (described in Advanced Functions)
-    - unbounded multiple steps (described as Streaming compression)
-
-  lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).
-  Decompressing such a compressed block requires additional metadata.
-  Exact metadata depends on exact decompression function.
-  For the typical case of LZ4_decompress_safe(),
-  metadata includes block's compressed size, and maximum bound of decompressed size.
-  Each application is free to encode and pass such metadata in whichever way it wants.
-
-  lz4.h only handle blocks, it can not generate Frames.
-
-  Blocks are different from Frames (doc/lz4_Frame_format.md).
-  Frames bundle both blocks and metadata in a specified manner.
-  Embedding metadata is required for compressed data to be self-contained and portable.
-  Frame format is delivered through a companion API, declared in lz4frame.h.
-  The `lz4` CLI can only manage frames.
-
- -

Version


-
-
int LZ4_versionNumber (void);  /**< library version number; useful to check dll version */
-

-
const char* LZ4_versionString (void);   /**< library version string; useful to check dll version */
-

-

Tuning parameter


-
-
#ifndef LZ4_MEMORY_USAGE
-# define LZ4_MEMORY_USAGE 14
-#endif
-

Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) - Increasing memory usage improves compression ratio. - Reduced memory usage may improve speed, thanks to better cache locality. - Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache - -


- -

Simple Functions


-
-
int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
-

Compresses 'srcSize' bytes from buffer 'src' - into already allocated 'dst' buffer of size 'dstCapacity'. - Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize). - It also runs faster, so it's a recommended setting. - If the function cannot compress 'src' into a more limited 'dst' budget, - compression stops *immediately*, and the function result is zero. - In which case, 'dst' content is undefined (invalid). - srcSize : max supported value is LZ4_MAX_INPUT_SIZE. - dstCapacity : size of buffer 'dst' (which must be already allocated) - @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity) - or 0 if compression fails - Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer). - -


- -
int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
-

compressedSize : is the exact complete size of the compressed block. - dstCapacity : is the size of destination buffer (which must be already allocated), presumed an upper bound of decompressed size. - @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity) - If destination buffer is not large enough, decoding will stop and output an error code (negative value). - If the source stream is detected malformed, the function will stop decoding and return a negative result. - Note 1 : This function is protected against malicious data packets : - it will never writes outside 'dst' buffer, nor read outside 'source' buffer, - even if the compressed block is maliciously modified to order the decoder to do these actions. - In such case, the decoder stops immediately, and considers the compressed block malformed. - Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them. - The implementation is free to send / store / derive this information in whichever way is most beneficial. - If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead. - -


- -

Advanced Functions


-
-
int LZ4_compressBound(int inputSize);
-

Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) - This function is primarily useful for memory allocation purposes (destination buffer size). - Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example). - Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize) - inputSize : max supported value is LZ4_MAX_INPUT_SIZE - return : maximum output size in a "worst case" scenario - or 0, if input size is incorrect (too large or negative) -


- -
int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
-

Same as LZ4_compress_default(), but allows selection of "acceleration" factor. - The larger the acceleration value, the faster the algorithm, but also the lesser the compression. - It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed. - An acceleration value of "1" is the same as regular LZ4_compress_default() - Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c). - Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c). -


- -
int LZ4_sizeofState(void);
-int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
-

Same as LZ4_compress_fast(), using an externally allocated memory space for its state. - Use LZ4_sizeofState() to know how much memory must be allocated, - and allocate it on 8-bytes boundaries (using `malloc()` typically). - Then, provide this buffer as `void* state` to compression function. - -


- -
int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
-

Reverse the logic : compresses as much data as possible from 'src' buffer - into already allocated buffer 'dst', of size >= 'targetDestSize'. - This function either compresses the entire 'src' content into 'dst' if it's large enough, - or fill 'dst' buffer completely with as much data as possible from 'src'. - note: acceleration parameter is fixed to "default". - - *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'. - New value is necessarily <= input value. - @return : Nb bytes written into 'dst' (necessarily <= targetDestSize) - or 0 if compression fails. - - Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+): - the produced compressed content could, in specific circumstances, - require to be decompressed into a destination buffer larger - by at least 1 byte than the content to decompress. - If an application uses `LZ4_compress_destSize()`, - it's highly recommended to update liblz4 to v1.9.2 or better. - If this can't be done or ensured, - the receiving decompression function should provide - a dstCapacity which is > decompressedSize, by at least 1 byte. - See https://github.com/lz4/lz4/issues/859 for details - -


- -
int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
-

Decompress an LZ4 compressed block, of size 'srcSize' at position 'src', - into destination buffer 'dst' of size 'dstCapacity'. - Up to 'targetOutputSize' bytes will be decoded. - The function stops decoding on reaching this objective. - This can be useful to boost performance - whenever only the beginning of a block is required. - - @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize) - If source stream is detected malformed, function returns a negative result. - - Note 1 : @return can be < targetOutputSize, if compressed block contains less data. - - Note 2 : targetOutputSize must be <= dstCapacity - - Note 3 : this function effectively stops decoding on reaching targetOutputSize, - so dstCapacity is kind of redundant. - This is because in older versions of this function, - decoding operation would still write complete sequences. - Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize, - it could write more bytes, though only up to dstCapacity. - Some "margin" used to be required for this operation to work properly. - Thankfully, this is no longer necessary. - The function nonetheless keeps the same signature, in an effort to preserve API compatibility. - - Note 4 : If srcSize is the exact size of the block, - then targetOutputSize can be any value, - including larger than the block's decompressed size. - The function will, at most, generate block's decompressed size. - - Note 5 : If srcSize is _larger_ than block's compressed size, - then targetOutputSize **MUST** be <= block's decompressed size. - Otherwise, *silent corruption will occur*. - -


- -

Streaming Compression Functions


-
-
void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
-

Use this to prepare an LZ4_stream_t for a new chain of dependent blocks - (e.g., LZ4_compress_fast_continue()). - - An LZ4_stream_t must be initialized once before usage. - This is automatically done when created by LZ4_createStream(). - However, should the LZ4_stream_t be simply declared on stack (for example), - it's necessary to initialize it first, using LZ4_initStream(). - - After init, start any new stream with LZ4_resetStream_fast(). - A same LZ4_stream_t can be re-used multiple times consecutively - and compress multiple streams, - provided that it starts each new stream with LZ4_resetStream_fast(). - - LZ4_resetStream_fast() is much faster than LZ4_initStream(), - but is not compatible with memory regions containing garbage data. - - Note: it's only useful to call LZ4_resetStream_fast() - in the context of streaming compression. - The *extState* functions perform their own resets. - Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive. - -


- -
int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
-

Use this function to reference a static dictionary into LZ4_stream_t. - The dictionary must remain available during compression. - LZ4_loadDict() triggers a reset, so any previous data will be forgotten. - The same dictionary will have to be loaded on decompression side for successful decoding. - Dictionary are useful for better compression of small data (KB range). - While LZ4 accept any input as dictionary, - results are generally better when using Zstandard's Dictionary Builder. - Loading a size of 0 is allowed, and is the same as reset. - @return : loaded dictionary size, in bytes (necessarily <= 64 KB) - -


- -
int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
-

Compress 'src' content using data from previously compressed blocks, for better compression ratio. - 'dst' buffer must be already allocated. - If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. - - @return : size of compressed block - or 0 if there is an error (typically, cannot fit into 'dst'). - - Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block. - Each block has precise boundaries. - Each block must be decompressed separately, calling LZ4_decompress_*() with relevant metadata. - It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together. - - Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory ! - - Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB. - Make sure that buffers are separated, by at least one byte. - This construction ensures that each block only depends on previous block. - - Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB. - - Note 5 : After an error, the stream status is undefined (invalid), it can only be reset or freed. - -


- -
int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);
-

If last 64KB data cannot be guaranteed to remain available at its current memory location, - save it into a safer place (char* safeBuffer). - This is schematically equivalent to a memcpy() followed by LZ4_loadDict(), - but is much faster, because LZ4_saveDict() doesn't need to rebuild tables. - @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error. - -


- -

Streaming Decompression Functions

  Bufferless synchronous API
-
- -
LZ4_streamDecode_t* LZ4_createStreamDecode(void);
-int                 LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
-

creation / destruction of streaming decompression tracking context. - A tracking context can be re-used multiple times. - -


- -
int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
-

An LZ4_streamDecode_t context can be allocated once and re-used multiple times. - Use this function to start decompression of a new stream of blocks. - A dictionary can optionally be set. Use NULL or size 0 for a reset order. - Dictionary is presumed stable : it must remain accessible and unmodified during next decompression. - @return : 1 if OK, 0 if error - -


- -
int LZ4_decoderRingBufferSize(int maxBlockSize);
-#define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize))  /* for static allocation; maxBlockSize presumed valid */
-

Note : in a ring buffer scenario (optional), - blocks are presumed decompressed next to each other - up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize), - at which stage it resumes from beginning of ring buffer. - When setting such a ring buffer for streaming decompression, - provides the minimum size of this ring buffer - to be compatible with any source respecting maxBlockSize condition. - @return : minimum ring buffer size, - or 0 if there is an error (invalid maxBlockSize). - -


- -
int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity);
-

These decoding functions allow decompression of consecutive blocks in "streaming" mode. - A block is an unsplittable entity, it must be presented entirely to a decompression function. - Decompression functions only accepts one block at a time. - The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded. - If less than 64KB of data has been decoded, all the data must be present. - - Special : if decompression side sets a ring buffer, it must respect one of the following conditions : - - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize). - maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes. - In which case, encoding and decoding buffers do not need to be synchronized. - Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize. - - Synchronized mode : - Decompression buffer size is _exactly_ the same as compression buffer size, - and follows exactly same update rule (block boundaries at same positions), - and decoding function is provided with exact decompressed size of each block (exception for last block of the stream), - _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB). - - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes. - In which case, encoding and decoding buffers do not need to be synchronized, - and encoding ring buffer can have any size, including small ones ( < 64 KB). - - Whenever these conditions are not possible, - save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression, - then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block. -


- -
int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize);
-

These decoding functions work the same as - a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue() - They are stand-alone, and don't need an LZ4_streamDecode_t structure. - Dictionary is presumed stable : it must remain accessible and unmodified during decompression. - Performance tip : Decompression speed can be substantially increased - when dst == dictStart + dictSize. - -


- -

Experimental section

- Symbols declared in this section must be considered unstable. Their
- signatures or semantics may change, or they may be removed altogether in the
- future. They are therefore only safe to depend on when the caller is
- statically linked against the library.
-
- To protect against unsafe usage, not only are the declarations guarded,
- the definitions are hidden by default
- when building LZ4 as a shared/dynamic library.
-
- In order to access these declarations,
- define LZ4_STATIC_LINKING_ONLY in your application
- before including LZ4's headers.
-
- In order to make their implementations accessible dynamically, you must
- define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.
-
- -
LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
-

A variant of LZ4_compress_fast_extState(). - - Using this variant avoids an expensive initialization step. - It is only safe to call if the state buffer is known to be correctly initialized already - (see above comment on LZ4_resetStream_fast() for a definition of "correctly initialized"). - From a high level, the difference is that - this function initializes the provided state with a call to something like LZ4_resetStream_fast() - while LZ4_compress_fast_extState() starts with a call to LZ4_resetStream(). - -


- -
LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream);
-

This is an experimental API that allows - efficient use of a static dictionary many times. - - Rather than re-loading the dictionary buffer into a working context before - each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a - working LZ4_stream_t, this function introduces a no-copy setup mechanism, - in which the working stream references the dictionary stream in-place. - - Several assumptions are made about the state of the dictionary stream. - Currently, only streams which have been prepared by LZ4_loadDict() should - be expected to work. - - Alternatively, the provided dictionaryStream may be NULL, - in which case any existing dictionary stream is unset. - - If a dictionary is provided, it replaces any pre-existing stream history. - The dictionary contents are the only history that can be referenced and - logically immediately precede the data compressed in the first subsequent - compression call. - - The dictionary will only remain attached to the working stream through the - first compression call, at the end of which it is cleared. The dictionary - stream (and source buffer) must remain in-place / accessible / unchanged - through the completion of the first compression call on the stream. - -


- -

- It's possible to have input and output sharing the same buffer, - for highly contrained memory environments. - In both cases, it requires input to lay at the end of the buffer, - and decompression to start at beginning of the buffer. - Buffer size must feature some margin, hence be larger than final size. - - |<------------------------buffer--------------------------------->| - |<-----------compressed data--------->| - |<-----------decompressed size------------------>| - |<----margin---->| - - This technique is more useful for decompression, - since decompressed size is typically larger, - and margin is short. - - In-place decompression will work inside any buffer - which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize). - This presumes that decompressedSize > compressedSize. - Otherwise, it means compression actually expanded data, - and it would be more efficient to store such data with a flag indicating it's not compressed. - This can happen when data is not compressible (already compressed, or encrypted). - - For in-place compression, margin is larger, as it must be able to cope with both - history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX, - and data expansion, which can happen when input is not compressible. - As a consequence, buffer size requirements are much higher, - and memory savings offered by in-place compression are more limited. - - There are ways to limit this cost for compression : - - Reduce history size, by modifying LZ4_DISTANCE_MAX. - Note that it is a compile-time constant, so all compressions will apply this limit. - Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX, - so it's a reasonable trick when inputs are known to be small. - - Require the compressor to deliver a "maximum compressed size". - This is the `dstCapacity` parameter in `LZ4_compress*()`. - When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail, - in which case, the return code will be 0 (zero). - The caller must be ready for these cases to happen, - and typically design a backup scheme to send data uncompressed. - The combination of both techniques can significantly reduce - the amount of margin required for in-place compression. - - In-place compression can work in any buffer - which size is >= (maxCompressedSize) - with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success. - LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX, - so it's possible to reduce memory requirements by playing with them. - -


- -
#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize)   ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize))  /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */
-

-
#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize)   ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN)  /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */
-

-

Private Definitions

- Do not use these definitions directly.
- They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
- Accessing members will expose user code to API and/or ABI break in future versions of the library.
-
- -
typedef struct {
-    const LZ4_byte* externalDict;
-    size_t extDictSize;
-    const LZ4_byte* prefixEnd;
-    size_t prefixSize;
-} LZ4_streamDecode_t_internal;
-

-
#define LZ4_STREAMSIZE       16416  /* static size, for inter-version compatibility */
-#define LZ4_STREAMSIZE_VOIDP (LZ4_STREAMSIZE / sizeof(void*))
-union LZ4_stream_u {
-    void* table[LZ4_STREAMSIZE_VOIDP];
-    LZ4_stream_t_internal internal_donotuse;
-}; /* previously typedef'd to LZ4_stream_t */
-

Do not use below internal definitions directly ! - Declare or allocate an LZ4_stream_t instead. - LZ4_stream_t can also be created using LZ4_createStream(), which is recommended. - The structure definition can be convenient for static allocation - (on stack, or as part of larger structure). - Init this structure with LZ4_initStream() before first use. - note : only use this definition in association with static linking ! - this definition is not API/ABI safe, and may change in future versions. - -


- -
LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
-

An LZ4_stream_t structure must be initialized at least once. - This is automatically done when invoking LZ4_createStream(), - but it's not when the structure is simply declared on stack (for example). - - Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t. - It can also initialize any arbitrary buffer of sufficient size, - and will @return a pointer of proper type upon initialization. - - Note : initialization fails if size and alignment conditions are not respected. - In which case, the function will @return NULL. - Note2: An LZ4_stream_t structure guarantees correct alignment and size. - Note3: Before v1.9.0, use LZ4_resetStream() instead - -


- -
#define LZ4_STREAMDECODESIZE_U64 (4 + ((sizeof(void*)==16) ? 2 : 0) /*AS-400*/ )
-#define LZ4_STREAMDECODESIZE     (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
-union LZ4_streamDecode_u {
-    unsigned long long table[LZ4_STREAMDECODESIZE_U64];
-    LZ4_streamDecode_t_internal internal_donotuse;
-} ;   /* previously typedef'd to LZ4_streamDecode_t */
-

information structure to track an LZ4 stream during decompression. - init this structure using LZ4_setStreamDecode() before first use. - note : only use in association with static linking ! - this definition is not API/ABI safe, - and may change in a future version ! - -


- -

Obsolete Functions


-
-
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
-#  define LZ4_DEPRECATED(message)   /* disable deprecation warnings */
-#else
-#  if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
-#    define LZ4_DEPRECATED(message) [[deprecated(message)]]
-#  elif defined(_MSC_VER)
-#    define LZ4_DEPRECATED(message) __declspec(deprecated(message))
-#  elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))
-#    define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
-#  elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)
-#    define LZ4_DEPRECATED(message) __attribute__((deprecated))
-#  else
-#    pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler")
-#    define LZ4_DEPRECATED(message)   /* disabled */
-#  endif
-#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
-

- Deprecated functions make the compiler generate a warning when invoked. - This is meant to invite users to update their source code. - Should deprecation warnings be a problem, it is generally possible to disable them, - typically with -Wno-deprecated-declarations for gcc - or _CRT_SECURE_NO_WARNINGS in Visual. - - Another method is to define LZ4_DISABLE_DEPRECATE_WARNINGS - before including the header file. - -


- -
LZ4_DEPRECATED("use LZ4_compress_default() instead")       LZ4LIB_API int LZ4_compress               (const char* src, char* dest, int srcSize);
-LZ4_DEPRECATED("use LZ4_compress_default() instead")       LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize);
-LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState               (void* state, const char* source, char* dest, int inputSize);
-LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
-LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue                (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
-LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue  (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
-


- -
LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
-LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
-


- -
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
-LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
-


- -
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead")
-int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
-LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead")
-int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
-LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead")
-int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);
-

These functions used to be faster than LZ4_decompress_safe(), - but this is no longer the case. They are now slower. - This is because LZ4_decompress_fast() doesn't know the input size, - and therefore must progress more cautiously into the input buffer to not read beyond the end of block. - On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability. - As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated. - - The last remaining LZ4_decompress_fast() specificity is that - it can decompress a block without knowing its compressed size. - Such functionality can be achieved in a more secure manner - by employing LZ4_decompress_safe_partial(). - - Parameters: - originalSize : is the uncompressed size to regenerate. - `dst` must be already allocated, its size must be >= 'originalSize' bytes. - @return : number of bytes read from source buffer (== compressed size). - The function expects to finish at block's end exactly. - If the source stream is detected malformed, the function stops decoding and returns a negative result. - note : LZ4_decompress_fast*() requires originalSize. Thanks to this information, it never writes past the output buffer. - However, since it doesn't know its 'src' size, it may read an unknown amount of input, past input buffer bounds. - Also, since match offsets are not validated, match reads from 'src' may underflow too. - These issues never happen if input (compressed) data is correct. - But they may happen if input data is invalid (error or intentional tampering). - As a consequence, use these functions in trusted environments with trusted data **only**. - -


- -
void LZ4_resetStream (LZ4_stream_t* streamPtr);
-

An LZ4_stream_t structure must be initialized at least once. - This is done with LZ4_initStream(), or LZ4_resetStream(). - Consider switching to LZ4_initStream(), - invoking LZ4_resetStream() will trigger deprecation warnings in the future. - -


- - - diff --git a/ta6ob/lz4/doc/lz4frame_manual.html b/ta6ob/lz4/doc/lz4frame_manual.html deleted file mode 100644 index 2758306..0000000 --- a/ta6ob/lz4/doc/lz4frame_manual.html +++ /dev/null @@ -1,396 +0,0 @@ - - - -1.9.3 Manual - - -

1.9.3 Manual

-
-

Contents

-
    -
  1. Introduction
  2. -
  3. Compiler specifics
  4. -
  5. Error management
  6. -
  7. Frame compression types
  8. -
  9. Simple compression function
  10. -
  11. Advanced compression functions
  12. -
  13. Resource Management
  14. -
  15. Compression
  16. -
  17. Decompression functions
  18. -
  19. Streaming decompression functions
  20. -
  21. Bulk processing dictionary API
  22. -
-
-

Introduction

-  lz4frame.h implements LZ4 frame specification (doc/lz4_Frame_format.md).
-  lz4frame.h provides frame compression functions that take care
-  of encoding standard metadata alongside LZ4-compressed blocks.
-
- -

Compiler specifics


-
-

Error management


-
-
unsigned    LZ4F_isError(LZ4F_errorCode_t code);   /**< tells when a function result is an error code */
-

-
const char* LZ4F_getErrorName(LZ4F_errorCode_t code);   /**< return error code string; for debugging */
-

-

Frame compression types


-
-
typedef enum {
-    LZ4F_default=0,
-    LZ4F_max64KB=4,
-    LZ4F_max256KB=5,
-    LZ4F_max1MB=6,
-    LZ4F_max4MB=7
-    LZ4F_OBSOLETE_ENUM(max64KB)
-    LZ4F_OBSOLETE_ENUM(max256KB)
-    LZ4F_OBSOLETE_ENUM(max1MB)
-    LZ4F_OBSOLETE_ENUM(max4MB)
-} LZ4F_blockSizeID_t;
-

-
typedef enum {
-    LZ4F_blockLinked=0,
-    LZ4F_blockIndependent
-    LZ4F_OBSOLETE_ENUM(blockLinked)
-    LZ4F_OBSOLETE_ENUM(blockIndependent)
-} LZ4F_blockMode_t;
-

-
typedef enum {
-    LZ4F_noContentChecksum=0,
-    LZ4F_contentChecksumEnabled
-    LZ4F_OBSOLETE_ENUM(noContentChecksum)
-    LZ4F_OBSOLETE_ENUM(contentChecksumEnabled)
-} LZ4F_contentChecksum_t;
-

-
typedef enum {
-    LZ4F_noBlockChecksum=0,
-    LZ4F_blockChecksumEnabled
-} LZ4F_blockChecksum_t;
-

-
typedef enum {
-    LZ4F_frame=0,
-    LZ4F_skippableFrame
-    LZ4F_OBSOLETE_ENUM(skippableFrame)
-} LZ4F_frameType_t;
-

-
typedef struct {
-  LZ4F_blockSizeID_t     blockSizeID;         /* max64KB, max256KB, max1MB, max4MB; 0 == default */
-  LZ4F_blockMode_t       blockMode;           /* LZ4F_blockLinked, LZ4F_blockIndependent; 0 == default */
-  LZ4F_contentChecksum_t contentChecksumFlag; /* 1: frame terminated with 32-bit checksum of decompressed data; 0: disabled (default) */
-  LZ4F_frameType_t       frameType;           /* read-only field : LZ4F_frame or LZ4F_skippableFrame */
-  unsigned long long     contentSize;         /* Size of uncompressed content ; 0 == unknown */
-  unsigned               dictID;              /* Dictionary ID, sent by compressor to help decoder select correct dictionary; 0 == no dictID provided */
-  LZ4F_blockChecksum_t   blockChecksumFlag;   /* 1: each block followed by a checksum of block's compressed data; 0: disabled (default) */
-} LZ4F_frameInfo_t;
-

makes it possible to set or read frame parameters. - Structure must be first init to 0, using memset() or LZ4F_INIT_FRAMEINFO, - setting all parameters to default. - It's then possible to update selectively some parameters -


- -
typedef struct {
-  LZ4F_frameInfo_t frameInfo;
-  int      compressionLevel;    /* 0: default (fast mode); values > LZ4HC_CLEVEL_MAX count as LZ4HC_CLEVEL_MAX; values < 0 trigger "fast acceleration" */
-  unsigned autoFlush;           /* 1: always flush; reduces usage of internal buffers */
-  unsigned favorDecSpeed;       /* 1: parser favors decompression speed vs compression ratio. Only works for high compression modes (>= LZ4HC_CLEVEL_OPT_MIN) */  /* v1.8.2+ */
-  unsigned reserved[3];         /* must be zero for forward compatibility */
-} LZ4F_preferences_t;
-

makes it possible to supply advanced compression instructions to streaming interface. - Structure must be first init to 0, using memset() or LZ4F_INIT_PREFERENCES, - setting all parameters to default. - All reserved fields must be set to zero. -


- -

Simple compression function


-
-
size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
-

Returns the maximum possible compressed size with LZ4F_compressFrame() given srcSize and preferences. - `preferencesPtr` is optional. It can be replaced by NULL, in which case, the function will assume default preferences. - Note : this result is only usable with LZ4F_compressFrame(). - It may also be used with LZ4F_compressUpdate() _if no flush() operation_ is performed. - -


- -
size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity,
-                                const void* srcBuffer, size_t srcSize,
-                                const LZ4F_preferences_t* preferencesPtr);
-

Compress an entire srcBuffer into a valid LZ4 frame. - dstCapacity MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). - The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default. - @return : number of bytes written into dstBuffer. - or an error code if it fails (can be tested using LZ4F_isError()) - -


- -

Advanced compression functions


-
-
typedef struct {
-  unsigned stableSrc;    /* 1 == src content will remain present on future calls to LZ4F_compress(); skip copying src content within tmp buffer */
-  unsigned reserved[3];
-} LZ4F_compressOptions_t;
-

-

Resource Management


-
-
LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** cctxPtr, unsigned version);
-LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctx);
-

The first thing to do is to create a compressionContext object, which will be used in all compression operations. - This is achieved using LZ4F_createCompressionContext(), which takes as argument a version. - The version provided MUST be LZ4F_VERSION. It is intended to track potential version mismatch, notably when using DLL. - The function will provide a pointer to a fully allocated LZ4F_cctx object. - If @return != zero, there was an error during context creation. - Object can release its memory using LZ4F_freeCompressionContext(); - -


- -

Compression


-
-
size_t LZ4F_compressBegin(LZ4F_cctx* cctx,
-                                      void* dstBuffer, size_t dstCapacity,
-                                      const LZ4F_preferences_t* prefsPtr);
-

will write the frame header into dstBuffer. - dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. - `prefsPtr` is optional : you can provide NULL as argument, all preferences will then be set to default. - @return : number of bytes written into dstBuffer for the header - or an error code (which can be tested using LZ4F_isError()) - -


- -
size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* prefsPtr);
-

Provides minimum dstCapacity required to guarantee success of - LZ4F_compressUpdate(), given a srcSize and preferences, for a worst case scenario. - When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() instead. - Note that the result is only valid for a single invocation of LZ4F_compressUpdate(). - When invoking LZ4F_compressUpdate() multiple times, - if the output buffer is gradually filled up instead of emptied and re-used from its start, - one must check if there is enough remaining capacity before each invocation, using LZ4F_compressBound(). - @return is always the same for a srcSize and prefsPtr. - prefsPtr is optional : when NULL is provided, preferences will be set to cover worst case scenario. - tech details : - @return if automatic flushing is not enabled, includes the possibility that internal buffer might already be filled by up to (blockSize-1) bytes. - It also includes frame footer (ending + checksum), since it might be generated by LZ4F_compressEnd(). - @return doesn't include frame header, as it was already generated by LZ4F_compressBegin(). - -


- -
size_t LZ4F_compressUpdate(LZ4F_cctx* cctx,
-                                       void* dstBuffer, size_t dstCapacity,
-                                 const void* srcBuffer, size_t srcSize,
-                                 const LZ4F_compressOptions_t* cOptPtr);
-

LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary. - Important rule: dstCapacity MUST be large enough to ensure operation success even in worst case situations. - This value is provided by LZ4F_compressBound(). - If this condition is not respected, LZ4F_compress() will fail (result is an errorCode). - LZ4F_compressUpdate() doesn't guarantee error recovery. - When an error occurs, compression context must be freed or resized. - `cOptPtr` is optional : NULL can be provided, in which case all options are set to default. - @return : number of bytes written into `dstBuffer` (it can be zero, meaning input data was just buffered). - or an error code if it fails (which can be tested using LZ4F_isError()) - -


- -
size_t LZ4F_flush(LZ4F_cctx* cctx,
-                              void* dstBuffer, size_t dstCapacity,
-                        const LZ4F_compressOptions_t* cOptPtr);
-

When data must be generated and sent immediately, without waiting for a block to be completely filled, - it's possible to call LZ4_flush(). It will immediately compress any data buffered within cctx. - `dstCapacity` must be large enough to ensure the operation will be successful. - `cOptPtr` is optional : it's possible to provide NULL, all options will be set to default. - @return : nb of bytes written into dstBuffer (can be zero, when there is no data stored within cctx) - or an error code if it fails (which can be tested using LZ4F_isError()) - Note : LZ4F_flush() is guaranteed to be successful when dstCapacity >= LZ4F_compressBound(0, prefsPtr). - -


- -
size_t LZ4F_compressEnd(LZ4F_cctx* cctx,
-                                    void* dstBuffer, size_t dstCapacity,
-                              const LZ4F_compressOptions_t* cOptPtr);
-

To properly finish an LZ4 frame, invoke LZ4F_compressEnd(). - It will flush whatever data remained within `cctx` (like LZ4_flush()) - and properly finalize the frame, with an endMark and a checksum. - `cOptPtr` is optional : NULL can be provided, in which case all options will be set to default. - @return : nb of bytes written into dstBuffer, necessarily >= 4 (endMark), - or an error code if it fails (which can be tested using LZ4F_isError()) - Note : LZ4F_compressEnd() is guaranteed to be successful when dstCapacity >= LZ4F_compressBound(0, prefsPtr). - A successful call to LZ4F_compressEnd() makes `cctx` available again for another compression task. - -


- -

Decompression functions


-
-
typedef struct {
-  unsigned stableDst;    /* pledges that last 64KB decompressed data will remain available unmodified. This optimization skips storage operations in tmp buffers. */
-  unsigned reserved[3];  /* must be set to zero for forward compatibility */
-} LZ4F_decompressOptions_t;
-

-
LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** dctxPtr, unsigned version);
-LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx);
-

Create an LZ4F_dctx object, to track all decompression operations. - The version provided MUST be LZ4F_VERSION. - The function provides a pointer to an allocated and initialized LZ4F_dctx object. - The result is an errorCode, which can be tested using LZ4F_isError(). - dctx memory can be released using LZ4F_freeDecompressionContext(); - Result of LZ4F_freeDecompressionContext() indicates current state of decompressionContext when being released. - That is, it should be == 0 if decompression has been completed fully and correctly. - -


- -

Streaming decompression functions


-
-
size_t LZ4F_headerSize(const void* src, size_t srcSize);
-

Provide the header size of a frame starting at `src`. - `srcSize` must be >= LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH, - which is enough to decode the header length. - @return : size of frame header - or an error code, which can be tested using LZ4F_isError() - note : Frame header size is variable, but is guaranteed to be - >= LZ4F_HEADER_SIZE_MIN bytes, and <= LZ4F_HEADER_SIZE_MAX bytes. - -


- -
size_t LZ4F_getFrameInfo(LZ4F_dctx* dctx,
-                                     LZ4F_frameInfo_t* frameInfoPtr,
-                                     const void* srcBuffer, size_t* srcSizePtr);
-

This function extracts frame parameters (max blockSize, dictID, etc.). - Its usage is optional: user can call LZ4F_decompress() directly. - - Extracted information will fill an existing LZ4F_frameInfo_t structure. - This can be useful for allocation and dictionary identification purposes. - - LZ4F_getFrameInfo() can work in the following situations : - - 1) At the beginning of a new frame, before any invocation of LZ4F_decompress(). - It will decode header from `srcBuffer`, - consuming the header and starting the decoding process. - - Input size must be large enough to contain the full frame header. - Frame header size can be known beforehand by LZ4F_headerSize(). - Frame header size is variable, but is guaranteed to be >= LZ4F_HEADER_SIZE_MIN bytes, - and not more than <= LZ4F_HEADER_SIZE_MAX bytes. - Hence, blindly providing LZ4F_HEADER_SIZE_MAX bytes or more will always work. - It's allowed to provide more input data than the header size, - LZ4F_getFrameInfo() will only consume the header. - - If input size is not large enough, - aka if it's smaller than header size, - function will fail and return an error code. - - 2) After decoding has been started, - it's possible to invoke LZ4F_getFrameInfo() anytime - to extract already decoded frame parameters stored within dctx. - - Note that, if decoding has barely started, - and not yet read enough information to decode the header, - LZ4F_getFrameInfo() will fail. - - The number of bytes consumed from srcBuffer will be updated in *srcSizePtr (necessarily <= original value). - LZ4F_getFrameInfo() only consumes bytes when decoding has not yet started, - and when decoding the header has been successful. - Decompression must then resume from (srcBuffer + *srcSizePtr). - - @return : a hint about how many srcSize bytes LZ4F_decompress() expects for next call, - or an error code which can be tested using LZ4F_isError(). - note 1 : in case of error, dctx is not modified. Decoding operation can resume from beginning safely. - note 2 : frame parameters are *copied into* an already allocated LZ4F_frameInfo_t structure. - -


- -
size_t LZ4F_decompress(LZ4F_dctx* dctx,
-                                   void* dstBuffer, size_t* dstSizePtr,
-                                   const void* srcBuffer, size_t* srcSizePtr,
-                                   const LZ4F_decompressOptions_t* dOptPtr);
-

Call this function repetitively to regenerate data compressed in `srcBuffer`. - - The function requires a valid dctx state. - It will read up to *srcSizePtr bytes from srcBuffer, - and decompress data into dstBuffer, of capacity *dstSizePtr. - - The nb of bytes consumed from srcBuffer will be written into *srcSizePtr (necessarily <= original value). - The nb of bytes decompressed into dstBuffer will be written into *dstSizePtr (necessarily <= original value). - - The function does not necessarily read all input bytes, so always check value in *srcSizePtr. - Unconsumed source data must be presented again in subsequent invocations. - - `dstBuffer` can freely change between each consecutive function invocation. - `dstBuffer` content will be overwritten. - - @return : an hint of how many `srcSize` bytes LZ4F_decompress() expects for next call. - Schematically, it's the size of the current (or remaining) compressed block + header of next block. - Respecting the hint provides some small speed benefit, because it skips intermediate buffers. - This is just a hint though, it's always possible to provide any srcSize. - - When a frame is fully decoded, @return will be 0 (no more data expected). - When provided with more bytes than necessary to decode a frame, - LZ4F_decompress() will stop reading exactly at end of current frame, and @return 0. - - If decompression failed, @return is an error code, which can be tested using LZ4F_isError(). - After a decompression error, the `dctx` context is not resumable. - Use LZ4F_resetDecompressionContext() to return to clean state. - - After a frame is fully decoded, dctx can be used again to decompress another frame. - -


- -
void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx);   /* always successful */
-

In case of an error, the context is left in "undefined" state. - In which case, it's necessary to reset it, before re-using it. - This method can also be used to abruptly stop any unfinished decompression, - and start a new one using same context resources. -


- -
typedef enum { LZ4F_LIST_ERRORS(LZ4F_GENERATE_ENUM)
-              _LZ4F_dummy_error_enum_for_c89_never_used } LZ4F_errorCodes;
-

-

Bulk processing dictionary API


-
-
LZ4FLIB_STATIC_API LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize);
-LZ4FLIB_STATIC_API void        LZ4F_freeCDict(LZ4F_CDict* CDict);
-

When compressing multiple messages / blocks using the same dictionary, it's recommended to load it just once. - LZ4_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay. - LZ4_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. - `dictBuffer` can be released after LZ4_CDict creation, since its content is copied within CDict -


- -
LZ4FLIB_STATIC_API size_t LZ4F_compressFrame_usingCDict(
-    LZ4F_cctx* cctx,
-    void* dst, size_t dstCapacity,
-    const void* src, size_t srcSize,
-    const LZ4F_CDict* cdict,
-    const LZ4F_preferences_t* preferencesPtr);
-

Compress an entire srcBuffer into a valid LZ4 frame using a digested Dictionary. - cctx must point to a context created by LZ4F_createCompressionContext(). - If cdict==NULL, compress without a dictionary. - dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). - If this condition is not respected, function will fail (@return an errorCode). - The LZ4F_preferences_t structure is optional : you may provide NULL as argument, - but it's not recommended, as it's the only way to provide dictID in the frame header. - @return : number of bytes written into dstBuffer. - or an error code if it fails (can be tested using LZ4F_isError()) -


- -
LZ4FLIB_STATIC_API size_t LZ4F_compressBegin_usingCDict(
-    LZ4F_cctx* cctx,
-    void* dstBuffer, size_t dstCapacity,
-    const LZ4F_CDict* cdict,
-    const LZ4F_preferences_t* prefsPtr);
-

Inits streaming dictionary compression, and writes the frame header into dstBuffer. - dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. - `prefsPtr` is optional : you may provide NULL as argument, - however, it's the only way to provide dictID in the frame header. - @return : number of bytes written into dstBuffer for the header, - or an error code (which can be tested using LZ4F_isError()) -


- -
LZ4FLIB_STATIC_API size_t LZ4F_decompress_usingDict(
-    LZ4F_dctx* dctxPtr,
-    void* dstBuffer, size_t* dstSizePtr,
-    const void* srcBuffer, size_t* srcSizePtr,
-    const void* dict, size_t dictSize,
-    const LZ4F_decompressOptions_t* decompressOptionsPtr);
-

Same as LZ4F_decompress(), using a predefined dictionary. - Dictionary is used "in place", without any preprocessing. - It must remain accessible throughout the entire frame decoding. -


- - - diff --git a/ta6ob/lz4/examples/.gitignore b/ta6ob/lz4/examples/.gitignore deleted file mode 100644 index 5abeef6..0000000 --- a/ta6ob/lz4/examples/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -/Makefile.lz4* -/printVersion -/doubleBuffer -/dictionaryRandomAccess -/ringBuffer -/ringBufferHC -/lineCompress -/frameCompress -/simpleBuffer -/*.exe diff --git a/ta6ob/lz4/examples/COPYING b/ta6ob/lz4/examples/COPYING deleted file mode 100644 index d159169..0000000 --- a/ta6ob/lz4/examples/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/ta6ob/lz4/examples/HCStreaming_ringBuffer.c b/ta6ob/lz4/examples/HCStreaming_ringBuffer.c deleted file mode 100644 index bc8391e..0000000 --- a/ta6ob/lz4/examples/HCStreaming_ringBuffer.c +++ /dev/null @@ -1,232 +0,0 @@ -// LZ4 HC streaming API example : ring buffer -// Based on a previous example by Takayuki Matsuoka - - -/************************************** - * Compiler Options - **************************************/ -#if defined(_MSC_VER) && (_MSC_VER <= 1800) /* Visual Studio <= 2013 */ -# define _CRT_SECURE_NO_WARNINGS -# define snprintf sprintf_s -#endif - -#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) -#ifdef __GNUC__ -# pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */ -#endif - - -/************************************** - * Includes - **************************************/ -#include "lz4hc.h" -#include "lz4.h" - -#include -#include -#include -#include -#include - -enum { - MESSAGE_MAX_BYTES = 1024, - RING_BUFFER_BYTES = 1024 * 8 + MESSAGE_MAX_BYTES, - DEC_BUFFER_BYTES = RING_BUFFER_BYTES + MESSAGE_MAX_BYTES // Intentionally larger to test unsynchronized ring buffers -}; - - -size_t write_int32(FILE* fp, int32_t i) { - return fwrite(&i, sizeof(i), 1, fp); -} - -size_t write_bin(FILE* fp, const void* array, int arrayBytes) { - assert(arrayBytes >= 0); - return fwrite(array, 1, (size_t)arrayBytes, fp); -} - -size_t read_int32(FILE* fp, int32_t* i) { - return fread(i, sizeof(*i), 1, fp); -} - -size_t read_bin(FILE* fp, void* array, int arrayBytes) { - assert(arrayBytes >= 0); - return fread(array, 1, (size_t)arrayBytes, fp); -} - - -void test_compress(FILE* outFp, FILE* inpFp) -{ - LZ4_streamHC_t lz4Stream_body = { 0 }; - LZ4_streamHC_t* lz4Stream = &lz4Stream_body; - - static char inpBuf[RING_BUFFER_BYTES]; - int inpOffset = 0; - - for(;;) { - // Read random length ([1,MESSAGE_MAX_BYTES]) data to the ring buffer. - char* const inpPtr = &inpBuf[inpOffset]; - const int randomLength = (rand() % MESSAGE_MAX_BYTES) + 1; - const int inpBytes = (int) read_bin(inpFp, inpPtr, randomLength); - if (0 == inpBytes) break; - -#define CMPBUFSIZE (LZ4_COMPRESSBOUND(MESSAGE_MAX_BYTES)) - { char cmpBuf[CMPBUFSIZE]; - const int cmpBytes = LZ4_compress_HC_continue(lz4Stream, inpPtr, cmpBuf, inpBytes, CMPBUFSIZE); - - if(cmpBytes <= 0) break; - write_int32(outFp, cmpBytes); - write_bin(outFp, cmpBuf, cmpBytes); - - inpOffset += inpBytes; - - // Wraparound the ringbuffer offset - if(inpOffset >= RING_BUFFER_BYTES - MESSAGE_MAX_BYTES) - inpOffset = 0; - } - } - - write_int32(outFp, 0); -} - - -void test_decompress(FILE* outFp, FILE* inpFp) -{ - static char decBuf[DEC_BUFFER_BYTES]; - int decOffset = 0; - LZ4_streamDecode_t lz4StreamDecode_body = { 0 }; - LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body; - - for(;;) { - int cmpBytes = 0; - char cmpBuf[CMPBUFSIZE]; - - { const size_t r0 = read_int32(inpFp, &cmpBytes); - size_t r1; - if(r0 != 1 || cmpBytes <= 0) - break; - - r1 = read_bin(inpFp, cmpBuf, cmpBytes); - if(r1 != (size_t) cmpBytes) - break; - } - - { char* const decPtr = &decBuf[decOffset]; - const int decBytes = LZ4_decompress_safe_continue( - lz4StreamDecode, cmpBuf, decPtr, cmpBytes, MESSAGE_MAX_BYTES); - if(decBytes <= 0) - break; - - decOffset += decBytes; - write_bin(outFp, decPtr, decBytes); - - // Wraparound the ringbuffer offset - if(decOffset >= DEC_BUFFER_BYTES - MESSAGE_MAX_BYTES) - decOffset = 0; - } - } -} - - -// Compare 2 files content -// return 0 if identical -// return ByteNb>0 if different -size_t compare(FILE* f0, FILE* f1) -{ - size_t result = 1; - - for (;;) { - char b0[65536]; - char b1[65536]; - const size_t r0 = fread(b0, 1, sizeof(b0), f0); - const size_t r1 = fread(b1, 1, sizeof(b1), f1); - - if ((r0==0) && (r1==0)) return 0; // success - - if (r0 != r1) { - size_t smallest = r0; - if (r1 -#include -#include -#include - -enum { - BLOCK_BYTES = 1024 * 8, -// BLOCK_BYTES = 1024 * 64, -}; - - -size_t write_int(FILE* fp, int i) { - return fwrite(&i, sizeof(i), 1, fp); -} - -size_t write_bin(FILE* fp, const void* array, size_t arrayBytes) { - return fwrite(array, 1, arrayBytes, fp); -} - -size_t read_int(FILE* fp, int* i) { - return fread(i, sizeof(*i), 1, fp); -} - -size_t read_bin(FILE* fp, void* array, size_t arrayBytes) { - return fread(array, 1, arrayBytes, fp); -} - - -void test_compress(FILE* outFp, FILE* inpFp) -{ - LZ4_stream_t lz4Stream_body; - LZ4_stream_t* lz4Stream = &lz4Stream_body; - - char inpBuf[2][BLOCK_BYTES]; - int inpBufIndex = 0; - - LZ4_initStream(lz4Stream, sizeof (*lz4Stream)); - - for(;;) { - char* const inpPtr = inpBuf[inpBufIndex]; - const int inpBytes = (int) read_bin(inpFp, inpPtr, BLOCK_BYTES); - if(0 == inpBytes) { - break; - } - - { - char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)]; - const int cmpBytes = LZ4_compress_fast_continue( - lz4Stream, inpPtr, cmpBuf, inpBytes, sizeof(cmpBuf), 1); - if(cmpBytes <= 0) { - break; - } - write_int(outFp, cmpBytes); - write_bin(outFp, cmpBuf, (size_t) cmpBytes); - } - - inpBufIndex = (inpBufIndex + 1) % 2; - } - - write_int(outFp, 0); -} - - -void test_decompress(FILE* outFp, FILE* inpFp) -{ - LZ4_streamDecode_t lz4StreamDecode_body; - LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body; - - char decBuf[2][BLOCK_BYTES]; - int decBufIndex = 0; - - LZ4_setStreamDecode(lz4StreamDecode, NULL, 0); - - for(;;) { - char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)]; - int cmpBytes = 0; - - { - const size_t readCount0 = read_int(inpFp, &cmpBytes); - if(readCount0 != 1 || cmpBytes <= 0) { - break; - } - - const size_t readCount1 = read_bin(inpFp, cmpBuf, (size_t) cmpBytes); - if(readCount1 != (size_t) cmpBytes) { - break; - } - } - - { - char* const decPtr = decBuf[decBufIndex]; - const int decBytes = LZ4_decompress_safe_continue( - lz4StreamDecode, cmpBuf, decPtr, cmpBytes, BLOCK_BYTES); - if(decBytes <= 0) { - break; - } - write_bin(outFp, decPtr, (size_t) decBytes); - } - - decBufIndex = (decBufIndex + 1) % 2; - } -} - - -int compare(FILE* fp0, FILE* fp1) -{ - int result = 0; - - while(0 == result) { - char b0[65536]; - char b1[65536]; - const size_t r0 = read_bin(fp0, b0, sizeof(b0)); - const size_t r1 = read_bin(fp1, b1, sizeof(b1)); - - result = (int) r0 - (int) r1; - - if(0 == r0 || 0 == r1) { - break; - } - if(0 == result) { - result = memcmp(b0, b1, r0); - } - } - - return result; -} - - -int main(int argc, char* argv[]) -{ - char inpFilename[256] = { 0 }; - char lz4Filename[256] = { 0 }; - char decFilename[256] = { 0 }; - - if(argc < 2) { - printf("Please specify input filename\n"); - return 0; - } - - snprintf(inpFilename, 256, "%s", argv[1]); - snprintf(lz4Filename, 256, "%s.lz4s-%d", argv[1], BLOCK_BYTES); - snprintf(decFilename, 256, "%s.lz4s-%d.dec", argv[1], BLOCK_BYTES); - - printf("inp = [%s]\n", inpFilename); - printf("lz4 = [%s]\n", lz4Filename); - printf("dec = [%s]\n", decFilename); - - // compress - { - FILE* inpFp = fopen(inpFilename, "rb"); - FILE* outFp = fopen(lz4Filename, "wb"); - - printf("compress : %s -> %s\n", inpFilename, lz4Filename); - test_compress(outFp, inpFp); - printf("compress : done\n"); - - fclose(outFp); - fclose(inpFp); - } - - // decompress - { - FILE* inpFp = fopen(lz4Filename, "rb"); - FILE* outFp = fopen(decFilename, "wb"); - - printf("decompress : %s -> %s\n", lz4Filename, decFilename); - test_decompress(outFp, inpFp); - printf("decompress : done\n"); - - fclose(outFp); - fclose(inpFp); - } - - // verify - { - FILE* inpFp = fopen(inpFilename, "rb"); - FILE* decFp = fopen(decFilename, "rb"); - - printf("verify : %s <-> %s\n", inpFilename, decFilename); - const int cmp = compare(inpFp, decFp); - if(0 == cmp) { - printf("verify : OK\n"); - } else { - printf("verify : NG\n"); - } - - fclose(decFp); - fclose(inpFp); - } - - return 0; -} diff --git a/ta6ob/lz4/examples/blockStreaming_doubleBuffer.md b/ta6ob/lz4/examples/blockStreaming_doubleBuffer.md deleted file mode 100644 index 38dc2e8..0000000 --- a/ta6ob/lz4/examples/blockStreaming_doubleBuffer.md +++ /dev/null @@ -1,100 +0,0 @@ -# LZ4 Streaming API Example : Double Buffer -by *Takayuki Matsuoka* - -`blockStreaming_doubleBuffer.c` is LZ4 Streaming API example which implements double buffer (de)compression. - -Please note : - - - Firstly, read "LZ4 Streaming API Basics". - - This is relatively advanced application example. - - Output file is not compatible with lz4frame and platform dependent. - - -## What's the point of this example ? - - - Handle huge file in small amount of memory - - Always better compression ratio than Block API - - Uniform block size - - -## How the compression works - -First of all, allocate "Double Buffer" for input and LZ4 compressed data buffer for output. -Double buffer has two pages, "first" page (Page#1) and "second" page (Page#2). - -``` - Double Buffer - - Page#1 Page#2 - +---------+---------+ - | Block#1 | | - +----+----+---------+ - | - v - {Out#1} - - - Prefix Dependency - +---------+ - | | - v | - +---------+----+----+ - | Block#1 | Block#2 | - +---------+----+----+ - | - v - {Out#2} - - - External Dictionary Mode - +---------+ - | | - | v - +----+----+---------+ - | Block#3 | Block#2 | - +----+----+---------+ - | - v - {Out#3} - - - Prefix Dependency - +---------+ - | | - v | - +---------+----+----+ - | Block#3 | Block#4 | - +---------+----+----+ - | - v - {Out#4} -``` - -Next, read first block to double buffer's first page. And compress it by `LZ4_compress_continue()`. -For the first time, LZ4 doesn't know any previous dependencies, -so it just compress the line without dependencies and generates compressed block {Out#1} to LZ4 compressed data buffer. -After that, write {Out#1} to the file. - -Next, read second block to double buffer's second page. And compress it. -This time, LZ4 can use dependency to Block#1 to improve compression ratio. -This dependency is called "Prefix mode". - -Next, read third block to double buffer's *first* page, and compress it. -Also this time, LZ4 can use dependency to Block#2. -This dependency is called "External Dictonaly mode". - -Continue these procedure to the end of the file. - - -## How the decompression works - -Decompression will do reverse order. - - - Read first compressed block. - - Decompress it to the first page and write that page to the file. - - Read second compressed block. - - Decompress it to the second page and write that page to the file. - - Read third compressed block. - - Decompress it to the *first* page and write that page to the file. - -Continue these procedure to the end of the compressed file. diff --git a/ta6ob/lz4/examples/blockStreaming_lineByLine.c b/ta6ob/lz4/examples/blockStreaming_lineByLine.c deleted file mode 100644 index 19c3345..0000000 --- a/ta6ob/lz4/examples/blockStreaming_lineByLine.c +++ /dev/null @@ -1,211 +0,0 @@ -// LZ4 streaming API example : line-by-line logfile compression -// by Takayuki Matsuoka - - -#if defined(_MSC_VER) && (_MSC_VER <= 1800) /* Visual Studio <= 2013 */ -# define _CRT_SECURE_NO_WARNINGS -# define snprintf sprintf_s -#endif -#include "lz4.h" - -#include -#include -#include -#include - -static size_t write_uint16(FILE* fp, uint16_t i) -{ - return fwrite(&i, sizeof(i), 1, fp); -} - -static size_t write_bin(FILE* fp, const void* array, int arrayBytes) -{ - return fwrite(array, 1, arrayBytes, fp); -} - -static size_t read_uint16(FILE* fp, uint16_t* i) -{ - return fread(i, sizeof(*i), 1, fp); -} - -static size_t read_bin(FILE* fp, void* array, int arrayBytes) -{ - return fread(array, 1, arrayBytes, fp); -} - - -static void test_compress( - FILE* outFp, - FILE* inpFp, - size_t messageMaxBytes, - size_t ringBufferBytes) -{ - LZ4_stream_t* const lz4Stream = LZ4_createStream(); - const size_t cmpBufBytes = LZ4_COMPRESSBOUND(messageMaxBytes); - char* const cmpBuf = (char*) malloc(cmpBufBytes); - char* const inpBuf = (char*) malloc(ringBufferBytes); - int inpOffset = 0; - - for ( ; ; ) - { - char* const inpPtr = &inpBuf[inpOffset]; - -#if 0 - // Read random length data to the ring buffer. - const int randomLength = (rand() % messageMaxBytes) + 1; - const int inpBytes = (int) read_bin(inpFp, inpPtr, randomLength); - if (0 == inpBytes) break; -#else - // Read line to the ring buffer. - int inpBytes = 0; - if (!fgets(inpPtr, (int) messageMaxBytes, inpFp)) - break; - inpBytes = (int) strlen(inpPtr); -#endif - - { - const int cmpBytes = LZ4_compress_fast_continue( - lz4Stream, inpPtr, cmpBuf, inpBytes, cmpBufBytes, 1); - if (cmpBytes <= 0) break; - write_uint16(outFp, (uint16_t) cmpBytes); - write_bin(outFp, cmpBuf, cmpBytes); - - // Add and wraparound the ringbuffer offset - inpOffset += inpBytes; - if ((size_t)inpOffset >= ringBufferBytes - messageMaxBytes) inpOffset = 0; - } - } - write_uint16(outFp, 0); - - free(inpBuf); - free(cmpBuf); - LZ4_freeStream(lz4Stream); -} - - -static void test_decompress( - FILE* outFp, - FILE* inpFp, - size_t messageMaxBytes, - size_t ringBufferBytes) -{ - LZ4_streamDecode_t* const lz4StreamDecode = LZ4_createStreamDecode(); - char* const cmpBuf = (char*) malloc(LZ4_COMPRESSBOUND(messageMaxBytes)); - char* const decBuf = (char*) malloc(ringBufferBytes); - int decOffset = 0; - - for ( ; ; ) - { - uint16_t cmpBytes = 0; - - if (read_uint16(inpFp, &cmpBytes) != 1) break; - if (cmpBytes == 0) break; - if (read_bin(inpFp, cmpBuf, cmpBytes) != cmpBytes) break; - - { - char* const decPtr = &decBuf[decOffset]; - const int decBytes = LZ4_decompress_safe_continue( - lz4StreamDecode, cmpBuf, decPtr, cmpBytes, (int) messageMaxBytes); - if (decBytes <= 0) break; - write_bin(outFp, decPtr, decBytes); - - // Add and wraparound the ringbuffer offset - decOffset += decBytes; - if ((size_t)decOffset >= ringBufferBytes - messageMaxBytes) decOffset = 0; - } - } - - free(decBuf); - free(cmpBuf); - LZ4_freeStreamDecode(lz4StreamDecode); -} - - -static int compare(FILE* f0, FILE* f1) -{ - int result = 0; - const size_t tempBufferBytes = 65536; - char* const b0 = (char*) malloc(tempBufferBytes); - char* const b1 = (char*) malloc(tempBufferBytes); - - while(0 == result) - { - const size_t r0 = fread(b0, 1, tempBufferBytes, f0); - const size_t r1 = fread(b1, 1, tempBufferBytes, f1); - - result = (int) r0 - (int) r1; - - if (0 == r0 || 0 == r1) break; - if (0 == result) result = memcmp(b0, b1, r0); - } - - free(b1); - free(b0); - return result; -} - - -int main(int argc, char* argv[]) -{ - enum { - MESSAGE_MAX_BYTES = 1024, - RING_BUFFER_BYTES = 1024 * 256 + MESSAGE_MAX_BYTES, - }; - - char inpFilename[256] = { 0 }; - char lz4Filename[256] = { 0 }; - char decFilename[256] = { 0 }; - - if (argc < 2) - { - printf("Please specify input filename\n"); - return 0; - } - - snprintf(inpFilename, 256, "%s", argv[1]); - snprintf(lz4Filename, 256, "%s.lz4s", argv[1]); - snprintf(decFilename, 256, "%s.lz4s.dec", argv[1]); - - printf("inp = [%s]\n", inpFilename); - printf("lz4 = [%s]\n", lz4Filename); - printf("dec = [%s]\n", decFilename); - - // compress - { - FILE* inpFp = fopen(inpFilename, "rb"); - FILE* outFp = fopen(lz4Filename, "wb"); - - test_compress(outFp, inpFp, MESSAGE_MAX_BYTES, RING_BUFFER_BYTES); - - fclose(outFp); - fclose(inpFp); - } - - // decompress - { - FILE* inpFp = fopen(lz4Filename, "rb"); - FILE* outFp = fopen(decFilename, "wb"); - - test_decompress(outFp, inpFp, MESSAGE_MAX_BYTES, RING_BUFFER_BYTES); - - fclose(outFp); - fclose(inpFp); - } - - // verify - { - FILE* inpFp = fopen(inpFilename, "rb"); - FILE* decFp = fopen(decFilename, "rb"); - - const int cmp = compare(inpFp, decFp); - if (0 == cmp) - printf("Verify : OK\n"); - else - printf("Verify : NG\n"); - - fclose(decFp); - fclose(inpFp); - } - - return 0; -} diff --git a/ta6ob/lz4/examples/blockStreaming_lineByLine.md b/ta6ob/lz4/examples/blockStreaming_lineByLine.md deleted file mode 100644 index 4735f92..0000000 --- a/ta6ob/lz4/examples/blockStreaming_lineByLine.md +++ /dev/null @@ -1,122 +0,0 @@ -# LZ4 Streaming API Example : Line by Line Text Compression -by *Takayuki Matsuoka* - -`blockStreaming_lineByLine.c` is LZ4 Straming API example which implements line by line incremental (de)compression. - -Please note the following restrictions : - - - Firstly, read "LZ4 Streaming API Basics". - - This is relatively advanced application example. - - Output file is not compatible with lz4frame and platform dependent. - - -## What's the point of this example ? - - - Line by line incremental (de)compression. - - Handle huge file in small amount of memory - - Generally better compression ratio than Block API - - Non-uniform block size - - -## How the compression works - -First of all, allocate "Ring Buffer" for input and LZ4 compressed data buffer for output. - -``` -(1) - Ring Buffer - - +--------+ - | Line#1 | - +---+----+ - | - v - {Out#1} - - -(2) - Prefix Mode Dependency - +----+ - | | - v | - +--------+-+------+ - | Line#1 | Line#2 | - +--------+---+----+ - | - v - {Out#2} - - -(3) - Prefix Prefix - +----+ +----+ - | | | | - v | v | - +--------+-+------+-+------+ - | Line#1 | Line#2 | Line#3 | - +--------+--------+---+----+ - | - v - {Out#3} - - -(4) - External Dictionary Mode - +----+ +----+ - | | | | - v | v | - ------+--------+-+------+-+--------+ - | .... | Line#X | Line#X+1 | - ------+--------+--------+-----+----+ - ^ | - | v - | {Out#X+1} - | - Reset - - -(5) - Prefix - +-----+ - | | - v | - ------+--------+--------+----------+--+-------+ - | .... | Line#X | Line#X+1 | Line#X+2 | - ------+--------+--------+----------+-----+----+ - ^ | - | v - | {Out#X+2} - | - Reset -``` - -Next (see (1)), read first line to ringbuffer and compress it by `LZ4_compress_continue()`. -For the first time, LZ4 doesn't know any previous dependencies, -so it just compress the line without dependencies and generates compressed line {Out#1} to LZ4 compressed data buffer. -After that, write {Out#1} to the file and forward ringbuffer offset. - -Do the same things to second line (see (2)). -But in this time, LZ4 can use dependency to Line#1 to improve compression ratio. -This dependency is called "Prefix mode". - -Eventually, we'll reach end of ringbuffer at Line#X (see (4)). -This time, we should reset ringbuffer offset. -After resetting, at Line#X+1 pointer is not adjacent, but LZ4 still maintain its memory. -This is called "External Dictionary Mode". - -In Line#X+2 (see (5)), finally LZ4 forget almost all memories but still remains Line#X+1. -This is the same situation as Line#2. - -Continue these procedure to the end of text file. - - -## How the decompression works - -Decompression will do reverse order. - - - Read compressed line from the file to buffer. - - Decompress it to the ringbuffer. - - Output decompressed plain text line to the file. - - Forward ringbuffer offset. If offset exceedes end of the ringbuffer, reset it. - -Continue these procedure to the end of the compressed file. diff --git a/ta6ob/lz4/examples/blockStreaming_ringBuffer.c b/ta6ob/lz4/examples/blockStreaming_ringBuffer.c deleted file mode 100644 index 0b6a3ce..0000000 --- a/ta6ob/lz4/examples/blockStreaming_ringBuffer.c +++ /dev/null @@ -1,190 +0,0 @@ -/* LZ4 streaming API example : ring buffer - * Based on sample code from Takayuki Matsuoka */ - - -/************************************** - * Compiler Options - **************************************/ -#if defined(_MSC_VER) && (_MSC_VER <= 1800) /* Visual Studio <= 2013 */ -# define _CRT_SECURE_NO_WARNINGS -# define snprintf sprintf_s -#endif - - -/************************************** - * Includes - **************************************/ -#include -#include -#include -#include -#include "lz4.h" - - -enum { - MESSAGE_MAX_BYTES = 1024, - RING_BUFFER_BYTES = 1024 * 8 + MESSAGE_MAX_BYTES, - DECODE_RING_BUFFER = RING_BUFFER_BYTES + MESSAGE_MAX_BYTES /* Intentionally larger, to test unsynchronized ring buffers */ -}; - - -size_t write_int32(FILE* fp, int32_t i) { - return fwrite(&i, sizeof(i), 1, fp); -} - -size_t write_bin(FILE* fp, const void* array, int arrayBytes) { - return fwrite(array, 1, arrayBytes, fp); -} - -size_t read_int32(FILE* fp, int32_t* i) { - return fread(i, sizeof(*i), 1, fp); -} - -size_t read_bin(FILE* fp, void* array, int arrayBytes) { - return fread(array, 1, arrayBytes, fp); -} - - -void test_compress(FILE* outFp, FILE* inpFp) -{ - LZ4_stream_t lz4Stream_body = { { 0 } }; - LZ4_stream_t* lz4Stream = &lz4Stream_body; - - static char inpBuf[RING_BUFFER_BYTES]; - int inpOffset = 0; - - for(;;) { - // Read random length ([1,MESSAGE_MAX_BYTES]) data to the ring buffer. - char* const inpPtr = &inpBuf[inpOffset]; - const int randomLength = (rand() % MESSAGE_MAX_BYTES) + 1; - const int inpBytes = (int) read_bin(inpFp, inpPtr, randomLength); - if (0 == inpBytes) break; - - { -#define CMPBUFSIZE (LZ4_COMPRESSBOUND(MESSAGE_MAX_BYTES)) - char cmpBuf[CMPBUFSIZE]; - const int cmpBytes = LZ4_compress_fast_continue(lz4Stream, inpPtr, cmpBuf, inpBytes, CMPBUFSIZE, 0); - if(cmpBytes <= 0) break; - write_int32(outFp, cmpBytes); - write_bin(outFp, cmpBuf, cmpBytes); - - inpOffset += inpBytes; - - // Wraparound the ringbuffer offset - if(inpOffset >= RING_BUFFER_BYTES - MESSAGE_MAX_BYTES) inpOffset = 0; - } - } - - write_int32(outFp, 0); -} - - -void test_decompress(FILE* outFp, FILE* inpFp) -{ - static char decBuf[DECODE_RING_BUFFER]; - int decOffset = 0; - LZ4_streamDecode_t lz4StreamDecode_body = { { 0 } }; - LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body; - - for(;;) { - int cmpBytes = 0; - char cmpBuf[CMPBUFSIZE]; - - { const size_t r0 = read_int32(inpFp, &cmpBytes); - if(r0 != 1 || cmpBytes <= 0) break; - - const size_t r1 = read_bin(inpFp, cmpBuf, cmpBytes); - if(r1 != (size_t) cmpBytes) break; - } - - { char* const decPtr = &decBuf[decOffset]; - const int decBytes = LZ4_decompress_safe_continue( - lz4StreamDecode, cmpBuf, decPtr, cmpBytes, MESSAGE_MAX_BYTES); - if(decBytes <= 0) break; - decOffset += decBytes; - write_bin(outFp, decPtr, decBytes); - - // Wraparound the ringbuffer offset - if(decOffset >= DECODE_RING_BUFFER - MESSAGE_MAX_BYTES) decOffset = 0; - } - } -} - - -int compare(FILE* f0, FILE* f1) -{ - int result = 0; - - while (0 == result) { - char b0[65536]; - char b1[65536]; - const size_t r0 = fread(b0, 1, sizeof(b0), f0); - const size_t r1 = fread(b1, 1, sizeof(b1), f1); - - result = (int) r0 - (int) r1; - - if (0 == r0 || 0 == r1) break; - - if (0 == result) result = memcmp(b0, b1, r0); - } - - return result; -} - - -int main(int argc, char** argv) -{ - char inpFilename[256] = { 0 }; - char lz4Filename[256] = { 0 }; - char decFilename[256] = { 0 }; - - if (argc < 2) { - printf("Please specify input filename\n"); - return 0; - } - - snprintf(inpFilename, 256, "%s", argv[1]); - snprintf(lz4Filename, 256, "%s.lz4s-%d", argv[1], 0); - snprintf(decFilename, 256, "%s.lz4s-%d.dec", argv[1], 0); - - printf("inp = [%s]\n", inpFilename); - printf("lz4 = [%s]\n", lz4Filename); - printf("dec = [%s]\n", decFilename); - - // compress - { FILE* const inpFp = fopen(inpFilename, "rb"); - FILE* const outFp = fopen(lz4Filename, "wb"); - - test_compress(outFp, inpFp); - - fclose(outFp); - fclose(inpFp); - } - - // decompress - { FILE* const inpFp = fopen(lz4Filename, "rb"); - FILE* const outFp = fopen(decFilename, "wb"); - - test_decompress(outFp, inpFp); - - fclose(outFp); - fclose(inpFp); - } - - // verify - { FILE* const inpFp = fopen(inpFilename, "rb"); - FILE* const decFp = fopen(decFilename, "rb"); - - const int cmp = compare(inpFp, decFp); - if (0 == cmp) { - printf("Verify : OK\n"); - } else { - printf("Verify : NG\n"); - } - - fclose(decFp); - fclose(inpFp); - } - - return 0; -} diff --git a/ta6ob/lz4/examples/compress_functions.c b/ta6ob/lz4/examples/compress_functions.c deleted file mode 100644 index 7fd6775..0000000 --- a/ta6ob/lz4/examples/compress_functions.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * compress_functions.c - * Copyright : Kyle Harper - * License : Follows same licensing as the lz4.c/lz4.h program at any given time. Currently, BSD 2. - * Description: A program to demonstrate the various compression functions involved in when using LZ4_compress_default(). The idea - * is to show how each step in the call stack can be used directly, if desired. There is also some benchmarking for - * each function to demonstrate the (probably lack of) performance difference when jumping the stack. - * (If you're new to lz4, please read simple_buffer.c to understand the fundamentals) - * - * The call stack (before theoretical compiler optimizations) for LZ4_compress_default is as follows: - * LZ4_compress_default - * LZ4_compress_fast - * LZ4_compress_fast_extState - * LZ4_compress_generic - * - * LZ4_compress_default() - * This is the recommended function for compressing data. It will serve as the baseline for comparison. - * LZ4_compress_fast() - * Despite its name, it's not a "fast" version of compression. It simply decides if HEAPMODE is set and either - * allocates memory on the heap for a struct or creates the struct directly on the stack. Stack access is generally - * faster but this function itself isn't giving that advantage, it's just some logic for compile time. - * LZ4_compress_fast_extState() - * This simply accepts all the pointers and values collected thus far and adds logic to determine how - * LZ4_compress_generic should be invoked; specifically: can the source fit into a single pass as determined by - * LZ4_64Klimit. - * LZ4_compress_generic() - * As the name suggests, this is the generic function that ultimately does most of the heavy lifting. Calling this - * directly can help avoid some test cases and branching which might be useful in some implementation-specific - * situations, but you really need to know what you're doing AND what you're asking lz4 to do! You also need a - * wrapper function because this function isn't exposed with lz4.h. - * - * The call stack for decompression functions is shallow. There are 2 options: - * LZ4_decompress_safe || LZ4_decompress_fast - * LZ4_decompress_generic - * - * LZ4_decompress_safe - * This is the recommended function for decompressing data. It is considered safe because the caller specifies - * both the size of the compresssed buffer to read as well as the maximum size of the output (decompressed) buffer - * instead of just the latter. - * LZ4_decompress_fast - * Again, despite its name it's not a "fast" version of decompression. It simply frees the caller of sending the - * size of the compressed buffer (it will simply be read-to-end, hence it's non-safety). - * LZ4_decompress_generic - * This is the generic function that both of the LZ4_decompress_* functions above end up calling. Calling this - * directly is not advised, period. Furthermore, it is a static inline function in lz4.c, so there isn't a symbol - * exposed for anyone using lz4.h to utilize. - * - * Special Note About Decompression: - * Using the LZ4_decompress_safe() function protects against malicious (user) input. If you are using data from a - * trusted source, or if your program is the producer (P) as well as its consumer (C) in a PC or MPMC setup, you can - * safely use the LZ4_decompress_fast function - */ - -/* Since lz4 compiles with c99 and not gnu/std99 we need to enable POSIX linking for time.h structs and functions. */ -#if __STDC_VERSION__ >= 199901L -#define _XOPEN_SOURCE 600 -#else -#define _XOPEN_SOURCE 500 -#endif -#define _POSIX_C_SOURCE 199309L - -/* Includes, for Power! */ -#define LZ4_DISABLE_DEPRECATE_WARNINGS /* LZ4_decompress_fast */ -#include "lz4.h" -#include /* for printf() */ -#include /* for exit() */ -#include /* for atoi() memcmp() */ -#include /* for uint_types */ -#include /* for PRIu64 */ -#include /* for clock_gettime() */ -#include /* for setlocale() */ - -/* We need to know what one billion is for clock timing. */ -#define BILLION 1000000000L - -/* Create a crude set of test IDs so we can switch on them later (Can't switch() on a char[] or char*). */ -#define ID__LZ4_COMPRESS_DEFAULT 1 -#define ID__LZ4_COMPRESS_FAST 2 -#define ID__LZ4_COMPRESS_FAST_EXTSTATE 3 -#define ID__LZ4_COMPRESS_GENERIC 4 -#define ID__LZ4_DECOMPRESS_SAFE 5 -#define ID__LZ4_DECOMPRESS_FAST 6 - - - -/* - * Easy show-error-and-bail function. - */ -void run_screaming(const char *message, const int code) { - printf("%s\n", message); - exit(code); -} - - -/* - * Centralize the usage function to keep main cleaner. - */ -void usage(const char *message) { - printf("Usage: ./argPerformanceTesting \n"); - run_screaming(message, 1); - return; -} - - - -/* - * Runs the benchmark for LZ4_compress_* based on function_id. - */ -uint64_t bench( - const char *known_good_dst, - const int function_id, - const int iterations, - const char *src, - char *dst, - const size_t src_size, - const size_t max_dst_size, - const size_t comp_size - ) { - uint64_t time_taken = 0; - int rv = 0; - const int warm_up = 5000; - struct timespec start, end; - const int acceleration = 1; - LZ4_stream_t state; - - // Select the right function to perform the benchmark on. We perform 5000 initial loops to warm the cache and ensure that dst - // remains matching to known_good_dst between successive calls. - switch(function_id) { - case ID__LZ4_COMPRESS_DEFAULT: - printf("Starting benchmark for function: LZ4_compress_default()\n"); - for(int junk=0; junk 1) - iterations = atoi(argv[1]); - if (iterations < 1) - usage("Argument 1 (iterations) must be > 0."); - - // First we will create 2 sources (char *) of 2000 bytes each. One normal text, the other highly-compressible text. - const char *src = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed luctus purus et risus vulputate, et mollis orci ullamcorper. Nulla facilisi. Fusce in ligula sed purus varius aliquet interdum vitae justo. Proin quis diam velit. Nulla varius iaculis auctor. Cras volutpat, justo eu dictum pulvinar, elit sem porttitor metus, et imperdiet metus sapien et ante. Nullam nisi nulla, ornare eu tristique eu, dignissim vitae diam. Nulla sagittis porta libero, a accumsan felis sagittis scelerisque. Integer laoreet eleifend congue. Etiam rhoncus leo vel dolor fermentum, quis luctus nisl iaculis. Praesent a erat sapien. Aliquam semper mi in lorem ultrices ultricies. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In feugiat risus sed enim ultrices, at sodales nulla tristique. Maecenas eget pellentesque justo, sed pellentesque lectus. Fusce sagittis sit amet elit vel varius. Donec sed ligula nec ligula vulputate rutrum sed ut lectus. Etiam congue pharetra leo vitae cursus. Morbi enim ante, porttitor ut varius vel, tincidunt quis justo. Nunc iaculis, risus id ultrices semper, metus est efficitur ligula, vel posuere risus nunc eget purus. Ut lorem turpis, condimentum at sem sed, porta aliquam turpis. In ut sapien a nulla dictum tincidunt quis sit amet lorem. Fusce at est egestas, luctus neque eu, consectetur tortor. Phasellus eleifend ultricies nulla ac lobortis. Morbi maximus quam cursus vehicula iaculis. Maecenas cursus vel justo ut rutrum. Curabitur magna orci, dignissim eget dapibus vitae, finibus id lacus. Praesent rhoncus mattis augue vitae bibendum. Praesent porta mauris non ultrices fermentum. Quisque vulputate ipsum in sodales pulvinar. Aliquam nec mollis felis. Donec vitae augue pulvinar, congue nisl sed, pretium purus. Fusce lobortis mi ac neque scelerisque semper. Pellentesque vel est vitae magna aliquet aliquet. Nam non dolor. Nulla facilisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi ac lacinia felis metus."; - const char *hc_src = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - // Set and derive sizes. Since we're using strings, use strlen() + 1 for \0. - const size_t src_size = strlen(src) + 1; - const size_t max_dst_size = LZ4_compressBound(src_size); - int bytes_returned = 0; - // Now build allocations for the data we'll be playing with. - char *dst = calloc(1, max_dst_size); - char *known_good_dst = calloc(1, max_dst_size); - char *known_good_hc_dst = calloc(1, max_dst_size); - if (dst == NULL || known_good_dst == NULL || known_good_hc_dst == NULL) - run_screaming("Couldn't allocate memory for the destination buffers. Sad :(", 1); - - // Create known-good buffers to verify our tests with other functions will produce the same results. - bytes_returned = LZ4_compress_default(src, known_good_dst, src_size, max_dst_size); - if (bytes_returned < 1) - run_screaming("Couldn't create a known-good destination buffer for comparison... this is bad.", 1); - const size_t src_comp_size = bytes_returned; - bytes_returned = LZ4_compress_default(hc_src, known_good_hc_dst, src_size, max_dst_size); - if (bytes_returned < 1) - run_screaming("Couldn't create a known-good (highly compressible) destination buffer for comparison... this is bad.", 1); - const size_t hc_src_comp_size = bytes_returned; - - - /* LZ4_compress_default() */ - // This is the default function so we don't need to demonstrate how to use it. See basics.c if you need more basal information. - - /* LZ4_compress_fast() */ - // Using this function is identical to LZ4_compress_default except we need to specify an "acceleration" value. Defaults to 1. - memset(dst, 0, max_dst_size); - bytes_returned = LZ4_compress_fast(src, dst, src_size, max_dst_size, 1); - if (bytes_returned < 1) - run_screaming("Failed to compress src using LZ4_compress_fast. echo $? for return code.", bytes_returned); - if (memcmp(dst, known_good_dst, bytes_returned) != 0) - run_screaming("According to memcmp(), the value we got in dst from LZ4_compress_fast doesn't match the known-good value. This is bad.", 1); - - /* LZ4_compress_fast_extState() */ - // Using this function directly requires that we build an LZ4_stream_t struct ourselves. We do NOT have to reset it ourselves. - memset(dst, 0, max_dst_size); - LZ4_stream_t state; - bytes_returned = LZ4_compress_fast_extState(&state, src, dst, src_size, max_dst_size, 1); - if (bytes_returned < 1) - run_screaming("Failed to compress src using LZ4_compress_fast_extState. echo $? for return code.", bytes_returned); - if (memcmp(dst, known_good_dst, bytes_returned) != 0) - run_screaming("According to memcmp(), the value we got in dst from LZ4_compress_fast_extState doesn't match the known-good value. This is bad.", 1); - - /* LZ4_compress_generic */ - // When you can exactly control the inputs and options of your LZ4 needs, you can use LZ4_compress_generic and fixed (const) - // values for the enum types such as dictionary and limitations. Any other direct-use is probably a bad idea. - // - // That said, the LZ4_compress_generic() function is 'static inline' and does not have a prototype in lz4.h to expose a symbol - // for it. In other words: we can't access it directly. I don't want to submit a PR that modifies lz4.c/h. Yann and others can - // do that if they feel it's worth expanding this example. - // - // I will, however, leave a skeleton of what would be required to use it directly: - /* - memset(dst, 0, max_dst_size); - // LZ4_stream_t state: is already declared above. We can reuse it BUT we have to reset the stream ourselves between each call. - LZ4_resetStream((LZ4_stream_t *)&state); - // Since src size is small we know the following enums will be used: notLimited (0), byU16 (2), noDict (0), noDictIssue (0). - bytes_returned = LZ4_compress_generic(&state, src, dst, src_size, max_dst_size, notLimited, byU16, noDict, noDictIssue, 1); - if (bytes_returned < 1) - run_screaming("Failed to compress src using LZ4_compress_generic. echo $? for return code.", bytes_returned); - if (memcmp(dst, known_good_dst, bytes_returned) != 0) - run_screaming("According to memcmp(), the value we got in dst from LZ4_compress_generic doesn't match the known-good value. This is bad.", 1); - */ - - - /* Benchmarking */ - /* Now we'll run a few rudimentary benchmarks with each function to demonstrate differences in speed based on the function used. - * Remember, we cannot call LZ4_compress_generic() directly (yet) so it's disabled. - */ - // Suite A - Normal Compressibility - char *dst_d = calloc(1, src_size); - memset(dst, 0, max_dst_size); - printf("\nStarting suite A: Normal compressible text.\n"); - uint64_t time_taken__default = bench(known_good_dst, ID__LZ4_COMPRESS_DEFAULT, iterations, src, dst, src_size, max_dst_size, src_comp_size); - uint64_t time_taken__fast = bench(known_good_dst, ID__LZ4_COMPRESS_FAST, iterations, src, dst, src_size, max_dst_size, src_comp_size); - uint64_t time_taken__fast_extstate = bench(known_good_dst, ID__LZ4_COMPRESS_FAST_EXTSTATE, iterations, src, dst, src_size, max_dst_size, src_comp_size); - //uint64_t time_taken__generic = bench(known_good_dst, ID__LZ4_COMPRESS_GENERIC, iterations, src, dst, src_size, max_dst_size, src_comp_size); - uint64_t time_taken__decomp_safe = bench(src, ID__LZ4_DECOMPRESS_SAFE, iterations, known_good_dst, dst_d, src_size, max_dst_size, src_comp_size); - uint64_t time_taken__decomp_fast = bench(src, ID__LZ4_DECOMPRESS_FAST, iterations, known_good_dst, dst_d, src_size, max_dst_size, src_comp_size); - // Suite B - Highly Compressible - memset(dst, 0, max_dst_size); - printf("\nStarting suite B: Highly compressible text.\n"); - uint64_t time_taken_hc__default = bench(known_good_hc_dst, ID__LZ4_COMPRESS_DEFAULT, iterations, hc_src, dst, src_size, max_dst_size, hc_src_comp_size); - uint64_t time_taken_hc__fast = bench(known_good_hc_dst, ID__LZ4_COMPRESS_FAST, iterations, hc_src, dst, src_size, max_dst_size, hc_src_comp_size); - uint64_t time_taken_hc__fast_extstate = bench(known_good_hc_dst, ID__LZ4_COMPRESS_FAST_EXTSTATE, iterations, hc_src, dst, src_size, max_dst_size, hc_src_comp_size); - //uint64_t time_taken_hc__generic = bench(known_good_hc_dst, ID__LZ4_COMPRESS_GENERIC, iterations, hc_src, dst, src_size, max_dst_size, hc_src_comp_size); - uint64_t time_taken_hc__decomp_safe = bench(hc_src, ID__LZ4_DECOMPRESS_SAFE, iterations, known_good_hc_dst, dst_d, src_size, max_dst_size, hc_src_comp_size); - uint64_t time_taken_hc__decomp_fast = bench(hc_src, ID__LZ4_DECOMPRESS_FAST, iterations, known_good_hc_dst, dst_d, src_size, max_dst_size, hc_src_comp_size); - - // Report and leave. - setlocale(LC_ALL, ""); - const char *format = "|%-14s|%-30s|%'14.9f|%'16d|%'14d|%'13.2f%%|\n"; - const char *header_format = "|%-14s|%-30s|%14s|%16s|%14s|%14s|\n"; - const char *separator = "+--------------+------------------------------+--------------+----------------+--------------+--------------+\n"; - printf("\n"); - printf("%s", separator); - printf(header_format, "Source", "Function Benchmarked", "Total Seconds", "Iterations/sec", "ns/Iteration", "% of default"); - printf("%s", separator); - printf(format, "Normal Text", "LZ4_compress_default()", (double)time_taken__default / BILLION, (int)(iterations / ((double)time_taken__default /BILLION)), (int)time_taken__default / iterations, (double)time_taken__default * 100 / time_taken__default); - printf(format, "Normal Text", "LZ4_compress_fast()", (double)time_taken__fast / BILLION, (int)(iterations / ((double)time_taken__fast /BILLION)), (int)time_taken__fast / iterations, (double)time_taken__fast * 100 / time_taken__default); - printf(format, "Normal Text", "LZ4_compress_fast_extState()", (double)time_taken__fast_extstate / BILLION, (int)(iterations / ((double)time_taken__fast_extstate /BILLION)), (int)time_taken__fast_extstate / iterations, (double)time_taken__fast_extstate * 100 / time_taken__default); - //printf(format, "Normal Text", "LZ4_compress_generic()", (double)time_taken__generic / BILLION, (int)(iterations / ((double)time_taken__generic /BILLION)), (int)time_taken__generic / iterations, (double)time_taken__generic * 100 / time_taken__default); - printf(format, "Normal Text", "LZ4_decompress_safe()", (double)time_taken__decomp_safe / BILLION, (int)(iterations / ((double)time_taken__decomp_safe /BILLION)), (int)time_taken__decomp_safe / iterations, (double)time_taken__decomp_safe * 100 / time_taken__default); - printf(format, "Normal Text", "LZ4_decompress_fast()", (double)time_taken__decomp_fast / BILLION, (int)(iterations / ((double)time_taken__decomp_fast /BILLION)), (int)time_taken__decomp_fast / iterations, (double)time_taken__decomp_fast * 100 / time_taken__default); - printf(header_format, "", "", "", "", "", ""); - printf(format, "Compressible", "LZ4_compress_default()", (double)time_taken_hc__default / BILLION, (int)(iterations / ((double)time_taken_hc__default /BILLION)), (int)time_taken_hc__default / iterations, (double)time_taken_hc__default * 100 / time_taken_hc__default); - printf(format, "Compressible", "LZ4_compress_fast()", (double)time_taken_hc__fast / BILLION, (int)(iterations / ((double)time_taken_hc__fast /BILLION)), (int)time_taken_hc__fast / iterations, (double)time_taken_hc__fast * 100 / time_taken_hc__default); - printf(format, "Compressible", "LZ4_compress_fast_extState()", (double)time_taken_hc__fast_extstate / BILLION, (int)(iterations / ((double)time_taken_hc__fast_extstate /BILLION)), (int)time_taken_hc__fast_extstate / iterations, (double)time_taken_hc__fast_extstate * 100 / time_taken_hc__default); - //printf(format, "Compressible", "LZ4_compress_generic()", (double)time_taken_hc__generic / BILLION, (int)(iterations / ((double)time_taken_hc__generic /BILLION)), (int)time_taken_hc__generic / iterations, (double)time_taken_hc__generic * 100 / time_taken_hc__default); - printf(format, "Compressible", "LZ4_decompress_safe()", (double)time_taken_hc__decomp_safe / BILLION, (int)(iterations / ((double)time_taken_hc__decomp_safe /BILLION)), (int)time_taken_hc__decomp_safe / iterations, (double)time_taken_hc__decomp_safe * 100 / time_taken_hc__default); - printf(format, "Compressible", "LZ4_decompress_fast()", (double)time_taken_hc__decomp_fast / BILLION, (int)(iterations / ((double)time_taken_hc__decomp_fast /BILLION)), (int)time_taken_hc__decomp_fast / iterations, (double)time_taken_hc__decomp_fast * 100 / time_taken_hc__default); - printf("%s", separator); - printf("\n"); - printf("All done, ran %d iterations per test.\n", iterations); - return 0; -} diff --git a/ta6ob/lz4/examples/dictionaryRandomAccess.c b/ta6ob/lz4/examples/dictionaryRandomAccess.c deleted file mode 100644 index ecb3b2d..0000000 --- a/ta6ob/lz4/examples/dictionaryRandomAccess.c +++ /dev/null @@ -1,280 +0,0 @@ -// LZ4 API example : Dictionary Random Access - -#if defined(_MSC_VER) && (_MSC_VER <= 1800) /* Visual Studio <= 2013 */ -# define _CRT_SECURE_NO_WARNINGS -# define snprintf sprintf_s -#endif -#include "lz4.h" - -#include -#include -#include -#include - -#define MIN(x, y) ((x) < (y) ? (x) : (y)) - -enum { - BLOCK_BYTES = 1024, /* 1 KiB of uncompressed data in a block */ - DICTIONARY_BYTES = 1024, /* Load a 1 KiB dictionary */ - MAX_BLOCKS = 1024 /* For simplicity of implementation */ -}; - -/** - * Magic bytes for this test case. - * This is not a great magic number because it is a common word in ASCII. - * However, it is important to have some versioning system in your format. - */ -const char kTestMagic[] = { 'T', 'E', 'S', 'T' }; - - -void write_int(FILE* fp, int i) { - size_t written = fwrite(&i, sizeof(i), 1, fp); - if (written != 1) { exit(10); } -} - -void write_bin(FILE* fp, const void* array, size_t arrayBytes) { - size_t written = fwrite(array, 1, arrayBytes, fp); - if (written != arrayBytes) { exit(11); } -} - -void read_int(FILE* fp, int* i) { - size_t read = fread(i, sizeof(*i), 1, fp); - if (read != 1) { exit(12); } -} - -size_t read_bin(FILE* fp, void* array, size_t arrayBytes) { - size_t read = fread(array, 1, arrayBytes, fp); - if (ferror(fp)) { exit(12); } - return read; -} - -void seek_bin(FILE* fp, long offset, int origin) { - if (fseek(fp, offset, origin)) { exit(14); } -} - - -void test_compress(FILE* outFp, FILE* inpFp, void *dict, int dictSize) -{ - LZ4_stream_t lz4Stream_body; - LZ4_stream_t* lz4Stream = &lz4Stream_body; - - char inpBuf[BLOCK_BYTES]; - int offsets[MAX_BLOCKS]; - int *offsetsEnd = offsets; - - - LZ4_initStream(lz4Stream, sizeof(*lz4Stream)); - - /* Write header magic */ - write_bin(outFp, kTestMagic, sizeof(kTestMagic)); - - *offsetsEnd++ = sizeof(kTestMagic); - /* Write compressed data blocks. Each block contains BLOCK_BYTES of plain - data except possibly the last. */ - for(;;) { - const int inpBytes = (int) read_bin(inpFp, inpBuf, BLOCK_BYTES); - if(0 == inpBytes) { - break; - } - - /* Forget previously compressed data and load the dictionary */ - LZ4_loadDict(lz4Stream, dict, dictSize); - { - char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)]; - const int cmpBytes = LZ4_compress_fast_continue( - lz4Stream, inpBuf, cmpBuf, inpBytes, sizeof(cmpBuf), 1); - if(cmpBytes <= 0) { exit(1); } - write_bin(outFp, cmpBuf, (size_t)cmpBytes); - /* Keep track of the offsets */ - *offsetsEnd = *(offsetsEnd - 1) + cmpBytes; - ++offsetsEnd; - } - if (offsetsEnd - offsets > MAX_BLOCKS) { exit(2); } - } - /* Write the tailing jump table */ - { - int *ptr = offsets; - while (ptr != offsetsEnd) { - write_int(outFp, *ptr++); - } - write_int(outFp, offsetsEnd - offsets); - } -} - - -void test_decompress(FILE* outFp, FILE* inpFp, void *dict, int dictSize, int offset, int length) -{ - LZ4_streamDecode_t lz4StreamDecode_body; - LZ4_streamDecode_t* lz4StreamDecode = &lz4StreamDecode_body; - - /* The blocks [currentBlock, endBlock) contain the data we want */ - int currentBlock = offset / BLOCK_BYTES; - int endBlock = ((offset + length - 1) / BLOCK_BYTES) + 1; - - char decBuf[BLOCK_BYTES]; - int offsets[MAX_BLOCKS]; - - /* Special cases */ - if (length == 0) { return; } - - /* Read the magic bytes */ - { - char magic[sizeof(kTestMagic)]; - size_t read = read_bin(inpFp, magic, sizeof(magic)); - if (read != sizeof(magic)) { exit(1); } - if (memcmp(kTestMagic, magic, sizeof(magic))) { exit(2); } - } - - /* Read the offsets tail */ - { - int numOffsets; - int block; - int *offsetsPtr = offsets; - seek_bin(inpFp, -4, SEEK_END); - read_int(inpFp, &numOffsets); - if (numOffsets <= endBlock) { exit(3); } - seek_bin(inpFp, -4 * (numOffsets + 1), SEEK_END); - for (block = 0; block <= endBlock; ++block) { - read_int(inpFp, offsetsPtr++); - } - } - /* Seek to the first block to read */ - seek_bin(inpFp, offsets[currentBlock], SEEK_SET); - offset = offset % BLOCK_BYTES; - - /* Start decoding */ - for(; currentBlock < endBlock; ++currentBlock) { - char cmpBuf[LZ4_COMPRESSBOUND(BLOCK_BYTES)]; - /* The difference in offsets is the size of the block */ - int cmpBytes = offsets[currentBlock + 1] - offsets[currentBlock]; - { - const size_t read = read_bin(inpFp, cmpBuf, (size_t)cmpBytes); - if(read != (size_t)cmpBytes) { exit(4); } - } - - /* Load the dictionary */ - LZ4_setStreamDecode(lz4StreamDecode, dict, dictSize); - { - const int decBytes = LZ4_decompress_safe_continue( - lz4StreamDecode, cmpBuf, decBuf, cmpBytes, BLOCK_BYTES); - if(decBytes <= 0) { exit(5); } - { - /* Write out the part of the data we care about */ - int blockLength = MIN(length, (decBytes - offset)); - write_bin(outFp, decBuf + offset, (size_t)blockLength); - offset = 0; - length -= blockLength; - } - } - } -} - - -int compare(FILE* fp0, FILE* fp1, int length) -{ - int result = 0; - - while(0 == result) { - char b0[4096]; - char b1[4096]; - const size_t r0 = read_bin(fp0, b0, MIN(length, (int)sizeof(b0))); - const size_t r1 = read_bin(fp1, b1, MIN(length, (int)sizeof(b1))); - - result = (int) r0 - (int) r1; - - if(0 == r0 || 0 == r1) { - break; - } - if(0 == result) { - result = memcmp(b0, b1, r0); - } - length -= r0; - } - - return result; -} - - -int main(int argc, char* argv[]) -{ - char inpFilename[256] = { 0 }; - char lz4Filename[256] = { 0 }; - char decFilename[256] = { 0 }; - char dictFilename[256] = { 0 }; - int offset; - int length; - char dict[DICTIONARY_BYTES]; - int dictSize; - - if(argc < 5) { - printf("Usage: %s input dictionary offset length", argv[0]); - return 0; - } - - snprintf(inpFilename, 256, "%s", argv[1]); - snprintf(lz4Filename, 256, "%s.lz4s-%d", argv[1], BLOCK_BYTES); - snprintf(decFilename, 256, "%s.lz4s-%d.dec", argv[1], BLOCK_BYTES); - snprintf(dictFilename, 256, "%s", argv[2]); - offset = atoi(argv[3]); - length = atoi(argv[4]); - - printf("inp = [%s]\n", inpFilename); - printf("lz4 = [%s]\n", lz4Filename); - printf("dec = [%s]\n", decFilename); - printf("dict = [%s]\n", dictFilename); - printf("offset = [%d]\n", offset); - printf("length = [%d]\n", length); - - /* Load dictionary */ - { - FILE* dictFp = fopen(dictFilename, "rb"); - dictSize = (int)read_bin(dictFp, dict, DICTIONARY_BYTES); - fclose(dictFp); - } - - /* compress */ - { - FILE* inpFp = fopen(inpFilename, "rb"); - FILE* outFp = fopen(lz4Filename, "wb"); - - printf("compress : %s -> %s\n", inpFilename, lz4Filename); - test_compress(outFp, inpFp, dict, dictSize); - printf("compress : done\n"); - - fclose(outFp); - fclose(inpFp); - } - - /* decompress */ - { - FILE* inpFp = fopen(lz4Filename, "rb"); - FILE* outFp = fopen(decFilename, "wb"); - - printf("decompress : %s -> %s\n", lz4Filename, decFilename); - test_decompress(outFp, inpFp, dict, DICTIONARY_BYTES, offset, length); - printf("decompress : done\n"); - - fclose(outFp); - fclose(inpFp); - } - - /* verify */ - { - FILE* inpFp = fopen(inpFilename, "rb"); - FILE* decFp = fopen(decFilename, "rb"); - seek_bin(inpFp, offset, SEEK_SET); - - printf("verify : %s <-> %s\n", inpFilename, decFilename); - const int cmp = compare(inpFp, decFp, length); - if(0 == cmp) { - printf("verify : OK\n"); - } else { - printf("verify : NG\n"); - } - - fclose(decFp); - fclose(inpFp); - } - - return 0; -} diff --git a/ta6ob/lz4/examples/dictionaryRandomAccess.md b/ta6ob/lz4/examples/dictionaryRandomAccess.md deleted file mode 100644 index 53d825d..0000000 --- a/ta6ob/lz4/examples/dictionaryRandomAccess.md +++ /dev/null @@ -1,67 +0,0 @@ -# LZ4 API Example : Dictionary Random Access - -`dictionaryRandomAccess.c` is LZ4 API example which implements dictionary compression and random access decompression. - -Please note that the output file is not compatible with lz4frame and is platform dependent. - - -## What's the point of this example ? - - - Dictionary based compression for homogenous files. - - Random access to compressed blocks. - - -## How the compression works - -Reads the dictionary from a file, and uses it as the history for each block. -This allows each block to be independent, but maintains compression ratio. - -``` - Dictionary - + - | - v - +---------+ - | Block#1 | - +----+----+ - | - v - {Out#1} - - - Dictionary - + - | - v - +---------+ - | Block#2 | - +----+----+ - | - v - {Out#2} -``` - -After writing the magic bytes `TEST` and then the compressed blocks, write out the jump table. -The last 4 bytes is an integer containing the number of blocks in the stream. -If there are `N` blocks, then just before the last 4 bytes is `N + 1` 4 byte integers containing the offsets at the beginning and end of each block. -Let `Offset#K` be the total number of bytes written after writing out `Block#K` *including* the magic bytes for simplicity. - -``` -+------+---------+ +---------+---+----------+ +----------+-----+ -| TEST | Block#1 | ... | Block#N | 4 | Offset#1 | ... | Offset#N | N+1 | -+------+---------+ +---------+---+----------+ +----------+-----+ -``` - -## How the decompression works - -Decompression will do reverse order. - - - Seek to the last 4 bytes of the file and read the number of offsets. - - Read each offset into an array. - - Seek to the first block containing data we want to read. - We know where to look because we know each block contains a fixed amount of uncompressed data, except possibly the last. - - Decompress it and write what data we need from it to the file. - - Read the next block. - - Decompress it and write that page to the file. - -Continue these procedure until all the required data has been read. diff --git a/ta6ob/lz4/examples/frameCompress.c b/ta6ob/lz4/examples/frameCompress.c deleted file mode 100644 index aac4a3b..0000000 --- a/ta6ob/lz4/examples/frameCompress.c +++ /dev/null @@ -1,401 +0,0 @@ -/* LZ4frame API example : compress a file - * Modified from an example code by Zbigniew Jędrzejewski-Szmek - * - * This example streams an input file into an output file - * using a bounded memory budget. - * Input is read in chunks of IN_CHUNK_SIZE */ - -#include -#include -#include -#include -#include - -#include - - -#define IN_CHUNK_SIZE (16*1024) - -static const LZ4F_preferences_t kPrefs = { - { LZ4F_max256KB, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame, - 0 /* unknown content size */, 0 /* no dictID */ , LZ4F_noBlockChecksum }, - 0, /* compression level; 0 == default */ - 0, /* autoflush */ - 0, /* favor decompression speed */ - { 0, 0, 0 }, /* reserved, must be set to 0 */ -}; - - -/* safe_fwrite() : - * performs fwrite(), ensure operation success, or immediately exit() */ -static void safe_fwrite(void* buf, size_t eltSize, size_t nbElt, FILE* f) -{ - size_t const writtenSize = fwrite(buf, eltSize, nbElt, f); - size_t const expectedSize = eltSize * nbElt; - if (nbElt>0) assert(expectedSize / nbElt == eltSize); /* check overflow */ - if (writtenSize < expectedSize) { - if (ferror(f)) /* note : ferror() must follow fwrite */ - fprintf(stderr, "Write failed \n"); - else - fprintf(stderr, "Write too short \n"); - exit(1); - } -} - - -/* ================================================= */ -/* Streaming Compression example */ -/* ================================================= */ - -typedef struct { - int error; - unsigned long long size_in; - unsigned long long size_out; -} compressResult_t; - -static compressResult_t -compress_file_internal(FILE* f_in, FILE* f_out, - LZ4F_compressionContext_t ctx, - void* inBuff, size_t inChunkSize, - void* outBuff, size_t outCapacity) -{ - compressResult_t result = { 1, 0, 0 }; /* result for an error */ - unsigned long long count_in = 0, count_out; - - assert(f_in != NULL); assert(f_out != NULL); - assert(ctx != NULL); - assert(outCapacity >= LZ4F_HEADER_SIZE_MAX); - assert(outCapacity >= LZ4F_compressBound(inChunkSize, &kPrefs)); - - /* write frame header */ - { size_t const headerSize = LZ4F_compressBegin(ctx, outBuff, outCapacity, &kPrefs); - if (LZ4F_isError(headerSize)) { - printf("Failed to start compression: error %u \n", (unsigned)headerSize); - return result; - } - count_out = headerSize; - printf("Buffer size is %u bytes, header size %u bytes \n", - (unsigned)outCapacity, (unsigned)headerSize); - safe_fwrite(outBuff, 1, headerSize, f_out); - } - - /* stream file */ - for (;;) { - size_t const readSize = fread(inBuff, 1, IN_CHUNK_SIZE, f_in); - if (readSize == 0) break; /* nothing left to read from input file */ - count_in += readSize; - - size_t const compressedSize = LZ4F_compressUpdate(ctx, - outBuff, outCapacity, - inBuff, readSize, - NULL); - if (LZ4F_isError(compressedSize)) { - printf("Compression failed: error %u \n", (unsigned)compressedSize); - return result; - } - - printf("Writing %u bytes\n", (unsigned)compressedSize); - safe_fwrite(outBuff, 1, compressedSize, f_out); - count_out += compressedSize; - } - - /* flush whatever remains within internal buffers */ - { size_t const compressedSize = LZ4F_compressEnd(ctx, - outBuff, outCapacity, - NULL); - if (LZ4F_isError(compressedSize)) { - printf("Failed to end compression: error %u \n", (unsigned)compressedSize); - return result; - } - - printf("Writing %u bytes \n", (unsigned)compressedSize); - safe_fwrite(outBuff, 1, compressedSize, f_out); - count_out += compressedSize; - } - - result.size_in = count_in; - result.size_out = count_out; - result.error = 0; - return result; -} - -static compressResult_t -compress_file(FILE* f_in, FILE* f_out) -{ - assert(f_in != NULL); - assert(f_out != NULL); - - /* ressource allocation */ - LZ4F_compressionContext_t ctx; - size_t const ctxCreation = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION); - void* const src = malloc(IN_CHUNK_SIZE); - size_t const outbufCapacity = LZ4F_compressBound(IN_CHUNK_SIZE, &kPrefs); /* large enough for any input <= IN_CHUNK_SIZE */ - void* const outbuff = malloc(outbufCapacity); - - compressResult_t result = { 1, 0, 0 }; /* == error (default) */ - if (!LZ4F_isError(ctxCreation) && src && outbuff) { - result = compress_file_internal(f_in, f_out, - ctx, - src, IN_CHUNK_SIZE, - outbuff, outbufCapacity); - } else { - printf("error : ressource allocation failed \n"); - } - - LZ4F_freeCompressionContext(ctx); /* supports free on NULL */ - free(src); - free(outbuff); - return result; -} - - -/* ================================================= */ -/* Streaming decompression example */ -/* ================================================= */ - -static size_t get_block_size(const LZ4F_frameInfo_t* info) { - switch (info->blockSizeID) { - case LZ4F_default: - case LZ4F_max64KB: return 1 << 16; - case LZ4F_max256KB: return 1 << 18; - case LZ4F_max1MB: return 1 << 20; - case LZ4F_max4MB: return 1 << 22; - default: - printf("Impossible with expected frame specification (<=v1.6.1)\n"); - exit(1); - } -} - -/* @return : 1==error, 0==success */ -static int -decompress_file_internal(FILE* f_in, FILE* f_out, - LZ4F_dctx* dctx, - void* src, size_t srcCapacity, size_t filled, size_t alreadyConsumed, - void* dst, size_t dstCapacity) -{ - int firstChunk = 1; - size_t ret = 1; - - assert(f_in != NULL); assert(f_out != NULL); - assert(dctx != NULL); - assert(src != NULL); assert(srcCapacity > 0); assert(filled <= srcCapacity); assert(alreadyConsumed <= filled); - assert(dst != NULL); assert(dstCapacity > 0); - - /* Decompression */ - while (ret != 0) { - /* Load more input */ - size_t readSize = firstChunk ? filled : fread(src, 1, srcCapacity, f_in); firstChunk=0; - const void* srcPtr = (const char*)src + alreadyConsumed; alreadyConsumed=0; - const void* const srcEnd = (const char*)srcPtr + readSize; - if (readSize == 0 || ferror(f_in)) { - printf("Decompress: not enough input or error reading file\n"); - return 1; - } - - /* Decompress: - * Continue while there is more input to read (srcPtr != srcEnd) - * and the frame isn't over (ret != 0) - */ - while (srcPtr < srcEnd && ret != 0) { - /* Any data within dst has been flushed at this stage */ - size_t dstSize = dstCapacity; - size_t srcSize = (const char*)srcEnd - (const char*)srcPtr; - ret = LZ4F_decompress(dctx, dst, &dstSize, srcPtr, &srcSize, /* LZ4F_decompressOptions_t */ NULL); - if (LZ4F_isError(ret)) { - printf("Decompression error: %s\n", LZ4F_getErrorName(ret)); - return 1; - } - /* Flush output */ - if (dstSize != 0) safe_fwrite(dst, 1, dstSize, f_out); - /* Update input */ - srcPtr = (const char*)srcPtr + srcSize; - } - - assert(srcPtr <= srcEnd); - - /* Ensure all input data has been consumed. - * It is valid to have multiple frames in the same file, - * but this example only supports one frame. - */ - if (srcPtr < srcEnd) { - printf("Decompress: Trailing data left in file after frame\n"); - return 1; - } - } - - /* Check that there isn't trailing data in the file after the frame. - * It is valid to have multiple frames in the same file, - * but this example only supports one frame. - */ - { size_t const readSize = fread(src, 1, 1, f_in); - if (readSize != 0 || !feof(f_in)) { - printf("Decompress: Trailing data left in file after frame\n"); - return 1; - } } - - return 0; -} - - -/* @return : 1==error, 0==completed */ -static int -decompress_file_allocDst(FILE* f_in, FILE* f_out, - LZ4F_dctx* dctx, - void* src, size_t srcCapacity) -{ - assert(f_in != NULL); assert(f_out != NULL); - assert(dctx != NULL); - assert(src != NULL); - assert(srcCapacity >= LZ4F_HEADER_SIZE_MAX); /* ensure LZ4F_getFrameInfo() can read enough data */ - - /* Read Frame header */ - size_t const readSize = fread(src, 1, srcCapacity, f_in); - if (readSize == 0 || ferror(f_in)) { - printf("Decompress: not enough input or error reading file\n"); - return 1; - } - - LZ4F_frameInfo_t info; - size_t consumedSize = readSize; - { size_t const fires = LZ4F_getFrameInfo(dctx, &info, src, &consumedSize); - if (LZ4F_isError(fires)) { - printf("LZ4F_getFrameInfo error: %s\n", LZ4F_getErrorName(fires)); - return 1; - } } - - /* Allocating enough space for an entire block isn't necessary for - * correctness, but it allows some memcpy's to be elided. - */ - size_t const dstCapacity = get_block_size(&info); - void* const dst = malloc(dstCapacity); - if (!dst) { perror("decompress_file(dst)"); return 1; } - - int const decompressionResult = decompress_file_internal( - f_in, f_out, - dctx, - src, srcCapacity, readSize-consumedSize, consumedSize, - dst, dstCapacity); - - free(dst); - return decompressionResult; -} - - -/* @result : 1==error, 0==success */ -static int decompress_file(FILE* f_in, FILE* f_out) -{ - assert(f_in != NULL); assert(f_out != NULL); - - /* Ressource allocation */ - void* const src = malloc(IN_CHUNK_SIZE); - if (!src) { perror("decompress_file(src)"); return 1; } - - LZ4F_dctx* dctx; - { size_t const dctxStatus = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION); - if (LZ4F_isError(dctxStatus)) { - printf("LZ4F_dctx creation error: %s\n", LZ4F_getErrorName(dctxStatus)); - } } - - int const result = !dctx ? 1 /* error */ : - decompress_file_allocDst(f_in, f_out, dctx, src, IN_CHUNK_SIZE); - - free(src); - LZ4F_freeDecompressionContext(dctx); /* note : free works on NULL */ - return result; -} - - -int compareFiles(FILE* fp0, FILE* fp1) -{ - int result = 0; - - while (result==0) { - char b0[1024]; - char b1[1024]; - size_t const r0 = fread(b0, 1, sizeof(b0), fp0); - size_t const r1 = fread(b1, 1, sizeof(b1), fp1); - - result = (r0 != r1); - if (!r0 || !r1) break; - if (!result) result = memcmp(b0, b1, r0); - } - - return result; -} - - -int main(int argc, const char **argv) { - char inpFilename[256] = { 0 }; - char lz4Filename[256] = { 0 }; - char decFilename[256] = { 0 }; - - if (argc < 2) { - printf("Please specify input filename\n"); - return 0; - } - - snprintf(inpFilename, 256, "%s", argv[1]); - snprintf(lz4Filename, 256, "%s.lz4", argv[1]); - snprintf(decFilename, 256, "%s.lz4.dec", argv[1]); - - printf("inp = [%s]\n", inpFilename); - printf("lz4 = [%s]\n", lz4Filename); - printf("dec = [%s]\n", decFilename); - - /* compress */ - { FILE* const inpFp = fopen(inpFilename, "rb"); - FILE* const outFp = fopen(lz4Filename, "wb"); - - printf("compress : %s -> %s\n", inpFilename, lz4Filename); - compressResult_t const ret = compress_file(inpFp, outFp); - - fclose(outFp); - fclose(inpFp); - - if (ret.error) { - printf("compress : failed with code %i\n", ret.error); - return ret.error; - } - printf("%s: %zu → %zu bytes, %.1f%%\n", - inpFilename, - (size_t)ret.size_in, (size_t)ret.size_out, /* might overflow is size_t is 32 bits and size_{in,out} > 4 GB */ - (double)ret.size_out / ret.size_in * 100); - printf("compress : done\n"); - } - - /* decompress */ - { FILE* const inpFp = fopen(lz4Filename, "rb"); - FILE* const outFp = fopen(decFilename, "wb"); - - printf("decompress : %s -> %s\n", lz4Filename, decFilename); - int const ret = decompress_file(inpFp, outFp); - - fclose(outFp); - fclose(inpFp); - - if (ret) { - printf("decompress : failed with code %i\n", ret); - return ret; - } - printf("decompress : done\n"); - } - - /* verify */ - { FILE* const inpFp = fopen(inpFilename, "rb"); - FILE* const decFp = fopen(decFilename, "rb"); - - printf("verify : %s <-> %s\n", inpFilename, decFilename); - int const cmp = compareFiles(inpFp, decFp); - - fclose(decFp); - fclose(inpFp); - - if (cmp) { - printf("corruption detected : decompressed file differs from original\n"); - return cmp; - } - printf("verify : OK\n"); - } - - return 0; -} diff --git a/ta6ob/lz4/examples/printVersion.c b/ta6ob/lz4/examples/printVersion.c deleted file mode 100644 index 7af318a..0000000 --- a/ta6ob/lz4/examples/printVersion.c +++ /dev/null @@ -1,13 +0,0 @@ -// LZ4 trivial example : print Library version number -// by Takayuki Matsuoka - - -#include -#include "lz4.h" - -int main(int argc, char** argv) -{ - (void)argc; (void)argv; - printf("Hello World ! LZ4 Library version = %d\n", LZ4_versionNumber()); - return 0; -} diff --git a/ta6ob/lz4/examples/simple_buffer.c b/ta6ob/lz4/examples/simple_buffer.c deleted file mode 100644 index 6afc62a..0000000 --- a/ta6ob/lz4/examples/simple_buffer.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * simple_buffer.c - * Copyright : Kyle Harper - * License : Follows same licensing as the lz4.c/lz4.h program at any given time. Currently, BSD 2. - * Description: Example program to demonstrate the basic usage of the compress/decompress functions within lz4.c/lz4.h. - * The functions you'll likely want are LZ4_compress_default and LZ4_decompress_safe. - * Both of these are documented in the lz4.h header file; I recommend reading them. - */ - -/* Dependencies */ -#include // For printf() -#include // For memcmp() -#include // For exit() -#include "lz4.h" // This is all that is required to expose the prototypes for basic compression and decompression. - -/* - * Simple show-error-and-bail function. - */ -void run_screaming(const char* message, const int code) { - printf("%s \n", message); - exit(code); -} - - -/* - * main - */ -int main(void) { - /* Introduction */ - // Below we will have a Compression and Decompression section to demonstrate. - // There are a few important notes before we start: - // 1) The return codes of LZ4_ functions are important. - // Read lz4.h if you're unsure what a given code means. - // 2) LZ4 uses char* pointers in all LZ4_ functions. - // This is baked into the API and not going to change, for consistency. - // If your program uses different pointer types, - // you may need to do some casting or set the right -Wno compiler flags to ignore those warnings (e.g.: -Wno-pointer-sign). - - /* Compression */ - // We'll store some text into a variable pointed to by *src to be compressed later. - const char* const src = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor site amat."; - // The compression function needs to know how many bytes exist. Since we're using a string, we can use strlen() + 1 (for \0). - const int src_size = (int)(strlen(src) + 1); - // LZ4 provides a function that will tell you the maximum size of compressed output based on input data via LZ4_compressBound(). - const int max_dst_size = LZ4_compressBound(src_size); - // We will use that size for our destination boundary when allocating space. - char* compressed_data = malloc((size_t)max_dst_size); - if (compressed_data == NULL) - run_screaming("Failed to allocate memory for *compressed_data.", 1); - // That's all the information and preparation LZ4 needs to compress *src into *compressed_data. - // Invoke LZ4_compress_default now with our size values and pointers to our memory locations. - // Save the return value for error checking. - const int compressed_data_size = LZ4_compress_default(src, compressed_data, src_size, max_dst_size); - // Check return_value to determine what happened. - if (compressed_data_size <= 0) - run_screaming("A 0 or negative result from LZ4_compress_default() indicates a failure trying to compress the data. ", 1); - if (compressed_data_size > 0) - printf("We successfully compressed some data! Ratio: %.2f\n", - (float) compressed_data_size/src_size); - // Not only does a positive return_value mean success, the value returned == the number of bytes required. - // You can use this to realloc() *compress_data to free up memory, if desired. We'll do so just to demonstrate the concept. - compressed_data = (char *)realloc(compressed_data, (size_t)compressed_data_size); - if (compressed_data == NULL) - run_screaming("Failed to re-alloc memory for compressed_data. Sad :(", 1); - - - /* Decompression */ - // Now that we've successfully compressed the information from *src to *compressed_data, let's do the opposite! - // The decompression will need to know the compressed size, and an upper bound of the decompressed size. - // In this example, we just re-use this information from previous section, - // but in a real-world scenario, metadata must be transmitted to the decompression side. - // Each implementation is in charge of this part. Oftentimes, it adds some header of its own. - // Sometimes, the metadata can be extracted from the local context. - - // First, let's create a *new_src location of size src_size since we know that value. - char* const regen_buffer = malloc(src_size); - if (regen_buffer == NULL) - run_screaming("Failed to allocate memory for *regen_buffer.", 1); - // The LZ4_decompress_safe function needs to know where the compressed data is, how many bytes long it is, - // where the regen_buffer memory location is, and how large regen_buffer (uncompressed) output will be. - // Again, save the return_value. - const int decompressed_size = LZ4_decompress_safe(compressed_data, regen_buffer, compressed_data_size, src_size); - free(compressed_data); /* no longer useful */ - if (decompressed_size < 0) - run_screaming("A negative result from LZ4_decompress_safe indicates a failure trying to decompress the data. See exit code (echo $?) for value returned.", decompressed_size); - if (decompressed_size >= 0) - printf("We successfully decompressed some data!\n"); - // Not only does a positive return value mean success, - // value returned == number of bytes regenerated from compressed_data stream. - if (decompressed_size != src_size) - run_screaming("Decompressed data is different from original! \n", 1); - - /* Validation */ - // We should be able to compare our original *src with our *new_src and be byte-for-byte identical. - if (memcmp(src, regen_buffer, src_size) != 0) - run_screaming("Validation failed. *src and *new_src are not identical.", 1); - printf("Validation done. The string we ended up with is:\n%s\n", regen_buffer); - return 0; -} diff --git a/ta6ob/lz4/examples/streaming_api_basics.md b/ta6ob/lz4/examples/streaming_api_basics.md deleted file mode 100644 index 1ccc6e3..0000000 --- a/ta6ob/lz4/examples/streaming_api_basics.md +++ /dev/null @@ -1,87 +0,0 @@ -# LZ4 Streaming API Basics -by *Takayuki Matsuoka* -## LZ4 API sets - -LZ4 has the following API sets : - - - "Auto Framing" API (lz4frame.h) : - This is most recommended API for usual application. - It guarantees interoperability with other LZ4 framing format compliant tools/libraries - such as LZ4 command line utility, node-lz4, etc. - - "Block" API : This is recommended for simple purpose. - It compress single raw memory block to LZ4 memory block and vice versa. - - "Streaming" API : This is designed for complex things. - For example, compress huge stream data in restricted memory environment. - -Basically, you should use "Auto Framing" API. -But if you want to write advanced application, it's time to use Block or Streaming APIs. - - -## What is difference between Block and Streaming API ? - -Block API (de)compresses a single contiguous memory block. -In other words, LZ4 library finds redundancy from a single contiguous memory block. -Streaming API does same thing but (de)compresses multiple adjacent contiguous memory blocks. -So LZ4 library could find more redundancy than Block API. - -The following figure shows difference between API and block sizes. -In these figures, the original data is split into 4KiBytes contiguous chunks. - -``` -Original Data - +---------------+---------------+----+----+----+ - | 4KiB Chunk A | 4KiB Chunk B | C | D |... | - +---------------+---------------+----+----+----+ - -Example (1) : Block API, 4KiB Block - +---------------+---------------+----+----+----+ - | 4KiB Chunk A | 4KiB Chunk B | C | D |... | - +---------------+---------------+----+----+----+ - | Block #1 | Block #2 | #3 | #4 |... | - +---------------+---------------+----+----+----+ - - (No Dependency) - - -Example (2) : Block API, 8KiB Block - +---------------+---------------+----+----+----+ - | 4KiB Chunk A | 4KiB Chunk B | C | D |... | - +---------------+---------------+----+----+----+ - | Block #1 |Block #2 |... | - +--------------------+----------+-------+-+----+ - ^ | ^ | - | | | | - +--------------+ +----+ - Internal Dependency Internal Dependency - - -Example (3) : Streaming API, 4KiB Block - +---------------+---------------+-----+----+----+ - | 4KiB Chunk A | 4KiB Chunk B | C | D |... | - +---------------+---------------+-----+----+----+ - | Block #1 | Block #2 | #3 | #4 |... | - +---------------+----+----------+-+---+-+--+----+ - ^ | ^ | ^ | - | | | | | | - +--------------+ +--------+ +---+ - Dependency Dependency Dependency -``` - - - In example (1), there is no dependency. - All blocks are compressed independently. - - In example (2), naturally 8KiBytes block has internal dependency. - But still block #1 and #2 are compressed independently. - - In example (3), block #2 has dependency to #1, - also #3 has dependency to #2 and #1, #4 has #3, #2 and #1, and so on. - -Here, we can observe difference between example (2) and (3). -In (2), there's no dependency between chunk B and C, but (3) has dependency between B and C. -This dependency improves compression ratio. - - -## Restriction of Streaming API - -For efficiency, Streaming API doesn't keep a mirror copy of dependent (de)compressed memory. -This means users should keep these dependent (de)compressed memory explicitly. -Usually, "Dependent memory" is previous adjacent contiguous memory up to 64KiBytes. -LZ4 will not access further memories. diff --git a/ta6ob/lz4/lib/.gitignore b/ta6ob/lz4/lib/.gitignore deleted file mode 100644 index 5d6f134..0000000 --- a/ta6ob/lz4/lib/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# make install artefact -liblz4.pc diff --git a/ta6ob/lz4/lib/LICENSE b/ta6ob/lz4/lib/LICENSE deleted file mode 100644 index 74c2cdd..0000000 --- a/ta6ob/lz4/lib/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -LZ4 Library -Copyright (c) 2011-2016, Yann Collet -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/ta6ob/lz4/lib/Makefile b/ta6ob/lz4/lib/Makefile deleted file mode 100644 index c12949b..0000000 --- a/ta6ob/lz4/lib/Makefile +++ /dev/null @@ -1,217 +0,0 @@ -# ################################################################ -# LZ4 library - Makefile -# Copyright (C) Yann Collet 2011-2016 -# All rights reserved. -# -# This Makefile is validated for Linux, macOS, *BSD, Hurd, Solaris, MSYS2 targets -# -# BSD license -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, this -# list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# You can contact the author at : -# - LZ4 source repository : https://github.com/lz4/lz4 -# - LZ4 forum froup : https://groups.google.com/forum/#!forum/lz4c -# ################################################################ - -# Version numbers -LIBVER_MAJOR_SCRIPT:=`sed -n '/define LZ4_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ./lz4.h` -LIBVER_MINOR_SCRIPT:=`sed -n '/define LZ4_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ./lz4.h` -LIBVER_PATCH_SCRIPT:=`sed -n '/define LZ4_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < ./lz4.h` -LIBVER_SCRIPT:= $(LIBVER_MAJOR_SCRIPT).$(LIBVER_MINOR_SCRIPT).$(LIBVER_PATCH_SCRIPT) -LIBVER_MAJOR := $(shell echo $(LIBVER_MAJOR_SCRIPT)) -LIBVER_MINOR := $(shell echo $(LIBVER_MINOR_SCRIPT)) -LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT)) -LIBVER := $(shell echo $(LIBVER_SCRIPT)) - -BUILD_SHARED:=yes -BUILD_STATIC:=yes - -CPPFLAGS+= -DXXH_NAMESPACE=LZ4_ -CFLAGS ?= -O3 -DEBUGFLAGS:= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ - -Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes \ - -Wundef -Wpointer-arith -Wstrict-aliasing=1 -CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) -FLAGS = $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) - -SRCFILES := $(sort $(wildcard *.c)) - -include ../Makefile.inc - -# OS X linker doesn't support -soname, and use different extension -# see : https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html -ifeq ($(TARGET_OS), Darwin) - SHARED_EXT = dylib - SHARED_EXT_MAJOR = $(LIBVER_MAJOR).$(SHARED_EXT) - SHARED_EXT_VER = $(LIBVER).$(SHARED_EXT) - SONAME_FLAGS = -install_name $(libdir)/liblz4.$(SHARED_EXT_MAJOR) -compatibility_version $(LIBVER_MAJOR) -current_version $(LIBVER) -else - SONAME_FLAGS = -Wl,-soname=liblz4.$(SHARED_EXT).$(LIBVER_MAJOR) - SHARED_EXT = so - SHARED_EXT_MAJOR = $(SHARED_EXT).$(LIBVER_MAJOR) - SHARED_EXT_VER = $(SHARED_EXT).$(LIBVER) -endif - -.PHONY: default -default: lib-release - -lib-release: DEBUGFLAGS := -lib-release: lib - -lib: liblz4.a liblz4 - -all: lib - -all32: CFLAGS+=-m32 -all32: all - -liblz4.a: $(SRCFILES) -ifeq ($(BUILD_STATIC),yes) # can be disabled on command line - @echo compiling static library - $(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -c $^ - $(Q)$(AR) rcs $@ *.o -endif - -ifeq ($(WINBASED),yes) -liblz4-dll.rc: liblz4-dll.rc.in - @echo creating library resource - $(Q)sed -e 's|@LIBLZ4@|$(LIBLZ4)|' \ - -e 's|@LIBVER_MAJOR@|$(LIBVER_MAJOR)|g' \ - -e 's|@LIBVER_MINOR@|$(LIBVER_MINOR)|g' \ - -e 's|@LIBVER_PATCH@|$(LIBVER_PATCH)|g' \ - $< >$@ - -liblz4-dll.o: liblz4-dll.rc - $(WINDRES) -i liblz4-dll.rc -o liblz4-dll.o - -$(LIBLZ4): $(SRCFILES) liblz4-dll.o -else -$(LIBLZ4): $(SRCFILES) -endif -ifeq ($(BUILD_SHARED),yes) # can be disabled on command line - @echo compiling dynamic library $(LIBVER) - ifeq ($(WINBASED),yes) - $(Q)$(CC) $(FLAGS) -DLZ4_DLL_EXPORT=1 -shared $^ -o dll/$@.dll -Wl,--out-implib,dll/$(LIBLZ4_EXP) - else - $(Q)$(CC) $(FLAGS) -shared $^ -fPIC -fvisibility=hidden $(SONAME_FLAGS) -o $@ - @echo creating versioned links - $(Q)$(LN_SF) $@ liblz4.$(SHARED_EXT_MAJOR) - $(Q)$(LN_SF) $@ liblz4.$(SHARED_EXT) - endif -endif - -ifeq (,$(filter MINGW%,$(TARGET_OS))) -liblz4: $(LIBLZ4) -endif - -clean: -ifeq ($(WINBASED),yes) - $(Q)$(RM) *.rc -endif - $(Q)$(RM) core *.o liblz4.pc dll/$(LIBLZ4).dll dll/$(LIBLZ4_EXP) - $(Q)$(RM) *.a *.$(SHARED_EXT) *.$(SHARED_EXT_MAJOR) *.$(SHARED_EXT_VER) - @echo Cleaning library completed - -#----------------------------------------------------------------------------- -# make install is validated only for Linux, OSX, BSD, Hurd and Solaris targets -#----------------------------------------------------------------------------- -ifeq ($(POSIX_ENV),Yes) - -.PHONY: listL120 -listL120: # extract lines >= 120 characters in *.{c,h}, by Takayuki Matsuoka (note : $$, for Makefile compatibility) - find . -type f -name '*.c' -o -name '*.h' | while read -r filename; do awk 'length > 120 {print FILENAME "(" FNR "): " $$0}' $$filename; done - -DESTDIR ?= -# directory variables : GNU conventions prefer lowercase -# see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html -# support both lower and uppercase (BSD), use lower in script -PREFIX ?= /usr/local -prefix ?= $(PREFIX) -EXEC_PREFIX ?= $(prefix) -exec_prefix ?= $(EXEC_PREFIX) -BINDIR ?= $(exec_prefix)/bin -bindir ?= $(BINDIR) -LIBDIR ?= $(exec_prefix)/lib -libdir ?= $(LIBDIR) -INCLUDEDIR ?= $(prefix)/include -includedir ?= $(INCLUDEDIR) - - ifneq (,$(filter $(TARGET_OS),OpenBSD FreeBSD NetBSD DragonFly MidnightBSD)) -PKGCONFIGDIR ?= $(prefix)/libdata/pkgconfig - else -PKGCONFIGDIR ?= $(libdir)/pkgconfig - endif -pkgconfigdir ?= $(PKGCONFIGDIR) - -liblz4.pc: liblz4.pc.in Makefile - @echo creating pkgconfig - $(Q)sed -e 's|@PREFIX@|$(prefix)|' \ - -e 's|@LIBDIR@|$(libdir)|' \ - -e 's|@INCLUDEDIR@|$(includedir)|' \ - -e 's|@VERSION@|$(LIBVER)|' \ - $< >$@ - -install: lib liblz4.pc - $(Q)$(INSTALL_DIR) $(DESTDIR)$(pkgconfigdir)/ $(DESTDIR)$(includedir)/ $(DESTDIR)$(libdir)/ $(DESTDIR)$(bindir)/ - $(Q)$(INSTALL_DATA) liblz4.pc $(DESTDIR)$(pkgconfigdir)/ - @echo Installing libraries - ifeq ($(BUILD_STATIC),yes) - $(Q)$(INSTALL_DATA) liblz4.a $(DESTDIR)$(libdir)/liblz4.a - $(Q)$(INSTALL_DATA) lz4frame_static.h $(DESTDIR)$(includedir)/lz4frame_static.h - endif - ifeq ($(BUILD_SHARED),yes) -# Traditionnally, one installs the DLLs in the bin directory as programs -# search them first in their directory. This allows to not pollute system -# directories (like c:/windows/system32), nor modify the PATH variable. - ifeq ($(WINBASED),yes) - $(Q)$(INSTALL_PROGRAM) dll/$(LIBLZ4).dll $(DESTDIR)$(bindir) - $(Q)$(INSTALL_PROGRAM) dll/$(LIBLZ4_EXP) $(DESTDIR)$(libdir) - else - $(Q)$(INSTALL_PROGRAM) liblz4.$(SHARED_EXT_VER) $(DESTDIR)$(libdir) - $(Q)$(LN_SF) liblz4.$(SHARED_EXT_VER) $(DESTDIR)$(libdir)/liblz4.$(SHARED_EXT_MAJOR) - $(Q)$(LN_SF) liblz4.$(SHARED_EXT_VER) $(DESTDIR)$(libdir)/liblz4.$(SHARED_EXT) - endif - endif - @echo Installing headers in $(includedir) - $(Q)$(INSTALL_DATA) lz4.h $(DESTDIR)$(includedir)/lz4.h - $(Q)$(INSTALL_DATA) lz4hc.h $(DESTDIR)$(includedir)/lz4hc.h - $(Q)$(INSTALL_DATA) lz4frame.h $(DESTDIR)$(includedir)/lz4frame.h - @echo lz4 libraries installed - -uninstall: - $(Q)$(RM) $(DESTDIR)$(pkgconfigdir)/liblz4.pc - ifeq (WINBASED,1) - $(Q)$(RM) $(DESTDIR)$(bindir)/$(LIBLZ4).dll - $(Q)$(RM) $(DESTDIR)$(libdir)/$(LIBLZ4_EXP) - else - $(Q)$(RM) $(DESTDIR)$(libdir)/liblz4.$(SHARED_EXT) - $(Q)$(RM) $(DESTDIR)$(libdir)/liblz4.$(SHARED_EXT_MAJOR) - $(Q)$(RM) $(DESTDIR)$(libdir)/liblz4.$(SHARED_EXT_VER) - endif - $(Q)$(RM) $(DESTDIR)$(libdir)/liblz4.a - $(Q)$(RM) $(DESTDIR)$(includedir)/lz4.h - $(Q)$(RM) $(DESTDIR)$(includedir)/lz4hc.h - $(Q)$(RM) $(DESTDIR)$(includedir)/lz4frame.h - $(Q)$(RM) $(DESTDIR)$(includedir)/lz4frame_static.h - @echo lz4 libraries successfully uninstalled - -endif diff --git a/ta6ob/lz4/lib/README.md b/ta6ob/lz4/lib/README.md deleted file mode 100644 index e2af868..0000000 --- a/ta6ob/lz4/lib/README.md +++ /dev/null @@ -1,137 +0,0 @@ -LZ4 - Library Files -================================ - -The `/lib` directory contains many files, but depending on project's objectives, -not all of them are necessary. - -#### Minimal LZ4 build - -The minimum required is **`lz4.c`** and **`lz4.h`**, -which provides the fast compression and decompression algorithms. -They generate and decode data using the [LZ4 block format]. - - -#### High Compression variant - -For more compression ratio at the cost of compression speed, -the High Compression variant called **lz4hc** is available. -Add files **`lz4hc.c`** and **`lz4hc.h`**. -This variant also compresses data using the [LZ4 block format], -and depends on regular `lib/lz4.*` source files. - - -#### Frame support, for interoperability - -In order to produce compressed data compatible with `lz4` command line utility, -it's necessary to use the [official interoperable frame format]. -This format is generated and decoded automatically by the **lz4frame** library. -Its public API is described in `lib/lz4frame.h`. -In order to work properly, lz4frame needs all other modules present in `/lib`, -including, lz4 and lz4hc, and also **xxhash**. -So it's necessary to include all `*.c` and `*.h` files present in `/lib`. - - -#### Advanced / Experimental API - -Definitions which are not guaranteed to remain stable in future versions, -are protected behind macros, such as `LZ4_STATIC_LINKING_ONLY`. -As the name strongly implies, these definitions should only be invoked -in the context of static linking ***only***. -Otherwise, dependent application may fail on API or ABI break in the future. -The associated symbols are also not exposed by the dynamic library by default. -Should they be nonetheless needed, it's possible to force their publication -by using build macros `LZ4_PUBLISH_STATIC_FUNCTIONS` -and `LZ4F_PUBLISH_STATIC_FUNCTIONS`. - - -#### Build macros - -The following build macro can be selected to adjust source code behavior at compilation time : - -- `LZ4_FAST_DEC_LOOP` : this triggers a speed optimized decompression loop, more powerful on modern cpus. - This loop works great on `x86`, `x64` and `aarch64` cpus, and is automatically enabled for them. - It's also possible to enable or disable it manually, by passing `LZ4_FAST_DEC_LOOP=1` or `0` to the preprocessor. - For example, with `gcc` : `-DLZ4_FAST_DEC_LOOP=1`, - and with `make` : `CPPFLAGS+=-DLZ4_FAST_DEC_LOOP=1 make lz4`. - -- `LZ4_DISTANCE_MAX` : control the maximum offset that the compressor will allow. - Set to 65535 by default, which is the maximum value supported by lz4 format. - Reducing maximum distance will reduce opportunities for LZ4 to find matches, - hence will produce a worse compression ratio. - However, a smaller max distance can allow compatibility with specific decoders using limited memory budget. - This build macro only influences the compressed output of the compressor. - -- `LZ4_DISABLE_DEPRECATE_WARNINGS` : invoking a deprecated function will make the compiler generate a warning. - This is meant to invite users to update their source code. - Should this be a problem, it's generally possible to make the compiler ignore these warnings, - for example with `-Wno-deprecated-declarations` on `gcc`, - or `_CRT_SECURE_NO_WARNINGS` for Visual Studio. - This build macro offers another project-specific method - by defining `LZ4_DISABLE_DEPRECATE_WARNINGS` before including the LZ4 header files. - -- `LZ4_USER_MEMORY_FUNCTIONS` : replace calls to 's `malloc`, `calloc` and `free` - by user-defined functions, which must be called `LZ4_malloc()`, `LZ4_calloc()` and `LZ4_free()`. - User functions must be available at link time. - -- `LZ4_FORCE_SW_BITCOUNT` : by default, the compression algorithm tries to determine lengths - by using bitcount instructions, generally implemented as fast single instructions in many cpus. - In case the target cpus doesn't support it, or compiler intrinsic doesn't work, or feature bad performance, - it's possible to use an optimized software path instead. - This is achieved by setting this build macros . - In most cases, it's not expected to be necessary, - but it can be legitimately considered for less common platforms. - -- `LZ4_ALIGN_TEST` : alignment test ensures that the memory area - passed as argument to become a compression state is suitably aligned. - This test can be disabled if it proves flaky, by setting this value to 0. - - -#### Amalgamation - -lz4 source code can be amalgamated into a single file. -One can combine all source code into `lz4_all.c` by using following command: -``` -cat lz4.c lz4hc.c lz4frame.c > lz4_all.c -``` -(`cat` file order is important) then compile `lz4_all.c`. -All `*.h` files present in `/lib` remain necessary to compile `lz4_all.c`. - - -#### Windows : using MinGW+MSYS to create DLL - -DLL can be created using MinGW+MSYS with the `make liblz4` command. -This command creates `dll\liblz4.dll` and the import library `dll\liblz4.lib`. -To override the `dlltool` command when cross-compiling on Linux, just set the `DLLTOOL` variable. Example of cross compilation on Linux with mingw-w64 64 bits: -``` -make BUILD_STATIC=no CC=x86_64-w64-mingw32-gcc DLLTOOL=x86_64-w64-mingw32-dlltool OS=Windows_NT -``` -The import library is only required with Visual C++. -The header files `lz4.h`, `lz4hc.h`, `lz4frame.h` and the dynamic library -`dll\liblz4.dll` are required to compile a project using gcc/MinGW. -The dynamic library has to be added to linking options. -It means that if a project that uses LZ4 consists of a single `test-dll.c` -file it should be linked with `dll\liblz4.dll`. For example: -``` - $(CC) $(CFLAGS) -Iinclude/ test-dll.c -o test-dll dll\liblz4.dll -``` -The compiled executable will require LZ4 DLL which is available at `dll\liblz4.dll`. - - -#### Miscellaneous - -Other files present in the directory are not source code. They are : - - - `LICENSE` : contains the BSD license text - - `Makefile` : `make` script to compile and install lz4 library (static and dynamic) - - `liblz4.pc.in` : for `pkg-config` (used in `make install`) - - `README.md` : this file - -[official interoperable frame format]: ../doc/lz4_Frame_format.md -[LZ4 block format]: ../doc/lz4_Block_format.md - - -#### License - -All source material within __lib__ directory are BSD 2-Clause licensed. -See [LICENSE](LICENSE) for details. -The license is also reminded at the top of each source file. diff --git a/ta6ob/lz4/lib/dll/example/Makefile b/ta6ob/lz4/lib/dll/example/Makefile deleted file mode 100644 index e987956..0000000 --- a/ta6ob/lz4/lib/dll/example/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -# ########################################################################## -# LZ4 programs - Makefile -# Copyright (C) Yann Collet 2016 -# -# GPL v2 License -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# You can contact the author at : -# - LZ4 homepage : http://www.lz4.org -# - LZ4 source repository : https://github.com/lz4/lz4 -# ########################################################################## - -VOID := /dev/null -LZ4DIR := ../include -LIBDIR := ../static -DLLDIR := ../dll - -CFLAGS ?= -O3 # can select custom flags. For example : CFLAGS="-O2 -g" make -CFLAGS += -Wall -Wextra -Wundef -Wcast-qual -Wcast-align -Wshadow -Wswitch-enum \ - -Wdeclaration-after-statement -Wstrict-prototypes \ - -Wpointer-arith -Wstrict-aliasing=1 -CFLAGS += $(MOREFLAGS) -CPPFLAGS:= -I$(LZ4DIR) -DXXH_NAMESPACE=LZ4_ -FLAGS := $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) - - -# Define *.exe as extension for Windows systems -ifneq (,$(filter Windows%,$(OS))) -EXT =.exe -else -EXT = -endif - -.PHONY: default fullbench-dll fullbench-lib - - -default: all - -all: fullbench-dll fullbench-lib - - -fullbench-lib: fullbench.c xxhash.c - $(CC) $(FLAGS) $^ -o $@$(EXT) $(LIBDIR)/liblz4_static.lib - -fullbench-dll: fullbench.c xxhash.c - $(CC) $(FLAGS) $^ -o $@$(EXT) -DLZ4_DLL_IMPORT=1 $(DLLDIR)/liblz4.dll - -clean: - @$(RM) fullbench-dll$(EXT) fullbench-lib$(EXT) \ - @echo Cleaning completed diff --git a/ta6ob/lz4/lib/dll/example/README.md b/ta6ob/lz4/lib/dll/example/README.md deleted file mode 100644 index 223e473..0000000 --- a/ta6ob/lz4/lib/dll/example/README.md +++ /dev/null @@ -1,69 +0,0 @@ -LZ4 Windows binary package -==================================== - -#### The package contents - -- `lz4.exe` : Command Line Utility, supporting gzip-like arguments -- `dll\liblz4.dll` : The DLL of LZ4 library -- `dll\liblz4.lib` : The import library of LZ4 library for Visual C++ -- `example\` : The example of usage of LZ4 library -- `include\` : Header files required with LZ4 library -- `static\liblz4_static.lib` : The static LZ4 library - - -#### Usage of Command Line Interface - -Command Line Interface (CLI) supports gzip-like arguments. -By default CLI takes an input file and compresses it to an output file: -``` - Usage: lz4 [arg] [input] [output] -``` -The full list of commands for CLI can be obtained with `-h` or `-H`. The ratio can -be improved with commands from `-3` to `-16` but higher levels also have slower -compression. CLI includes in-memory compression benchmark module with compression -levels starting from `-b` and ending with `-e` with iteration time of `-i` seconds. -CLI supports aggregation of parameters i.e. `-b1`, `-e18`, and `-i1` can be joined -into `-b1e18i1`. - - -#### The example of usage of static and dynamic LZ4 libraries with gcc/MinGW - -Use `cd example` and `make` to build `fullbench-dll` and `fullbench-lib`. -`fullbench-dll` uses a dynamic LZ4 library from the `dll` directory. -`fullbench-lib` uses a static LZ4 library from the `lib` directory. - - -#### Using LZ4 DLL with gcc/MinGW - -The header files from `include\` and the dynamic library `dll\liblz4.dll` -are required to compile a project using gcc/MinGW. -The dynamic library has to be added to linking options. -It means that if a project that uses LZ4 consists of a single `test-dll.c` -file it should be linked with `dll\liblz4.dll`. For example: -``` - gcc $(CFLAGS) -Iinclude\ test-dll.c -o test-dll dll\liblz4.dll -``` -The compiled executable will require LZ4 DLL which is available at `dll\liblz4.dll`. - - -#### The example of usage of static and dynamic LZ4 libraries with Visual C++ - -Open `example\fullbench-dll.sln` to compile `fullbench-dll` that uses a -dynamic LZ4 library from the `dll` directory. The solution works with Visual C++ -2010 or newer. When one will open the solution with Visual C++ newer than 2010 -then the solution will upgraded to the current version. - - -#### Using LZ4 DLL with Visual C++ - -The header files from `include\` and the import library `dll\liblz4.lib` -are required to compile a project using Visual C++. - -1. The header files should be added to `Additional Include Directories` that can - be found in project properties `C/C++` then `General`. -2. The import library has to be added to `Additional Dependencies` that can - be found in project properties `Linker` then `Input`. - If one will provide only the name `liblz4.lib` without a full path to the library - the directory has to be added to `Linker\General\Additional Library Directories`. - -The compiled executable will require LZ4 DLL which is available at `dll\liblz4.dll`. diff --git a/ta6ob/lz4/lib/dll/example/fullbench-dll.sln b/ta6ob/lz4/lib/dll/example/fullbench-dll.sln deleted file mode 100644 index 72e302e..0000000 --- a/ta6ob/lz4/lib/dll/example/fullbench-dll.sln +++ /dev/null @@ -1,25 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2012 for Windows Desktop -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fullbench-dll", "fullbench-dll.vcxproj", "{13992FD2-077E-4954-B065-A428198201A9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {13992FD2-077E-4954-B065-A428198201A9}.Debug|Win32.ActiveCfg = Debug|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|Win32.Build.0 = Debug|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|x64.ActiveCfg = Debug|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Debug|x64.Build.0 = Debug|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Release|Win32.ActiveCfg = Release|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Release|Win32.Build.0 = Release|Win32 - {13992FD2-077E-4954-B065-A428198201A9}.Release|x64.ActiveCfg = Release|x64 - {13992FD2-077E-4954-B065-A428198201A9}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/ta6ob/lz4/lib/dll/example/fullbench-dll.vcxproj b/ta6ob/lz4/lib/dll/example/fullbench-dll.vcxproj deleted file mode 100644 index cdb5534..0000000 --- a/ta6ob/lz4/lib/dll/example/fullbench-dll.vcxproj +++ /dev/null @@ -1,182 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {13992FD2-077E-4954-B065-A428198201A9} - Win32Proj - fullbench-dll - $(SolutionDir)bin\$(Platform)_$(Configuration)\ - $(SolutionDir)bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - true - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - - - false - $(IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath); - true - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - false - ..\include - - - Console - true - $(SolutionDir)..\dll;%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - false - - - - - - - Level4 - Disabled - WIN32;_DEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - true - true - /analyze:stacksize295252 %(AdditionalOptions) - ..\include - - - Console - true - $(SolutionDir)..\dll;%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - false - ..\include - - - Console - true - true - true - $(SolutionDir)..\dll;%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - false - - - - - Level4 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;LZ4_DLL_IMPORT=1;%(PreprocessorDefinitions) - false - true - /analyze:stacksize295252 %(AdditionalOptions) - ..\include - - - Console - true - true - true - $(SolutionDir)..\dll;%(AdditionalLibraryDirectories) - liblz4.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ta6ob/lz4/lib/liblz4-dll.rc.in b/ta6ob/lz4/lib/liblz4-dll.rc.in deleted file mode 100644 index bf9adf5..0000000 --- a/ta6ob/lz4/lib/liblz4-dll.rc.in +++ /dev/null @@ -1,35 +0,0 @@ -#include - -// DLL version information. -1 VERSIONINFO -FILEVERSION @LIBVER_MAJOR@,@LIBVER_MINOR@,@LIBVER_PATCH@,0 -PRODUCTVERSION @LIBVER_MAJOR@,@LIBVER_MINOR@,@LIBVER_PATCH@,0 -FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG | VS_FF_PRERELEASE -#else - FILEFLAGS 0 -#endif -FILEOS VOS_NT_WINDOWS32 -FILETYPE VFT_DLL -FILESUBTYPE VFT2_UNKNOWN -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "Yann Collet" - VALUE "FileDescription", "Extremely fast compression" - VALUE "FileVersion", "@LIBVER_MAJOR@.@LIBVER_MINOR@.@LIBVER_PATCH@.0" - VALUE "InternalName", "@LIBLZ4@" - VALUE "LegalCopyright", "Copyright (C) 2013-2016, Yann Collet" - VALUE "OriginalFilename", "@LIBLZ4@.dll" - VALUE "ProductName", "LZ4" - VALUE "ProductVersion", "@LIBVER_MAJOR@.@LIBVER_MINOR@.@LIBVER_PATCH@.0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1200 - END -END diff --git a/ta6ob/lz4/lib/liblz4.pc.in b/ta6ob/lz4/lib/liblz4.pc.in deleted file mode 100644 index cb31cd7..0000000 --- a/ta6ob/lz4/lib/liblz4.pc.in +++ /dev/null @@ -1,14 +0,0 @@ -# LZ4 - Fast LZ compression algorithm -# Copyright (C) 2011-2014, Yann Collet. -# BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - -prefix=@PREFIX@ -libdir=@LIBDIR@ -includedir=@INCLUDEDIR@ - -Name: lz4 -Description: extremely fast lossless compression algorithm library -URL: http://www.lz4.org/ -Version: @VERSION@ -Libs: -L@LIBDIR@ -llz4 -Cflags: -I@INCLUDEDIR@ diff --git a/ta6ob/lz4/lib/lz4.c b/ta6ob/lz4/lib/lz4.c deleted file mode 100644 index 9f5e9bf..0000000 --- a/ta6ob/lz4/lib/lz4.c +++ /dev/null @@ -1,2495 +0,0 @@ -/* - LZ4 - Fast LZ compression algorithm - Copyright (C) 2011-present, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - LZ4 homepage : http://www.lz4.org - - LZ4 source repository : https://github.com/lz4/lz4 -*/ - -/*-************************************ -* Tuning parameters -**************************************/ -/* - * LZ4_HEAPMODE : - * Select how default compression functions will allocate memory for their hash table, - * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). - */ -#ifndef LZ4_HEAPMODE -# define LZ4_HEAPMODE 0 -#endif - -/* - * LZ4_ACCELERATION_DEFAULT : - * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0 - */ -#define LZ4_ACCELERATION_DEFAULT 1 -/* - * LZ4_ACCELERATION_MAX : - * Any "acceleration" value higher than this threshold - * get treated as LZ4_ACCELERATION_MAX instead (fix #876) - */ -#define LZ4_ACCELERATION_MAX 65537 - - -/*-************************************ -* CPU Feature Detection -**************************************/ -/* LZ4_FORCE_MEMORY_ACCESS - * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. - * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. - * The below switch allow to select different access method for improved performance. - * Method 0 (default) : use `memcpy()`. Safe and portable. - * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). - * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. - * Method 2 : direct access. This method is portable but violate C standard. - * It can generate buggy code on targets which assembly generation depends on alignment. - * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) - * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. - * Prefer these methods in priority order (0 > 1 > 2) - */ -#ifndef LZ4_FORCE_MEMORY_ACCESS /* can be defined externally */ -# if defined(__GNUC__) && \ - ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) \ - || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) -# define LZ4_FORCE_MEMORY_ACCESS 2 -# elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || defined(__GNUC__) -# define LZ4_FORCE_MEMORY_ACCESS 1 -# endif -#endif - -/* - * LZ4_FORCE_SW_BITCOUNT - * Define this parameter if your target system or compiler does not support hardware bit count - */ -#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for WinCE doesn't support Hardware bit count */ -# undef LZ4_FORCE_SW_BITCOUNT /* avoid double def */ -# define LZ4_FORCE_SW_BITCOUNT -#endif - - - -/*-************************************ -* Dependency -**************************************/ -/* - * LZ4_SRC_INCLUDED: - * Amalgamation flag, whether lz4.c is included - */ -#ifndef LZ4_SRC_INCLUDED -# define LZ4_SRC_INCLUDED 1 -#endif - -#ifndef LZ4_STATIC_LINKING_ONLY -#define LZ4_STATIC_LINKING_ONLY -#endif - -#ifndef LZ4_DISABLE_DEPRECATE_WARNINGS -#define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */ -#endif - -#define LZ4_STATIC_LINKING_ONLY /* LZ4_DISTANCE_MAX */ -#include "lz4.h" -/* see also "memory routines" below */ - - -/*-************************************ -* Compiler Options -**************************************/ -#if defined(_MSC_VER) && (_MSC_VER >= 1400) /* Visual Studio 2005+ */ -# include /* only present in VS2005+ */ -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#endif /* _MSC_VER */ - -#ifndef LZ4_FORCE_INLINE -# ifdef _MSC_VER /* Visual Studio */ -# define LZ4_FORCE_INLINE static __forceinline -# else -# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -# ifdef __GNUC__ -# define LZ4_FORCE_INLINE static inline __attribute__((always_inline)) -# else -# define LZ4_FORCE_INLINE static inline -# endif -# else -# define LZ4_FORCE_INLINE static -# endif /* __STDC_VERSION__ */ -# endif /* _MSC_VER */ -#endif /* LZ4_FORCE_INLINE */ - -/* LZ4_FORCE_O2 and LZ4_FORCE_INLINE - * gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy8, - * together with a simple 8-byte copy loop as a fall-back path. - * However, this optimization hurts the decompression speed by >30%, - * because the execution does not go to the optimized loop - * for typical compressible data, and all of the preamble checks - * before going to the fall-back path become useless overhead. - * This optimization happens only with the -O3 flag, and -O2 generates - * a simple 8-byte copy loop. - * With gcc on ppc64le, all of the LZ4_decompress_* and LZ4_wildCopy8 - * functions are annotated with __attribute__((optimize("O2"))), - * and also LZ4_wildCopy8 is forcibly inlined, so that the O2 attribute - * of LZ4_wildCopy8 does not affect the compression speed. - */ -#if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) && defined(__GNUC__) && !defined(__clang__) -# define LZ4_FORCE_O2 __attribute__((optimize("O2"))) -# undef LZ4_FORCE_INLINE -# define LZ4_FORCE_INLINE static __inline __attribute__((optimize("O2"),always_inline)) -#else -# define LZ4_FORCE_O2 -#endif - -#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) -# define expect(expr,value) (__builtin_expect ((expr),(value)) ) -#else -# define expect(expr,value) (expr) -#endif - -#ifndef likely -#define likely(expr) expect((expr) != 0, 1) -#endif -#ifndef unlikely -#define unlikely(expr) expect((expr) != 0, 0) -#endif - -/* Should the alignment test prove unreliable, for some reason, - * it can be disabled by setting LZ4_ALIGN_TEST to 0 */ -#ifndef LZ4_ALIGN_TEST /* can be externally provided */ -# define LZ4_ALIGN_TEST 1 -#endif - - -/*-************************************ -* Memory routines -**************************************/ -#ifdef LZ4_USER_MEMORY_FUNCTIONS -/* memory management functions can be customized by user project. - * Below functions must exist somewhere in the Project - * and be available at link time */ -void* LZ4_malloc(size_t s); -void* LZ4_calloc(size_t n, size_t s); -void LZ4_free(void* p); -# define ALLOC(s) LZ4_malloc(s) -# define ALLOC_AND_ZERO(s) LZ4_calloc(1,s) -# define FREEMEM(p) LZ4_free(p) -#else -# include /* malloc, calloc, free */ -# define ALLOC(s) malloc(s) -# define ALLOC_AND_ZERO(s) calloc(1,s) -# define FREEMEM(p) free(p) -#endif - -#include /* memset, memcpy */ -#define MEM_INIT(p,v,s) memset((p),(v),(s)) - - -/*-************************************ -* Common Constants -**************************************/ -#define MINMATCH 4 - -#define WILDCOPYLENGTH 8 -#define LASTLITERALS 5 /* see ../doc/lz4_Block_format.md#parsing-restrictions */ -#define MFLIMIT 12 /* see ../doc/lz4_Block_format.md#parsing-restrictions */ -#define MATCH_SAFEGUARD_DISTANCE ((2*WILDCOPYLENGTH) - MINMATCH) /* ensure it's possible to write 2 x wildcopyLength without overflowing output buffer */ -#define FASTLOOP_SAFE_DISTANCE 64 -static const int LZ4_minLength = (MFLIMIT+1); - -#define KB *(1 <<10) -#define MB *(1 <<20) -#define GB *(1U<<30) - -#define LZ4_DISTANCE_ABSOLUTE_MAX 65535 -#if (LZ4_DISTANCE_MAX > LZ4_DISTANCE_ABSOLUTE_MAX) /* max supported by LZ4 format */ -# error "LZ4_DISTANCE_MAX is too big : must be <= 65535" -#endif - -#define ML_BITS 4 -#define ML_MASK ((1U<=1) -# include -#else -# ifndef assert -# define assert(condition) ((void)0) -# endif -#endif - -#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use after variable declarations */ - -#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2) -# include - static int g_debuglog_enable = 1; -# define DEBUGLOG(l, ...) { \ - if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \ - fprintf(stderr, __FILE__ ": "); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, " \n"); \ - } } -#else -# define DEBUGLOG(l, ...) {} /* disabled */ -#endif - -static int LZ4_isAligned(const void* ptr, size_t alignment) -{ - return ((size_t)ptr & (alignment -1)) == 0; -} - - -/*-************************************ -* Types -**************************************/ -#include -#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -# include - typedef uint8_t BYTE; - typedef uint16_t U16; - typedef uint32_t U32; - typedef int32_t S32; - typedef uint64_t U64; - typedef uintptr_t uptrval; -#else -# if UINT_MAX != 4294967295UL -# error "LZ4 code (when not C++ or C99) assumes that sizeof(int) == 4" -# endif - typedef unsigned char BYTE; - typedef unsigned short U16; - typedef unsigned int U32; - typedef signed int S32; - typedef unsigned long long U64; - typedef size_t uptrval; /* generally true, except OpenVMS-64 */ -#endif - -#if defined(__x86_64__) - typedef U64 reg_t; /* 64-bits in x32 mode */ -#else - typedef size_t reg_t; /* 32-bits in x32 mode */ -#endif - -typedef enum { - notLimited = 0, - limitedOutput = 1, - fillOutput = 2 -} limitedOutput_directive; - - -/*-************************************ -* Reading and writing into memory -**************************************/ - -/** - * LZ4 relies on memcpy with a constant size being inlined. In freestanding - * environments, the compiler can't assume the implementation of memcpy() is - * standard compliant, so it can't apply its specialized memcpy() inlining - * logic. When possible, use __builtin_memcpy() to tell the compiler to analyze - * memcpy() as if it were standard compliant, so it can inline it in freestanding - * environments. This is needed when decompressing the Linux Kernel, for example. - */ -#if defined(__GNUC__) && (__GNUC__ >= 4) -#define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size) -#else -#define LZ4_memcpy(dst, src, size) memcpy(dst, src, size) -#endif - -static unsigned LZ4_isLittleEndian(void) -{ - const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ - return one.c[0]; -} - - -#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2) -/* lie to the compiler about data alignment; use with caution */ - -static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; } -static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; } -static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; } - -static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } -static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } - -#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1) - -/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ -/* currently only defined for gcc and icc */ -typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign; - -static U16 LZ4_read16(const void* ptr) { return ((const unalign*)ptr)->u16; } -static U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } -static reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; } - -static void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; } -static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; } - -#else /* safe and portable access using memcpy() */ - -static U16 LZ4_read16(const void* memPtr) -{ - U16 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val; -} - -static U32 LZ4_read32(const void* memPtr) -{ - U32 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val; -} - -static reg_t LZ4_read_ARCH(const void* memPtr) -{ - reg_t val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val; -} - -static void LZ4_write16(void* memPtr, U16 value) -{ - LZ4_memcpy(memPtr, &value, sizeof(value)); -} - -static void LZ4_write32(void* memPtr, U32 value) -{ - LZ4_memcpy(memPtr, &value, sizeof(value)); -} - -#endif /* LZ4_FORCE_MEMORY_ACCESS */ - - -static U16 LZ4_readLE16(const void* memPtr) -{ - if (LZ4_isLittleEndian()) { - return LZ4_read16(memPtr); - } else { - const BYTE* p = (const BYTE*)memPtr; - return (U16)((U16)p[0] + (p[1]<<8)); - } -} - -static void LZ4_writeLE16(void* memPtr, U16 value) -{ - if (LZ4_isLittleEndian()) { - LZ4_write16(memPtr, value); - } else { - BYTE* p = (BYTE*)memPtr; - p[0] = (BYTE) value; - p[1] = (BYTE)(value>>8); - } -} - -/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */ -LZ4_FORCE_INLINE -void LZ4_wildCopy8(void* dstPtr, const void* srcPtr, void* dstEnd) -{ - BYTE* d = (BYTE*)dstPtr; - const BYTE* s = (const BYTE*)srcPtr; - BYTE* const e = (BYTE*)dstEnd; - - do { LZ4_memcpy(d,s,8); d+=8; s+=8; } while (d= 16. */ -LZ4_FORCE_INLINE void -LZ4_wildCopy32(void* dstPtr, const void* srcPtr, void* dstEnd) -{ - BYTE* d = (BYTE*)dstPtr; - const BYTE* s = (const BYTE*)srcPtr; - BYTE* const e = (BYTE*)dstEnd; - - do { LZ4_memcpy(d,s,16); LZ4_memcpy(d+16,s+16,16); d+=32; s+=32; } while (d= dstPtr + MINMATCH - * - there is at least 8 bytes available to write after dstEnd */ -LZ4_FORCE_INLINE void -LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset) -{ - BYTE v[8]; - - assert(dstEnd >= dstPtr + MINMATCH); - - switch(offset) { - case 1: - MEM_INIT(v, *srcPtr, 8); - break; - case 2: - LZ4_memcpy(v, srcPtr, 2); - LZ4_memcpy(&v[2], srcPtr, 2); - LZ4_memcpy(&v[4], v, 4); - break; - case 4: - LZ4_memcpy(v, srcPtr, 4); - LZ4_memcpy(&v[4], srcPtr, 4); - break; - default: - LZ4_memcpy_using_offset_base(dstPtr, srcPtr, dstEnd, offset); - return; - } - - LZ4_memcpy(dstPtr, v, 8); - dstPtr += 8; - while (dstPtr < dstEnd) { - LZ4_memcpy(dstPtr, v, 8); - dstPtr += 8; - } -} -#endif - - -/*-************************************ -* Common functions -**************************************/ -static unsigned LZ4_NbCommonBytes (reg_t val) -{ - assert(val != 0); - if (LZ4_isLittleEndian()) { - if (sizeof(val) == 8) { -# if defined(_MSC_VER) && (_MSC_VER >= 1800) && defined(_M_AMD64) && !defined(LZ4_FORCE_SW_BITCOUNT) - /* x64 CPUS without BMI support interpret `TZCNT` as `REP BSF` */ - return (unsigned)_tzcnt_u64(val) >> 3; -# elif defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r = 0; - _BitScanForward64(&r, (U64)val); - return (unsigned)r >> 3; -# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ - ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ - !defined(LZ4_FORCE_SW_BITCOUNT) - return (unsigned)__builtin_ctzll((U64)val) >> 3; -# else - const U64 m = 0x0101010101010101ULL; - val ^= val - 1; - return (unsigned)(((U64)((val & (m - 1)) * m)) >> 56); -# endif - } else /* 32 bits */ { -# if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r; - _BitScanForward(&r, (U32)val); - return (unsigned)r >> 3; -# elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ - ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ - !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (unsigned)__builtin_ctz((U32)val) >> 3; -# else - const U32 m = 0x01010101; - return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24; -# endif - } - } else /* Big Endian CPU */ { - if (sizeof(val)==8) { -# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ - ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ - !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (unsigned)__builtin_clzll((U64)val) >> 3; -# else -#if 1 - /* this method is probably faster, - * but adds a 128 bytes lookup table */ - static const unsigned char ctz7_tab[128] = { - 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - }; - U64 const mask = 0x0101010101010101ULL; - U64 const t = (((val >> 8) - mask) | val) & mask; - return ctz7_tab[(t * 0x0080402010080402ULL) >> 57]; -#else - /* this method doesn't consume memory space like the previous one, - * but it contains several branches, - * that may end up slowing execution */ - static const U32 by32 = sizeof(val)*4; /* 32 on 64 bits (goal), 16 on 32 bits. - Just to avoid some static analyzer complaining about shift by 32 on 32-bits target. - Note that this code path is never triggered in 32-bits mode. */ - unsigned r; - if (!(val>>by32)) { r=4; } else { r=0; val>>=by32; } - if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } - r += (!val); - return r; -#endif -# endif - } else /* 32 bits */ { -# if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ - ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ - !defined(LZ4_FORCE_SW_BITCOUNT) - return (unsigned)__builtin_clz((U32)val) >> 3; -# else - val >>= 8; - val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) | - (val + 0x00FF0000)) >> 24; - return (unsigned)val ^ 3; -# endif - } - } -} - - -#define STEPSIZE sizeof(reg_t) -LZ4_FORCE_INLINE -unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) -{ - const BYTE* const pStart = pIn; - - if (likely(pIn < pInLimit-(STEPSIZE-1))) { - reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); - if (!diff) { - pIn+=STEPSIZE; pMatch+=STEPSIZE; - } else { - return LZ4_NbCommonBytes(diff); - } } - - while (likely(pIn < pInLimit-(STEPSIZE-1))) { - reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); - if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; } - pIn += LZ4_NbCommonBytes(diff); - return (unsigned)(pIn - pStart); - } - - if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; } - if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; } - if ((pIn compression run slower on incompressible data */ - - -/*-************************************ -* Local Structures and types -**************************************/ -typedef enum { clearedTable = 0, byPtr, byU32, byU16 } tableType_t; - -/** - * This enum distinguishes several different modes of accessing previous - * content in the stream. - * - * - noDict : There is no preceding content. - * - withPrefix64k : Table entries up to ctx->dictSize before the current blob - * blob being compressed are valid and refer to the preceding - * content (of length ctx->dictSize), which is available - * contiguously preceding in memory the content currently - * being compressed. - * - usingExtDict : Like withPrefix64k, but the preceding content is somewhere - * else in memory, starting at ctx->dictionary with length - * ctx->dictSize. - * - usingDictCtx : Like usingExtDict, but everything concerning the preceding - * content is in a separate context, pointed to by - * ctx->dictCtx. ctx->dictionary, ctx->dictSize, and table - * entries in the current context that refer to positions - * preceding the beginning of the current compression are - * ignored. Instead, ctx->dictCtx->dictionary and ctx->dictCtx - * ->dictSize describe the location and size of the preceding - * content, and matches are found by looking in the ctx - * ->dictCtx->hashTable. - */ -typedef enum { noDict = 0, withPrefix64k, usingExtDict, usingDictCtx } dict_directive; -typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; - - -/*-************************************ -* Local Utils -**************************************/ -int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; } -const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; } -int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } -int LZ4_sizeofState(void) { return LZ4_STREAMSIZE; } - - -/*-************************************ -* Internal Definitions used in Tests -**************************************/ -#if defined (__cplusplus) -extern "C" { -#endif - -int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize); - -int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, - int compressedSize, int maxOutputSize, - const void* dictStart, size_t dictSize); - -#if defined (__cplusplus) -} -#endif - -/*-****************************** -* Compression functions -********************************/ -LZ4_FORCE_INLINE U32 LZ4_hash4(U32 sequence, tableType_t const tableType) -{ - if (tableType == byU16) - return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); - else - return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); -} - -LZ4_FORCE_INLINE U32 LZ4_hash5(U64 sequence, tableType_t const tableType) -{ - const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; - if (LZ4_isLittleEndian()) { - const U64 prime5bytes = 889523592379ULL; - return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog)); - } else { - const U64 prime8bytes = 11400714785074694791ULL; - return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog)); - } -} - -LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType) -{ - if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType); - return LZ4_hash4(LZ4_read32(p), tableType); -} - -LZ4_FORCE_INLINE void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType) -{ - switch (tableType) - { - default: /* fallthrough */ - case clearedTable: { /* illegal! */ assert(0); return; } - case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = NULL; return; } - case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = 0; return; } - case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = 0; return; } - } -} - -LZ4_FORCE_INLINE void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType) -{ - switch (tableType) - { - default: /* fallthrough */ - case clearedTable: /* fallthrough */ - case byPtr: { /* illegal! */ assert(0); return; } - case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = idx; return; } - case byU16: { U16* hashTable = (U16*) tableBase; assert(idx < 65536); hashTable[h] = (U16)idx; return; } - } -} - -LZ4_FORCE_INLINE void LZ4_putPositionOnHash(const BYTE* p, U32 h, - void* tableBase, tableType_t const tableType, - const BYTE* srcBase) -{ - switch (tableType) - { - case clearedTable: { /* illegal! */ assert(0); return; } - case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; } - case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; } - case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; } - } -} - -LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) -{ - U32 const h = LZ4_hashPosition(p, tableType); - LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); -} - -/* LZ4_getIndexOnHash() : - * Index of match position registered in hash table. - * hash position must be calculated by using base+index, or dictBase+index. - * Assumption 1 : only valid if tableType == byU32 or byU16. - * Assumption 2 : h is presumed valid (within limits of hash table) - */ -LZ4_FORCE_INLINE U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType) -{ - LZ4_STATIC_ASSERT(LZ4_MEMORY_USAGE > 2); - if (tableType == byU32) { - const U32* const hashTable = (const U32*) tableBase; - assert(h < (1U << (LZ4_MEMORY_USAGE-2))); - return hashTable[h]; - } - if (tableType == byU16) { - const U16* const hashTable = (const U16*) tableBase; - assert(h < (1U << (LZ4_MEMORY_USAGE-1))); - return hashTable[h]; - } - assert(0); return 0; /* forbidden case */ -} - -static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType_t tableType, const BYTE* srcBase) -{ - if (tableType == byPtr) { const BYTE* const* hashTable = (const BYTE* const*) tableBase; return hashTable[h]; } - if (tableType == byU32) { const U32* const hashTable = (const U32*) tableBase; return hashTable[h] + srcBase; } - { const U16* const hashTable = (const U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ -} - -LZ4_FORCE_INLINE const BYTE* -LZ4_getPosition(const BYTE* p, - const void* tableBase, tableType_t tableType, - const BYTE* srcBase) -{ - U32 const h = LZ4_hashPosition(p, tableType); - return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); -} - -LZ4_FORCE_INLINE void -LZ4_prepareTable(LZ4_stream_t_internal* const cctx, - const int inputSize, - const tableType_t tableType) { - /* If the table hasn't been used, it's guaranteed to be zeroed out, and is - * therefore safe to use no matter what mode we're in. Otherwise, we figure - * out if it's safe to leave as is or whether it needs to be reset. - */ - if ((tableType_t)cctx->tableType != clearedTable) { - assert(inputSize >= 0); - if ((tableType_t)cctx->tableType != tableType - || ((tableType == byU16) && cctx->currentOffset + (unsigned)inputSize >= 0xFFFFU) - || ((tableType == byU32) && cctx->currentOffset > 1 GB) - || tableType == byPtr - || inputSize >= 4 KB) - { - DEBUGLOG(4, "LZ4_prepareTable: Resetting table in %p", cctx); - MEM_INIT(cctx->hashTable, 0, LZ4_HASHTABLESIZE); - cctx->currentOffset = 0; - cctx->tableType = (U32)clearedTable; - } else { - DEBUGLOG(4, "LZ4_prepareTable: Re-use hash table (no reset)"); - } - } - - /* Adding a gap, so all previous entries are > LZ4_DISTANCE_MAX back, is faster - * than compressing without a gap. However, compressing with - * currentOffset == 0 is faster still, so we preserve that case. - */ - if (cctx->currentOffset != 0 && tableType == byU32) { - DEBUGLOG(5, "LZ4_prepareTable: adding 64KB to currentOffset"); - cctx->currentOffset += 64 KB; - } - - /* Finally, clear history */ - cctx->dictCtx = NULL; - cctx->dictionary = NULL; - cctx->dictSize = 0; -} - -/** LZ4_compress_generic() : - * inlined, to ensure branches are decided at compilation time. - * Presumed already validated at this stage: - * - source != NULL - * - inputSize > 0 - */ -LZ4_FORCE_INLINE int LZ4_compress_generic_validated( - LZ4_stream_t_internal* const cctx, - const char* const source, - char* const dest, - const int inputSize, - int *inputConsumed, /* only written when outputDirective == fillOutput */ - const int maxOutputSize, - const limitedOutput_directive outputDirective, - const tableType_t tableType, - const dict_directive dictDirective, - const dictIssue_directive dictIssue, - const int acceleration) -{ - int result; - const BYTE* ip = (const BYTE*) source; - - U32 const startIndex = cctx->currentOffset; - const BYTE* base = (const BYTE*) source - startIndex; - const BYTE* lowLimit; - - const LZ4_stream_t_internal* dictCtx = (const LZ4_stream_t_internal*) cctx->dictCtx; - const BYTE* const dictionary = - dictDirective == usingDictCtx ? dictCtx->dictionary : cctx->dictionary; - const U32 dictSize = - dictDirective == usingDictCtx ? dictCtx->dictSize : cctx->dictSize; - const U32 dictDelta = (dictDirective == usingDictCtx) ? startIndex - dictCtx->currentOffset : 0; /* make indexes in dictCtx comparable with index in current context */ - - int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx); - U32 const prefixIdxLimit = startIndex - dictSize; /* used when dictDirective == dictSmall */ - const BYTE* const dictEnd = dictionary ? dictionary + dictSize : dictionary; - const BYTE* anchor = (const BYTE*) source; - const BYTE* const iend = ip + inputSize; - const BYTE* const mflimitPlusOne = iend - MFLIMIT + 1; - const BYTE* const matchlimit = iend - LASTLITERALS; - - /* the dictCtx currentOffset is indexed on the start of the dictionary, - * while a dictionary in the current context precedes the currentOffset */ - const BYTE* dictBase = !dictionary ? NULL : (dictDirective == usingDictCtx) ? - dictionary + dictSize - dictCtx->currentOffset : - dictionary + dictSize - startIndex; - - BYTE* op = (BYTE*) dest; - BYTE* const olimit = op + maxOutputSize; - - U32 offset = 0; - U32 forwardH; - - DEBUGLOG(5, "LZ4_compress_generic_validated: srcSize=%i, tableType=%u", inputSize, tableType); - assert(ip != NULL); - /* If init conditions are not met, we don't have to mark stream - * as having dirty context, since no action was taken yet */ - if (outputDirective == fillOutput && maxOutputSize < 1) { return 0; } /* Impossible to store anything */ - if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) { return 0; } /* Size too large (not within 64K limit) */ - if (tableType==byPtr) assert(dictDirective==noDict); /* only supported use case with byPtr */ - assert(acceleration >= 1); - - lowLimit = (const BYTE*)source - (dictDirective == withPrefix64k ? dictSize : 0); - - /* Update context state */ - if (dictDirective == usingDictCtx) { - /* Subsequent linked blocks can't use the dictionary. */ - /* Instead, they use the block we just compressed. */ - cctx->dictCtx = NULL; - cctx->dictSize = (U32)inputSize; - } else { - cctx->dictSize += (U32)inputSize; - } - cctx->currentOffset += (U32)inputSize; - cctx->tableType = (U32)tableType; - - if (inputSizehashTable, tableType, base); - ip++; forwardH = LZ4_hashPosition(ip, tableType); - - /* Main Loop */ - for ( ; ; ) { - const BYTE* match; - BYTE* token; - const BYTE* filledIp; - - /* Find a match */ - if (tableType == byPtr) { - const BYTE* forwardIp = ip; - int step = 1; - int searchMatchNb = acceleration << LZ4_skipTrigger; - do { - U32 const h = forwardH; - ip = forwardIp; - forwardIp += step; - step = (searchMatchNb++ >> LZ4_skipTrigger); - - if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals; - assert(ip < mflimitPlusOne); - - match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base); - forwardH = LZ4_hashPosition(forwardIp, tableType); - LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base); - - } while ( (match+LZ4_DISTANCE_MAX < ip) - || (LZ4_read32(match) != LZ4_read32(ip)) ); - - } else { /* byU32, byU16 */ - - const BYTE* forwardIp = ip; - int step = 1; - int searchMatchNb = acceleration << LZ4_skipTrigger; - do { - U32 const h = forwardH; - U32 const current = (U32)(forwardIp - base); - U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType); - assert(matchIndex <= current); - assert(forwardIp - base < (ptrdiff_t)(2 GB - 1)); - ip = forwardIp; - forwardIp += step; - step = (searchMatchNb++ >> LZ4_skipTrigger); - - if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals; - assert(ip < mflimitPlusOne); - - if (dictDirective == usingDictCtx) { - if (matchIndex < startIndex) { - /* there was no match, try the dictionary */ - assert(tableType == byU32); - matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32); - match = dictBase + matchIndex; - matchIndex += dictDelta; /* make dictCtx index comparable with current context */ - lowLimit = dictionary; - } else { - match = base + matchIndex; - lowLimit = (const BYTE*)source; - } - } else if (dictDirective==usingExtDict) { - if (matchIndex < startIndex) { - DEBUGLOG(7, "extDict candidate: matchIndex=%5u < startIndex=%5u", matchIndex, startIndex); - assert(startIndex - matchIndex >= MINMATCH); - match = dictBase + matchIndex; - lowLimit = dictionary; - } else { - match = base + matchIndex; - lowLimit = (const BYTE*)source; - } - } else { /* single continuous memory segment */ - match = base + matchIndex; - } - forwardH = LZ4_hashPosition(forwardIp, tableType); - LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType); - - DEBUGLOG(7, "candidate at pos=%u (offset=%u \n", matchIndex, current - matchIndex); - if ((dictIssue == dictSmall) && (matchIndex < prefixIdxLimit)) { continue; } /* match outside of valid area */ - assert(matchIndex < current); - if ( ((tableType != byU16) || (LZ4_DISTANCE_MAX < LZ4_DISTANCE_ABSOLUTE_MAX)) - && (matchIndex+LZ4_DISTANCE_MAX < current)) { - continue; - } /* too far */ - assert((current - matchIndex) <= LZ4_DISTANCE_MAX); /* match now expected within distance */ - - if (LZ4_read32(match) == LZ4_read32(ip)) { - if (maybe_extMem) offset = current - matchIndex; - break; /* match found */ - } - - } while(1); - } - - /* Catch up */ - filledIp = ip; - while (((ip>anchor) & (match > lowLimit)) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } - - /* Encode Literals */ - { unsigned const litLength = (unsigned)(ip - anchor); - token = op++; - if ((outputDirective == limitedOutput) && /* Check output buffer overflow */ - (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)) ) { - return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */ - } - if ((outputDirective == fillOutput) && - (unlikely(op + (litLength+240)/255 /* litlen */ + litLength /* literals */ + 2 /* offset */ + 1 /* token */ + MFLIMIT - MINMATCH /* min last literals so last match is <= end - MFLIMIT */ > olimit))) { - op--; - goto _last_literals; - } - if (litLength >= RUN_MASK) { - int len = (int)(litLength - RUN_MASK); - *token = (RUN_MASK<= 255 ; len-=255) *op++ = 255; - *op++ = (BYTE)len; - } - else *token = (BYTE)(litLength< olimit)) { - /* the match was too close to the end, rewind and go to last literals */ - op = token; - goto _last_literals; - } - - /* Encode Offset */ - if (maybe_extMem) { /* static test */ - DEBUGLOG(6, " with offset=%u (ext if > %i)", offset, (int)(ip - (const BYTE*)source)); - assert(offset <= LZ4_DISTANCE_MAX && offset > 0); - LZ4_writeLE16(op, (U16)offset); op+=2; - } else { - DEBUGLOG(6, " with offset=%u (same segment)", (U32)(ip - match)); - assert(ip-match <= LZ4_DISTANCE_MAX); - LZ4_writeLE16(op, (U16)(ip - match)); op+=2; - } - - /* Encode MatchLength */ - { unsigned matchCode; - - if ( (dictDirective==usingExtDict || dictDirective==usingDictCtx) - && (lowLimit==dictionary) /* match within extDict */ ) { - const BYTE* limit = ip + (dictEnd-match); - assert(dictEnd > match); - if (limit > matchlimit) limit = matchlimit; - matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); - ip += (size_t)matchCode + MINMATCH; - if (ip==limit) { - unsigned const more = LZ4_count(limit, (const BYTE*)source, matchlimit); - matchCode += more; - ip += more; - } - DEBUGLOG(6, " with matchLength=%u starting in extDict", matchCode+MINMATCH); - } else { - matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); - ip += (size_t)matchCode + MINMATCH; - DEBUGLOG(6, " with matchLength=%u", matchCode+MINMATCH); - } - - if ((outputDirective) && /* Check output buffer overflow */ - (unlikely(op + (1 + LASTLITERALS) + (matchCode+240)/255 > olimit)) ) { - if (outputDirective == fillOutput) { - /* Match description too long : reduce it */ - U32 newMatchCode = 15 /* in token */ - 1 /* to avoid needing a zero byte */ + ((U32)(olimit - op) - 1 - LASTLITERALS) * 255; - ip -= matchCode - newMatchCode; - assert(newMatchCode < matchCode); - matchCode = newMatchCode; - if (unlikely(ip <= filledIp)) { - /* We have already filled up to filledIp so if ip ends up less than filledIp - * we have positions in the hash table beyond the current position. This is - * a problem if we reuse the hash table. So we have to remove these positions - * from the hash table. - */ - const BYTE* ptr; - DEBUGLOG(5, "Clearing %u positions", (U32)(filledIp - ip)); - for (ptr = ip; ptr <= filledIp; ++ptr) { - U32 const h = LZ4_hashPosition(ptr, tableType); - LZ4_clearHash(h, cctx->hashTable, tableType); - } - } - } else { - assert(outputDirective == limitedOutput); - return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */ - } - } - if (matchCode >= ML_MASK) { - *token += ML_MASK; - matchCode -= ML_MASK; - LZ4_write32(op, 0xFFFFFFFF); - while (matchCode >= 4*255) { - op+=4; - LZ4_write32(op, 0xFFFFFFFF); - matchCode -= 4*255; - } - op += matchCode / 255; - *op++ = (BYTE)(matchCode % 255); - } else - *token += (BYTE)(matchCode); - } - /* Ensure we have enough space for the last literals. */ - assert(!(outputDirective == fillOutput && op + 1 + LASTLITERALS > olimit)); - - anchor = ip; - - /* Test end of chunk */ - if (ip >= mflimitPlusOne) break; - - /* Fill table */ - LZ4_putPosition(ip-2, cctx->hashTable, tableType, base); - - /* Test next position */ - if (tableType == byPtr) { - - match = LZ4_getPosition(ip, cctx->hashTable, tableType, base); - LZ4_putPosition(ip, cctx->hashTable, tableType, base); - if ( (match+LZ4_DISTANCE_MAX >= ip) - && (LZ4_read32(match) == LZ4_read32(ip)) ) - { token=op++; *token=0; goto _next_match; } - - } else { /* byU32, byU16 */ - - U32 const h = LZ4_hashPosition(ip, tableType); - U32 const current = (U32)(ip-base); - U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType); - assert(matchIndex < current); - if (dictDirective == usingDictCtx) { - if (matchIndex < startIndex) { - /* there was no match, try the dictionary */ - matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32); - match = dictBase + matchIndex; - lowLimit = dictionary; /* required for match length counter */ - matchIndex += dictDelta; - } else { - match = base + matchIndex; - lowLimit = (const BYTE*)source; /* required for match length counter */ - } - } else if (dictDirective==usingExtDict) { - if (matchIndex < startIndex) { - match = dictBase + matchIndex; - lowLimit = dictionary; /* required for match length counter */ - } else { - match = base + matchIndex; - lowLimit = (const BYTE*)source; /* required for match length counter */ - } - } else { /* single memory segment */ - match = base + matchIndex; - } - LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType); - assert(matchIndex < current); - if ( ((dictIssue==dictSmall) ? (matchIndex >= prefixIdxLimit) : 1) - && (((tableType==byU16) && (LZ4_DISTANCE_MAX == LZ4_DISTANCE_ABSOLUTE_MAX)) ? 1 : (matchIndex+LZ4_DISTANCE_MAX >= current)) - && (LZ4_read32(match) == LZ4_read32(ip)) ) { - token=op++; - *token=0; - if (maybe_extMem) offset = current - matchIndex; - DEBUGLOG(6, "seq.start:%i, literals=%u, match.start:%i", - (int)(anchor-(const BYTE*)source), 0, (int)(ip-(const BYTE*)source)); - goto _next_match; - } - } - - /* Prepare next loop */ - forwardH = LZ4_hashPosition(++ip, tableType); - - } - -_last_literals: - /* Encode Last Literals */ - { size_t lastRun = (size_t)(iend - anchor); - if ( (outputDirective) && /* Check output buffer overflow */ - (op + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > olimit)) { - if (outputDirective == fillOutput) { - /* adapt lastRun to fill 'dst' */ - assert(olimit >= op); - lastRun = (size_t)(olimit-op) - 1/*token*/; - lastRun -= (lastRun + 256 - RUN_MASK) / 256; /*additional length tokens*/ - } else { - assert(outputDirective == limitedOutput); - return 0; /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */ - } - } - DEBUGLOG(6, "Final literal run : %i literals", (int)lastRun); - if (lastRun >= RUN_MASK) { - size_t accumulator = lastRun - RUN_MASK; - *op++ = RUN_MASK << ML_BITS; - for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; - *op++ = (BYTE) accumulator; - } else { - *op++ = (BYTE)(lastRun< 0); - DEBUGLOG(5, "LZ4_compress_generic: compressed %i bytes into %i bytes", inputSize, result); - return result; -} - -/** LZ4_compress_generic() : - * inlined, to ensure branches are decided at compilation time; - * takes care of src == (NULL, 0) - * and forward the rest to LZ4_compress_generic_validated */ -LZ4_FORCE_INLINE int LZ4_compress_generic( - LZ4_stream_t_internal* const cctx, - const char* const src, - char* const dst, - const int srcSize, - int *inputConsumed, /* only written when outputDirective == fillOutput */ - const int dstCapacity, - const limitedOutput_directive outputDirective, - const tableType_t tableType, - const dict_directive dictDirective, - const dictIssue_directive dictIssue, - const int acceleration) -{ - DEBUGLOG(5, "LZ4_compress_generic: srcSize=%i, dstCapacity=%i", - srcSize, dstCapacity); - - if ((U32)srcSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; } /* Unsupported srcSize, too large (or negative) */ - if (srcSize == 0) { /* src == NULL supported if srcSize == 0 */ - if (outputDirective != notLimited && dstCapacity <= 0) return 0; /* no output, can't write anything */ - DEBUGLOG(5, "Generating an empty block"); - assert(outputDirective == notLimited || dstCapacity >= 1); - assert(dst != NULL); - dst[0] = 0; - if (outputDirective == fillOutput) { - assert (inputConsumed != NULL); - *inputConsumed = 0; - } - return 1; - } - assert(src != NULL); - - return LZ4_compress_generic_validated(cctx, src, dst, srcSize, - inputConsumed, /* only written into if outputDirective == fillOutput */ - dstCapacity, outputDirective, - tableType, dictDirective, dictIssue, acceleration); -} - - -int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) -{ - LZ4_stream_t_internal* const ctx = & LZ4_initStream(state, sizeof(LZ4_stream_t)) -> internal_donotuse; - assert(ctx != NULL); - if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT; - if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX; - if (maxOutputSize >= LZ4_compressBound(inputSize)) { - if (inputSize < LZ4_64Klimit) { - return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, byU16, noDict, noDictIssue, acceleration); - } else { - const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32; - return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration); - } - } else { - if (inputSize < LZ4_64Klimit) { - return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); - } else { - const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32; - return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, noDict, noDictIssue, acceleration); - } - } -} - -/** - * LZ4_compress_fast_extState_fastReset() : - * A variant of LZ4_compress_fast_extState(). - * - * Using this variant avoids an expensive initialization step. It is only safe - * to call if the state buffer is known to be correctly initialized already - * (see comment in lz4.h on LZ4_resetStream_fast() for a definition of - * "correctly initialized"). - */ -int LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration) -{ - LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse; - if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT; - if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX; - - if (dstCapacity >= LZ4_compressBound(srcSize)) { - if (srcSize < LZ4_64Klimit) { - const tableType_t tableType = byU16; - LZ4_prepareTable(ctx, srcSize, tableType); - if (ctx->currentOffset) { - return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, dictSmall, acceleration); - } else { - return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration); - } - } else { - const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32; - LZ4_prepareTable(ctx, srcSize, tableType); - return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration); - } - } else { - if (srcSize < LZ4_64Klimit) { - const tableType_t tableType = byU16; - LZ4_prepareTable(ctx, srcSize, tableType); - if (ctx->currentOffset) { - return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, dictSmall, acceleration); - } else { - return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration); - } - } else { - const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32; - LZ4_prepareTable(ctx, srcSize, tableType); - return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration); - } - } -} - - -int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) -{ - int result; -#if (LZ4_HEAPMODE) - LZ4_stream_t* ctxPtr = ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ - if (ctxPtr == NULL) return 0; -#else - LZ4_stream_t ctx; - LZ4_stream_t* const ctxPtr = &ctx; -#endif - result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); - -#if (LZ4_HEAPMODE) - FREEMEM(ctxPtr); -#endif - return result; -} - - -int LZ4_compress_default(const char* src, char* dst, int srcSize, int maxOutputSize) -{ - return LZ4_compress_fast(src, dst, srcSize, maxOutputSize, 1); -} - - -/* Note!: This function leaves the stream in an unclean/broken state! - * It is not safe to subsequently use the same state with a _fastReset() or - * _continue() call without resetting it. */ -static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) -{ - void* const s = LZ4_initStream(state, sizeof (*state)); - assert(s != NULL); (void)s; - - if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */ - return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); - } else { - if (*srcSizePtr < LZ4_64Klimit) { - return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, byU16, noDict, noDictIssue, 1); - } else { - tableType_t const addrMode = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32; - return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, addrMode, noDict, noDictIssue, 1); - } } -} - - -int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) -{ -#if (LZ4_HEAPMODE) - LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ - if (ctx == NULL) return 0; -#else - LZ4_stream_t ctxBody; - LZ4_stream_t* ctx = &ctxBody; -#endif - - int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); - -#if (LZ4_HEAPMODE) - FREEMEM(ctx); -#endif - return result; -} - - - -/*-****************************** -* Streaming functions -********************************/ - -LZ4_stream_t* LZ4_createStream(void) -{ - LZ4_stream_t* const lz4s = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t)); - LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */ - DEBUGLOG(4, "LZ4_createStream %p", lz4s); - if (lz4s == NULL) return NULL; - LZ4_initStream(lz4s, sizeof(*lz4s)); - return lz4s; -} - -static size_t LZ4_stream_t_alignment(void) -{ -#if LZ4_ALIGN_TEST - typedef struct { char c; LZ4_stream_t t; } t_a; - return sizeof(t_a) - sizeof(LZ4_stream_t); -#else - return 1; /* effectively disabled */ -#endif -} - -LZ4_stream_t* LZ4_initStream (void* buffer, size_t size) -{ - DEBUGLOG(5, "LZ4_initStream"); - if (buffer == NULL) { return NULL; } - if (size < sizeof(LZ4_stream_t)) { return NULL; } - if (!LZ4_isAligned(buffer, LZ4_stream_t_alignment())) return NULL; - MEM_INIT(buffer, 0, sizeof(LZ4_stream_t_internal)); - return (LZ4_stream_t*)buffer; -} - -/* resetStream is now deprecated, - * prefer initStream() which is more general */ -void LZ4_resetStream (LZ4_stream_t* LZ4_stream) -{ - DEBUGLOG(5, "LZ4_resetStream (ctx:%p)", LZ4_stream); - MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t_internal)); -} - -void LZ4_resetStream_fast(LZ4_stream_t* ctx) { - LZ4_prepareTable(&(ctx->internal_donotuse), 0, byU32); -} - -int LZ4_freeStream (LZ4_stream_t* LZ4_stream) -{ - if (!LZ4_stream) return 0; /* support free on NULL */ - DEBUGLOG(5, "LZ4_freeStream %p", LZ4_stream); - FREEMEM(LZ4_stream); - return (0); -} - - -#define HASH_UNIT sizeof(reg_t) -int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) -{ - LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse; - const tableType_t tableType = byU32; - const BYTE* p = (const BYTE*)dictionary; - const BYTE* const dictEnd = p + dictSize; - const BYTE* base; - - DEBUGLOG(4, "LZ4_loadDict (%i bytes from %p into %p)", dictSize, dictionary, LZ4_dict); - - /* It's necessary to reset the context, - * and not just continue it with prepareTable() - * to avoid any risk of generating overflowing matchIndex - * when compressing using this dictionary */ - LZ4_resetStream(LZ4_dict); - - /* We always increment the offset by 64 KB, since, if the dict is longer, - * we truncate it to the last 64k, and if it's shorter, we still want to - * advance by a whole window length so we can provide the guarantee that - * there are only valid offsets in the window, which allows an optimization - * in LZ4_compress_fast_continue() where it uses noDictIssue even when the - * dictionary isn't a full 64k. */ - dict->currentOffset += 64 KB; - - if (dictSize < (int)HASH_UNIT) { - return 0; - } - - if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB; - base = dictEnd - dict->currentOffset; - dict->dictionary = p; - dict->dictSize = (U32)(dictEnd - p); - dict->tableType = (U32)tableType; - - while (p <= dictEnd-HASH_UNIT) { - LZ4_putPosition(p, dict->hashTable, tableType, base); - p+=3; - } - - return (int)dict->dictSize; -} - -void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream) { - const LZ4_stream_t_internal* dictCtx = dictionaryStream == NULL ? NULL : - &(dictionaryStream->internal_donotuse); - - DEBUGLOG(4, "LZ4_attach_dictionary (%p, %p, size %u)", - workingStream, dictionaryStream, - dictCtx != NULL ? dictCtx->dictSize : 0); - - if (dictCtx != NULL) { - /* If the current offset is zero, we will never look in the - * external dictionary context, since there is no value a table - * entry can take that indicate a miss. In that case, we need - * to bump the offset to something non-zero. - */ - if (workingStream->internal_donotuse.currentOffset == 0) { - workingStream->internal_donotuse.currentOffset = 64 KB; - } - - /* Don't actually attach an empty dictionary. - */ - if (dictCtx->dictSize == 0) { - dictCtx = NULL; - } - } - workingStream->internal_donotuse.dictCtx = dictCtx; -} - - -static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, int nextSize) -{ - assert(nextSize >= 0); - if (LZ4_dict->currentOffset + (unsigned)nextSize > 0x80000000) { /* potential ptrdiff_t overflow (32-bits mode) */ - /* rescale hash table */ - U32 const delta = LZ4_dict->currentOffset - 64 KB; - const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize; - int i; - DEBUGLOG(4, "LZ4_renormDictT"); - for (i=0; ihashTable[i] < delta) LZ4_dict->hashTable[i]=0; - else LZ4_dict->hashTable[i] -= delta; - } - LZ4_dict->currentOffset = 64 KB; - if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB; - LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize; - } -} - - -int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, - const char* source, char* dest, - int inputSize, int maxOutputSize, - int acceleration) -{ - const tableType_t tableType = byU32; - LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse; - const BYTE* dictEnd = streamPtr->dictionary + streamPtr->dictSize; - - DEBUGLOG(5, "LZ4_compress_fast_continue (inputSize=%i)", inputSize); - - LZ4_renormDictT(streamPtr, inputSize); /* avoid index overflow */ - if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT; - if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX; - - /* invalidate tiny dictionaries */ - if ( (streamPtr->dictSize-1 < 4-1) /* intentional underflow */ - && (dictEnd != (const BYTE*)source) ) { - DEBUGLOG(5, "LZ4_compress_fast_continue: dictSize(%u) at addr:%p is too small", streamPtr->dictSize, streamPtr->dictionary); - streamPtr->dictSize = 0; - streamPtr->dictionary = (const BYTE*)source; - dictEnd = (const BYTE*)source; - } - - /* Check overlapping input/dictionary space */ - { const BYTE* sourceEnd = (const BYTE*) source + inputSize; - if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) { - streamPtr->dictSize = (U32)(dictEnd - sourceEnd); - if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB; - if (streamPtr->dictSize < 4) streamPtr->dictSize = 0; - streamPtr->dictionary = dictEnd - streamPtr->dictSize; - } - } - - /* prefix mode : source data follows dictionary */ - if (dictEnd == (const BYTE*)source) { - if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) - return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, dictSmall, acceleration); - else - return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, noDictIssue, acceleration); - } - - /* external dictionary mode */ - { int result; - if (streamPtr->dictCtx) { - /* We depend here on the fact that dictCtx'es (produced by - * LZ4_loadDict) guarantee that their tables contain no references - * to offsets between dictCtx->currentOffset - 64 KB and - * dictCtx->currentOffset - dictCtx->dictSize. This makes it safe - * to use noDictIssue even when the dict isn't a full 64 KB. - */ - if (inputSize > 4 KB) { - /* For compressing large blobs, it is faster to pay the setup - * cost to copy the dictionary's tables into the active context, - * so that the compression loop is only looking into one table. - */ - LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(*streamPtr)); - result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration); - } else { - result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration); - } - } else { - if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) { - result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, dictSmall, acceleration); - } else { - result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration); - } - } - streamPtr->dictionary = (const BYTE*)source; - streamPtr->dictSize = (U32)inputSize; - return result; - } -} - - -/* Hidden debug function, to force-test external dictionary mode */ -int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize) -{ - LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse; - int result; - - LZ4_renormDictT(streamPtr, srcSize); - - if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) { - result = LZ4_compress_generic(streamPtr, source, dest, srcSize, NULL, 0, notLimited, byU32, usingExtDict, dictSmall, 1); - } else { - result = LZ4_compress_generic(streamPtr, source, dest, srcSize, NULL, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); - } - - streamPtr->dictionary = (const BYTE*)source; - streamPtr->dictSize = (U32)srcSize; - - return result; -} - - -/*! LZ4_saveDict() : - * If previously compressed data block is not guaranteed to remain available at its memory location, - * save it into a safer place (char* safeBuffer). - * Note : you don't need to call LZ4_loadDict() afterwards, - * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue(). - * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. - */ -int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) -{ - LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse; - const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize; - - if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */ - if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; } - - if (safeBuffer == NULL) assert(dictSize == 0); - if (dictSize > 0) - memmove(safeBuffer, previousDictEnd - dictSize, dictSize); - - dict->dictionary = (const BYTE*)safeBuffer; - dict->dictSize = (U32)dictSize; - - return dictSize; -} - - - -/*-******************************* - * Decompression functions - ********************************/ - -typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; -typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive; - -#undef MIN -#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) - -/* Read the variable-length literal or match length. - * - * ip - pointer to use as input. - * lencheck - end ip. Return an error if ip advances >= lencheck. - * loop_check - check ip >= lencheck in body of loop. Returns loop_error if so. - * initial_check - check ip >= lencheck before start of loop. Returns initial_error if so. - * error (output) - error code. Should be set to 0 before call. - */ -typedef enum { loop_error = -2, initial_error = -1, ok = 0 } variable_length_error; -LZ4_FORCE_INLINE unsigned -read_variable_length(const BYTE**ip, const BYTE* lencheck, - int loop_check, int initial_check, - variable_length_error* error) -{ - U32 length = 0; - U32 s; - if (initial_check && unlikely((*ip) >= lencheck)) { /* overflow detection */ - *error = initial_error; - return length; - } - do { - s = **ip; - (*ip)++; - length += s; - if (loop_check && unlikely((*ip) >= lencheck)) { /* overflow detection */ - *error = loop_error; - return length; - } - } while (s==255); - - return length; -} - -/*! LZ4_decompress_generic() : - * This generic decompression function covers all use cases. - * It shall be instantiated several times, using different sets of directives. - * Note that it is important for performance that this function really get inlined, - * in order to remove useless branches during compilation optimization. - */ -LZ4_FORCE_INLINE int -LZ4_decompress_generic( - const char* const src, - char* const dst, - int srcSize, - int outputSize, /* If endOnInput==endOnInputSize, this value is `dstCapacity` */ - - endCondition_directive endOnInput, /* endOnOutputSize, endOnInputSize */ - earlyEnd_directive partialDecoding, /* full, partial */ - dict_directive dict, /* noDict, withPrefix64k, usingExtDict */ - const BYTE* const lowPrefix, /* always <= dst, == dst when no prefix */ - const BYTE* const dictStart, /* only if dict==usingExtDict */ - const size_t dictSize /* note : = 0 if noDict */ - ) -{ - if (src == NULL) { return -1; } - - { const BYTE* ip = (const BYTE*) src; - const BYTE* const iend = ip + srcSize; - - BYTE* op = (BYTE*) dst; - BYTE* const oend = op + outputSize; - BYTE* cpy; - - const BYTE* const dictEnd = (dictStart == NULL) ? NULL : dictStart + dictSize; - - const int safeDecode = (endOnInput==endOnInputSize); - const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); - - - /* Set up the "end" pointers for the shortcut. */ - const BYTE* const shortiend = iend - (endOnInput ? 14 : 8) /*maxLL*/ - 2 /*offset*/; - const BYTE* const shortoend = oend - (endOnInput ? 14 : 8) /*maxLL*/ - 18 /*maxML*/; - - const BYTE* match; - size_t offset; - unsigned token; - size_t length; - - - DEBUGLOG(5, "LZ4_decompress_generic (srcSize:%i, dstSize:%i)", srcSize, outputSize); - - /* Special cases */ - assert(lowPrefix <= op); - if ((endOnInput) && (unlikely(outputSize==0))) { - /* Empty output buffer */ - if (partialDecoding) return 0; - return ((srcSize==1) && (*ip==0)) ? 0 : -1; - } - if ((!endOnInput) && (unlikely(outputSize==0))) { return (*ip==0 ? 1 : -1); } - if ((endOnInput) && unlikely(srcSize==0)) { return -1; } - - /* Currently the fast loop shows a regression on qualcomm arm chips. */ -#if LZ4_FAST_DEC_LOOP - if ((oend - op) < FASTLOOP_SAFE_DISTANCE) { - DEBUGLOG(6, "skip fast decode loop"); - goto safe_decode; - } - - /* Fast loop : decode sequences as long as output < iend-FASTLOOP_SAFE_DISTANCE */ - while (1) { - /* Main fastloop assertion: We can always wildcopy FASTLOOP_SAFE_DISTANCE */ - assert(oend - op >= FASTLOOP_SAFE_DISTANCE); - if (endOnInput) { assert(ip < iend); } - token = *ip++; - length = token >> ML_BITS; /* literal length */ - - assert(!endOnInput || ip <= iend); /* ip < iend before the increment */ - - /* decode literal length */ - if (length == RUN_MASK) { - variable_length_error error = ok; - length += read_variable_length(&ip, iend-RUN_MASK, (int)endOnInput, (int)endOnInput, &error); - if (error == initial_error) { goto _output_error; } - if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */ - if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */ - - /* copy literals */ - cpy = op+length; - LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); - if (endOnInput) { /* LZ4_decompress_safe() */ - if ((cpy>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; } - LZ4_wildCopy32(op, ip, cpy); - } else { /* LZ4_decompress_fast() */ - if (cpy>oend-8) { goto safe_literal_copy; } - LZ4_wildCopy8(op, ip, cpy); /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time : - * it doesn't know input length, and only relies on end-of-block properties */ - } - ip += length; op = cpy; - } else { - cpy = op+length; - if (endOnInput) { /* LZ4_decompress_safe() */ - DEBUGLOG(7, "copy %u bytes in a 16-bytes stripe", (unsigned)length); - /* We don't need to check oend, since we check it once for each loop below */ - if (ip > iend-(16 + 1/*max lit + offset + nextToken*/)) { goto safe_literal_copy; } - /* Literals can only be 14, but hope compilers optimize if we copy by a register size */ - LZ4_memcpy(op, ip, 16); - } else { /* LZ4_decompress_fast() */ - /* LZ4_decompress_fast() cannot copy more than 8 bytes at a time : - * it doesn't know input length, and relies on end-of-block properties */ - LZ4_memcpy(op, ip, 8); - if (length > 8) { LZ4_memcpy(op+8, ip+8, 8); } - } - ip += length; op = cpy; - } - - /* get offset */ - offset = LZ4_readLE16(ip); ip+=2; - match = op - offset; - assert(match <= op); - - /* get matchlength */ - length = token & ML_MASK; - - if (length == ML_MASK) { - variable_length_error error = ok; - if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */ - length += read_variable_length(&ip, iend - LASTLITERALS + 1, (int)endOnInput, 0, &error); - if (error != ok) { goto _output_error; } - if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */ - length += MINMATCH; - if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) { - goto safe_match_copy; - } - } else { - length += MINMATCH; - if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) { - goto safe_match_copy; - } - - /* Fastpath check: Avoids a branch in LZ4_wildCopy32 if true */ - if ((dict == withPrefix64k) || (match >= lowPrefix)) { - if (offset >= 8) { - assert(match >= lowPrefix); - assert(match <= op); - assert(op + 18 <= oend); - - LZ4_memcpy(op, match, 8); - LZ4_memcpy(op+8, match+8, 8); - LZ4_memcpy(op+16, match+16, 2); - op += length; - continue; - } } } - - if (checkOffset && (unlikely(match + dictSize < lowPrefix))) { goto _output_error; } /* Error : offset outside buffers */ - /* match starting within external dictionary */ - if ((dict==usingExtDict) && (match < lowPrefix)) { - if (unlikely(op+length > oend-LASTLITERALS)) { - if (partialDecoding) { - DEBUGLOG(7, "partialDecoding: dictionary match, close to dstEnd"); - length = MIN(length, (size_t)(oend-op)); - } else { - goto _output_error; /* end-of-block condition violated */ - } } - - if (length <= (size_t)(lowPrefix-match)) { - /* match fits entirely within external dictionary : just copy */ - memmove(op, dictEnd - (lowPrefix-match), length); - op += length; - } else { - /* match stretches into both external dictionary and current block */ - size_t const copySize = (size_t)(lowPrefix - match); - size_t const restSize = length - copySize; - LZ4_memcpy(op, dictEnd - copySize, copySize); - op += copySize; - if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */ - BYTE* const endOfMatch = op + restSize; - const BYTE* copyFrom = lowPrefix; - while (op < endOfMatch) { *op++ = *copyFrom++; } - } else { - LZ4_memcpy(op, lowPrefix, restSize); - op += restSize; - } } - continue; - } - - /* copy match within block */ - cpy = op + length; - - assert((op <= oend) && (oend-op >= 32)); - if (unlikely(offset<16)) { - LZ4_memcpy_using_offset(op, match, cpy, offset); - } else { - LZ4_wildCopy32(op, match, cpy); - } - - op = cpy; /* wildcopy correction */ - } - safe_decode: -#endif - - /* Main Loop : decode remaining sequences where output < FASTLOOP_SAFE_DISTANCE */ - while (1) { - token = *ip++; - length = token >> ML_BITS; /* literal length */ - - assert(!endOnInput || ip <= iend); /* ip < iend before the increment */ - - /* A two-stage shortcut for the most common case: - * 1) If the literal length is 0..14, and there is enough space, - * enter the shortcut and copy 16 bytes on behalf of the literals - * (in the fast mode, only 8 bytes can be safely copied this way). - * 2) Further if the match length is 4..18, copy 18 bytes in a similar - * manner; but we ensure that there's enough space in the output for - * those 18 bytes earlier, upon entering the shortcut (in other words, - * there is a combined check for both stages). - */ - if ( (endOnInput ? length != RUN_MASK : length <= 8) - /* strictly "less than" on input, to re-enter the loop with at least one byte */ - && likely((endOnInput ? ip < shortiend : 1) & (op <= shortoend)) ) { - /* Copy the literals */ - LZ4_memcpy(op, ip, endOnInput ? 16 : 8); - op += length; ip += length; - - /* The second stage: prepare for match copying, decode full info. - * If it doesn't work out, the info won't be wasted. */ - length = token & ML_MASK; /* match length */ - offset = LZ4_readLE16(ip); ip += 2; - match = op - offset; - assert(match <= op); /* check overflow */ - - /* Do not deal with overlapping matches. */ - if ( (length != ML_MASK) - && (offset >= 8) - && (dict==withPrefix64k || match >= lowPrefix) ) { - /* Copy the match. */ - LZ4_memcpy(op + 0, match + 0, 8); - LZ4_memcpy(op + 8, match + 8, 8); - LZ4_memcpy(op +16, match +16, 2); - op += length + MINMATCH; - /* Both stages worked, load the next token. */ - continue; - } - - /* The second stage didn't work out, but the info is ready. - * Propel it right to the point of match copying. */ - goto _copy_match; - } - - /* decode literal length */ - if (length == RUN_MASK) { - variable_length_error error = ok; - length += read_variable_length(&ip, iend-RUN_MASK, (int)endOnInput, (int)endOnInput, &error); - if (error == initial_error) { goto _output_error; } - if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */ - if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */ - } - - /* copy literals */ - cpy = op+length; -#if LZ4_FAST_DEC_LOOP - safe_literal_copy: -#endif - LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); - if ( ((endOnInput) && ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) ) - || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) - { - /* We've either hit the input parsing restriction or the output parsing restriction. - * In the normal scenario, decoding a full block, it must be the last sequence, - * otherwise it's an error (invalid input or dimensions). - * In partialDecoding scenario, it's necessary to ensure there is no buffer overflow. - */ - if (partialDecoding) { - /* Since we are partial decoding we may be in this block because of the output parsing - * restriction, which is not valid since the output buffer is allowed to be undersized. - */ - assert(endOnInput); - DEBUGLOG(7, "partialDecoding: copying literals, close to input or output end") - DEBUGLOG(7, "partialDecoding: literal length = %u", (unsigned)length); - DEBUGLOG(7, "partialDecoding: remaining space in dstBuffer : %i", (int)(oend - op)); - DEBUGLOG(7, "partialDecoding: remaining space in srcBuffer : %i", (int)(iend - ip)); - /* Finishing in the middle of a literals segment, - * due to lack of input. - */ - if (ip+length > iend) { - length = (size_t)(iend-ip); - cpy = op + length; - } - /* Finishing in the middle of a literals segment, - * due to lack of output space. - */ - if (cpy > oend) { - cpy = oend; - assert(op<=oend); - length = (size_t)(oend-op); - } - } else { - /* We must be on the last sequence because of the parsing limitations so check - * that we exactly regenerate the original size (must be exact when !endOnInput). - */ - if ((!endOnInput) && (cpy != oend)) { goto _output_error; } - /* We must be on the last sequence (or invalid) because of the parsing limitations - * so check that we exactly consume the input and don't overrun the output buffer. - */ - if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) { - DEBUGLOG(6, "should have been last run of literals") - DEBUGLOG(6, "ip(%p) + length(%i) = %p != iend (%p)", ip, (int)length, ip+length, iend); - DEBUGLOG(6, "or cpy(%p) > oend(%p)", cpy, oend); - goto _output_error; - } - } - memmove(op, ip, length); /* supports overlapping memory regions; only matters for in-place decompression scenarios */ - ip += length; - op += length; - /* Necessarily EOF when !partialDecoding. - * When partialDecoding, it is EOF if we've either - * filled the output buffer or - * can't proceed with reading an offset for following match. - */ - if (!partialDecoding || (cpy == oend) || (ip >= (iend-2))) { - break; - } - } else { - LZ4_wildCopy8(op, ip, cpy); /* may overwrite up to WILDCOPYLENGTH beyond cpy */ - ip += length; op = cpy; - } - - /* get offset */ - offset = LZ4_readLE16(ip); ip+=2; - match = op - offset; - - /* get matchlength */ - length = token & ML_MASK; - - _copy_match: - if (length == ML_MASK) { - variable_length_error error = ok; - length += read_variable_length(&ip, iend - LASTLITERALS + 1, (int)endOnInput, 0, &error); - if (error != ok) goto _output_error; - if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */ - } - length += MINMATCH; - -#if LZ4_FAST_DEC_LOOP - safe_match_copy: -#endif - if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error; /* Error : offset outside buffers */ - /* match starting within external dictionary */ - if ((dict==usingExtDict) && (match < lowPrefix)) { - if (unlikely(op+length > oend-LASTLITERALS)) { - if (partialDecoding) length = MIN(length, (size_t)(oend-op)); - else goto _output_error; /* doesn't respect parsing restriction */ - } - - if (length <= (size_t)(lowPrefix-match)) { - /* match fits entirely within external dictionary : just copy */ - memmove(op, dictEnd - (lowPrefix-match), length); - op += length; - } else { - /* match stretches into both external dictionary and current block */ - size_t const copySize = (size_t)(lowPrefix - match); - size_t const restSize = length - copySize; - LZ4_memcpy(op, dictEnd - copySize, copySize); - op += copySize; - if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */ - BYTE* const endOfMatch = op + restSize; - const BYTE* copyFrom = lowPrefix; - while (op < endOfMatch) *op++ = *copyFrom++; - } else { - LZ4_memcpy(op, lowPrefix, restSize); - op += restSize; - } } - continue; - } - assert(match >= lowPrefix); - - /* copy match within block */ - cpy = op + length; - - /* partialDecoding : may end anywhere within the block */ - assert(op<=oend); - if (partialDecoding && (cpy > oend-MATCH_SAFEGUARD_DISTANCE)) { - size_t const mlen = MIN(length, (size_t)(oend-op)); - const BYTE* const matchEnd = match + mlen; - BYTE* const copyEnd = op + mlen; - if (matchEnd > op) { /* overlap copy */ - while (op < copyEnd) { *op++ = *match++; } - } else { - LZ4_memcpy(op, match, mlen); - } - op = copyEnd; - if (op == oend) { break; } - continue; - } - - if (unlikely(offset<8)) { - LZ4_write32(op, 0); /* silence msan warning when offset==0 */ - op[0] = match[0]; - op[1] = match[1]; - op[2] = match[2]; - op[3] = match[3]; - match += inc32table[offset]; - LZ4_memcpy(op+4, match, 4); - match -= dec64table[offset]; - } else { - LZ4_memcpy(op, match, 8); - match += 8; - } - op += 8; - - if (unlikely(cpy > oend-MATCH_SAFEGUARD_DISTANCE)) { - BYTE* const oCopyLimit = oend - (WILDCOPYLENGTH-1); - if (cpy > oend-LASTLITERALS) { goto _output_error; } /* Error : last LASTLITERALS bytes must be literals (uncompressed) */ - if (op < oCopyLimit) { - LZ4_wildCopy8(op, match, oCopyLimit); - match += oCopyLimit - op; - op = oCopyLimit; - } - while (op < cpy) { *op++ = *match++; } - } else { - LZ4_memcpy(op, match, 8); - if (length > 16) { LZ4_wildCopy8(op+8, match+8, cpy); } - } - op = cpy; /* wildcopy correction */ - } - - /* end of decoding */ - if (endOnInput) { - DEBUGLOG(5, "decoded %i bytes", (int) (((char*)op)-dst)); - return (int) (((char*)op)-dst); /* Nb of output bytes decoded */ - } else { - return (int) (((const char*)ip)-src); /* Nb of input bytes read */ - } - - /* Overflow error detected */ - _output_error: - return (int) (-(((const char*)ip)-src))-1; - } -} - - -/*===== Instantiate the API decoding functions. =====*/ - -LZ4_FORCE_O2 -int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize) -{ - return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, - endOnInputSize, decode_full_block, noDict, - (BYTE*)dest, NULL, 0); -} - -LZ4_FORCE_O2 -int LZ4_decompress_safe_partial(const char* src, char* dst, int compressedSize, int targetOutputSize, int dstCapacity) -{ - dstCapacity = MIN(targetOutputSize, dstCapacity); - return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity, - endOnInputSize, partial_decode, - noDict, (BYTE*)dst, NULL, 0); -} - -LZ4_FORCE_O2 -int LZ4_decompress_fast(const char* source, char* dest, int originalSize) -{ - return LZ4_decompress_generic(source, dest, 0, originalSize, - endOnOutputSize, decode_full_block, withPrefix64k, - (BYTE*)dest - 64 KB, NULL, 0); -} - -/*===== Instantiate a few more decoding cases, used more than once. =====*/ - -LZ4_FORCE_O2 /* Exported, an obsolete API function. */ -int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize) -{ - return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, - endOnInputSize, decode_full_block, withPrefix64k, - (BYTE*)dest - 64 KB, NULL, 0); -} - -/* Another obsolete API function, paired with the previous one. */ -int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize) -{ - /* LZ4_decompress_fast doesn't validate match offsets, - * and thus serves well with any prefixed dictionary. */ - return LZ4_decompress_fast(source, dest, originalSize); -} - -LZ4_FORCE_O2 -static int LZ4_decompress_safe_withSmallPrefix(const char* source, char* dest, int compressedSize, int maxOutputSize, - size_t prefixSize) -{ - return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, - endOnInputSize, decode_full_block, noDict, - (BYTE*)dest-prefixSize, NULL, 0); -} - -LZ4_FORCE_O2 -int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, - int compressedSize, int maxOutputSize, - const void* dictStart, size_t dictSize) -{ - return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, - endOnInputSize, decode_full_block, usingExtDict, - (BYTE*)dest, (const BYTE*)dictStart, dictSize); -} - -LZ4_FORCE_O2 -static int LZ4_decompress_fast_extDict(const char* source, char* dest, int originalSize, - const void* dictStart, size_t dictSize) -{ - return LZ4_decompress_generic(source, dest, 0, originalSize, - endOnOutputSize, decode_full_block, usingExtDict, - (BYTE*)dest, (const BYTE*)dictStart, dictSize); -} - -/* The "double dictionary" mode, for use with e.g. ring buffers: the first part - * of the dictionary is passed as prefix, and the second via dictStart + dictSize. - * These routines are used only once, in LZ4_decompress_*_continue(). - */ -LZ4_FORCE_INLINE -int LZ4_decompress_safe_doubleDict(const char* source, char* dest, int compressedSize, int maxOutputSize, - size_t prefixSize, const void* dictStart, size_t dictSize) -{ - return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, - endOnInputSize, decode_full_block, usingExtDict, - (BYTE*)dest-prefixSize, (const BYTE*)dictStart, dictSize); -} - -LZ4_FORCE_INLINE -int LZ4_decompress_fast_doubleDict(const char* source, char* dest, int originalSize, - size_t prefixSize, const void* dictStart, size_t dictSize) -{ - return LZ4_decompress_generic(source, dest, 0, originalSize, - endOnOutputSize, decode_full_block, usingExtDict, - (BYTE*)dest-prefixSize, (const BYTE*)dictStart, dictSize); -} - -/*===== streaming decompression functions =====*/ - -LZ4_streamDecode_t* LZ4_createStreamDecode(void) -{ - LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOC_AND_ZERO(sizeof(LZ4_streamDecode_t)); - LZ4_STATIC_ASSERT(LZ4_STREAMDECODESIZE >= sizeof(LZ4_streamDecode_t_internal)); /* A compilation error here means LZ4_STREAMDECODESIZE is not large enough */ - return lz4s; -} - -int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream) -{ - if (LZ4_stream == NULL) { return 0; } /* support free on NULL */ - FREEMEM(LZ4_stream); - return 0; -} - -/*! LZ4_setStreamDecode() : - * Use this function to instruct where to find the dictionary. - * This function is not necessary if previous data is still available where it was decoded. - * Loading a size of 0 is allowed (same effect as no dictionary). - * @return : 1 if OK, 0 if error - */ -int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize) -{ - LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; - lz4sd->prefixSize = (size_t) dictSize; - lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize; - lz4sd->externalDict = NULL; - lz4sd->extDictSize = 0; - return 1; -} - -/*! LZ4_decoderRingBufferSize() : - * when setting a ring buffer for streaming decompression (optional scenario), - * provides the minimum size of this ring buffer - * to be compatible with any source respecting maxBlockSize condition. - * Note : in a ring buffer scenario, - * blocks are presumed decompressed next to each other. - * When not enough space remains for next block (remainingSize < maxBlockSize), - * decoding resumes from beginning of ring buffer. - * @return : minimum ring buffer size, - * or 0 if there is an error (invalid maxBlockSize). - */ -int LZ4_decoderRingBufferSize(int maxBlockSize) -{ - if (maxBlockSize < 0) return 0; - if (maxBlockSize > LZ4_MAX_INPUT_SIZE) return 0; - if (maxBlockSize < 16) maxBlockSize = 16; - return LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize); -} - -/* -*_continue() : - These decoding functions allow decompression of multiple blocks in "streaming" mode. - Previously decoded blocks must still be available at the memory position where they were decoded. - If it's not possible, save the relevant part of decoded data into a safe buffer, - and indicate where it stands using LZ4_setStreamDecode() -*/ -LZ4_FORCE_O2 -int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) -{ - LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; - int result; - - if (lz4sd->prefixSize == 0) { - /* The first call, no dictionary yet. */ - assert(lz4sd->extDictSize == 0); - result = LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize); - if (result <= 0) return result; - lz4sd->prefixSize = (size_t)result; - lz4sd->prefixEnd = (BYTE*)dest + result; - } else if (lz4sd->prefixEnd == (BYTE*)dest) { - /* They're rolling the current segment. */ - if (lz4sd->prefixSize >= 64 KB - 1) - result = LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize); - else if (lz4sd->extDictSize == 0) - result = LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, - lz4sd->prefixSize); - else - result = LZ4_decompress_safe_doubleDict(source, dest, compressedSize, maxOutputSize, - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) return result; - lz4sd->prefixSize += (size_t)result; - lz4sd->prefixEnd += result; - } else { - /* The buffer wraps around, or they're switching to another buffer. */ - lz4sd->extDictSize = lz4sd->prefixSize; - lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; - result = LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, - lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) return result; - lz4sd->prefixSize = (size_t)result; - lz4sd->prefixEnd = (BYTE*)dest + result; - } - - return result; -} - -LZ4_FORCE_O2 -int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize) -{ - LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; - int result; - assert(originalSize >= 0); - - if (lz4sd->prefixSize == 0) { - assert(lz4sd->extDictSize == 0); - result = LZ4_decompress_fast(source, dest, originalSize); - if (result <= 0) return result; - lz4sd->prefixSize = (size_t)originalSize; - lz4sd->prefixEnd = (BYTE*)dest + originalSize; - } else if (lz4sd->prefixEnd == (BYTE*)dest) { - if (lz4sd->prefixSize >= 64 KB - 1 || lz4sd->extDictSize == 0) - result = LZ4_decompress_fast(source, dest, originalSize); - else - result = LZ4_decompress_fast_doubleDict(source, dest, originalSize, - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) return result; - lz4sd->prefixSize += (size_t)originalSize; - lz4sd->prefixEnd += originalSize; - } else { - lz4sd->extDictSize = lz4sd->prefixSize; - lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; - result = LZ4_decompress_fast_extDict(source, dest, originalSize, - lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) return result; - lz4sd->prefixSize = (size_t)originalSize; - lz4sd->prefixEnd = (BYTE*)dest + originalSize; - } - - return result; -} - - -/* -Advanced decoding functions : -*_usingDict() : - These decoding functions work the same as "_continue" ones, - the dictionary must be explicitly provided within parameters -*/ - -int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) -{ - if (dictSize==0) - return LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize); - if (dictStart+dictSize == dest) { - if (dictSize >= 64 KB - 1) { - return LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize); - } - assert(dictSize >= 0); - return LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, (size_t)dictSize); - } - assert(dictSize >= 0); - return LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, dictStart, (size_t)dictSize); -} - -int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize) -{ - if (dictSize==0 || dictStart+dictSize == dest) - return LZ4_decompress_fast(source, dest, originalSize); - assert(dictSize >= 0); - return LZ4_decompress_fast_extDict(source, dest, originalSize, dictStart, (size_t)dictSize); -} - - -/*=************************************************* -* Obsolete Functions -***************************************************/ -/* obsolete compression functions */ -int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) -{ - return LZ4_compress_default(source, dest, inputSize, maxOutputSize); -} -int LZ4_compress(const char* src, char* dest, int srcSize) -{ - return LZ4_compress_default(src, dest, srcSize, LZ4_compressBound(srcSize)); -} -int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) -{ - return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); -} -int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) -{ - return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1); -} -int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int dstCapacity) -{ - return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, dstCapacity, 1); -} -int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) -{ - return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1); -} - -/* -These decompression functions are deprecated and should no longer be used. -They are only provided here for compatibility with older user programs. -- LZ4_uncompress is totally equivalent to LZ4_decompress_fast -- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe -*/ -int LZ4_uncompress (const char* source, char* dest, int outputSize) -{ - return LZ4_decompress_fast(source, dest, outputSize); -} -int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) -{ - return LZ4_decompress_safe(source, dest, isize, maxOutputSize); -} - -/* Obsolete Streaming functions */ - -int LZ4_sizeofStreamState(void) { return LZ4_STREAMSIZE; } - -int LZ4_resetStreamState(void* state, char* inputBuffer) -{ - (void)inputBuffer; - LZ4_resetStream((LZ4_stream_t*)state); - return 0; -} - -void* LZ4_create (char* inputBuffer) -{ - (void)inputBuffer; - return LZ4_createStream(); -} - -char* LZ4_slideInputBuffer (void* state) -{ - /* avoid const char * -> char * conversion warning */ - return (char *)(uptrval)((LZ4_stream_t*)state)->internal_donotuse.dictionary; -} - -#endif /* LZ4_COMMONDEFS_ONLY */ diff --git a/ta6ob/lz4/lib/lz4.h b/ta6ob/lz4/lib/lz4.h deleted file mode 100644 index 7ab1e48..0000000 --- a/ta6ob/lz4/lib/lz4.h +++ /dev/null @@ -1,774 +0,0 @@ -/* - * LZ4 - Fast LZ compression algorithm - * Header File - * Copyright (C) 2011-present, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - LZ4 homepage : http://www.lz4.org - - LZ4 source repository : https://github.com/lz4/lz4 -*/ -#if defined (__cplusplus) -extern "C" { -#endif - -#ifndef LZ4_H_2983827168210 -#define LZ4_H_2983827168210 - -/* --- Dependency --- */ -#include /* size_t */ - - -/** - Introduction - - LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core, - scalable with multi-cores CPU. It features an extremely fast decoder, with speed in - multiple GB/s per core, typically reaching RAM speed limits on multi-core systems. - - The LZ4 compression library provides in-memory compression and decompression functions. - It gives full buffer control to user. - Compression can be done in: - - a single step (described as Simple Functions) - - a single step, reusing a context (described in Advanced Functions) - - unbounded multiple steps (described as Streaming compression) - - lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md). - Decompressing such a compressed block requires additional metadata. - Exact metadata depends on exact decompression function. - For the typical case of LZ4_decompress_safe(), - metadata includes block's compressed size, and maximum bound of decompressed size. - Each application is free to encode and pass such metadata in whichever way it wants. - - lz4.h only handle blocks, it can not generate Frames. - - Blocks are different from Frames (doc/lz4_Frame_format.md). - Frames bundle both blocks and metadata in a specified manner. - Embedding metadata is required for compressed data to be self-contained and portable. - Frame format is delivered through a companion API, declared in lz4frame.h. - The `lz4` CLI can only manage frames. -*/ - -/*^*************************************************************** -* Export parameters -*****************************************************************/ -/* -* LZ4_DLL_EXPORT : -* Enable exporting of functions when building a Windows DLL -* LZ4LIB_VISIBILITY : -* Control library symbols visibility. -*/ -#ifndef LZ4LIB_VISIBILITY -# if defined(__GNUC__) && (__GNUC__ >= 4) -# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default"))) -# else -# define LZ4LIB_VISIBILITY -# endif -#endif -#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1) -# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY -#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1) -# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ -#else -# define LZ4LIB_API LZ4LIB_VISIBILITY -#endif - -/*------ Version ------*/ -#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ -#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */ -#define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */ - -#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) - -#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE -#define LZ4_QUOTE(str) #str -#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str) -#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) - -LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version */ -LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version */ - - -/*-************************************ -* Tuning parameter -**************************************/ -/*! - * LZ4_MEMORY_USAGE : - * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) - * Increasing memory usage improves compression ratio. - * Reduced memory usage may improve speed, thanks to better cache locality. - * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache - */ -#ifndef LZ4_MEMORY_USAGE -# define LZ4_MEMORY_USAGE 14 -#endif - - -/*-************************************ -* Simple Functions -**************************************/ -/*! LZ4_compress_default() : - * Compresses 'srcSize' bytes from buffer 'src' - * into already allocated 'dst' buffer of size 'dstCapacity'. - * Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize). - * It also runs faster, so it's a recommended setting. - * If the function cannot compress 'src' into a more limited 'dst' budget, - * compression stops *immediately*, and the function result is zero. - * In which case, 'dst' content is undefined (invalid). - * srcSize : max supported value is LZ4_MAX_INPUT_SIZE. - * dstCapacity : size of buffer 'dst' (which must be already allocated) - * @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity) - * or 0 if compression fails - * Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer). - */ -LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity); - -/*! LZ4_decompress_safe() : - * compressedSize : is the exact complete size of the compressed block. - * dstCapacity : is the size of destination buffer (which must be already allocated), presumed an upper bound of decompressed size. - * @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity) - * If destination buffer is not large enough, decoding will stop and output an error code (negative value). - * If the source stream is detected malformed, the function will stop decoding and return a negative result. - * Note 1 : This function is protected against malicious data packets : - * it will never writes outside 'dst' buffer, nor read outside 'source' buffer, - * even if the compressed block is maliciously modified to order the decoder to do these actions. - * In such case, the decoder stops immediately, and considers the compressed block malformed. - * Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them. - * The implementation is free to send / store / derive this information in whichever way is most beneficial. - * If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead. - */ -LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity); - - -/*-************************************ -* Advanced Functions -**************************************/ -#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ -#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) - -/*! LZ4_compressBound() : - Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) - This function is primarily useful for memory allocation purposes (destination buffer size). - Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example). - Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize) - inputSize : max supported value is LZ4_MAX_INPUT_SIZE - return : maximum output size in a "worst case" scenario - or 0, if input size is incorrect (too large or negative) -*/ -LZ4LIB_API int LZ4_compressBound(int inputSize); - -/*! LZ4_compress_fast() : - Same as LZ4_compress_default(), but allows selection of "acceleration" factor. - The larger the acceleration value, the faster the algorithm, but also the lesser the compression. - It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed. - An acceleration value of "1" is the same as regular LZ4_compress_default() - Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c). - Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c). -*/ -LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); - - -/*! LZ4_compress_fast_extState() : - * Same as LZ4_compress_fast(), using an externally allocated memory space for its state. - * Use LZ4_sizeofState() to know how much memory must be allocated, - * and allocate it on 8-bytes boundaries (using `malloc()` typically). - * Then, provide this buffer as `void* state` to compression function. - */ -LZ4LIB_API int LZ4_sizeofState(void); -LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); - - -/*! LZ4_compress_destSize() : - * Reverse the logic : compresses as much data as possible from 'src' buffer - * into already allocated buffer 'dst', of size >= 'targetDestSize'. - * This function either compresses the entire 'src' content into 'dst' if it's large enough, - * or fill 'dst' buffer completely with as much data as possible from 'src'. - * note: acceleration parameter is fixed to "default". - * - * *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'. - * New value is necessarily <= input value. - * @return : Nb bytes written into 'dst' (necessarily <= targetDestSize) - * or 0 if compression fails. - * - * Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+): - * the produced compressed content could, in specific circumstances, - * require to be decompressed into a destination buffer larger - * by at least 1 byte than the content to decompress. - * If an application uses `LZ4_compress_destSize()`, - * it's highly recommended to update liblz4 to v1.9.2 or better. - * If this can't be done or ensured, - * the receiving decompression function should provide - * a dstCapacity which is > decompressedSize, by at least 1 byte. - * See https://github.com/lz4/lz4/issues/859 for details - */ -LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize); - - -/*! LZ4_decompress_safe_partial() : - * Decompress an LZ4 compressed block, of size 'srcSize' at position 'src', - * into destination buffer 'dst' of size 'dstCapacity'. - * Up to 'targetOutputSize' bytes will be decoded. - * The function stops decoding on reaching this objective. - * This can be useful to boost performance - * whenever only the beginning of a block is required. - * - * @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize) - * If source stream is detected malformed, function returns a negative result. - * - * Note 1 : @return can be < targetOutputSize, if compressed block contains less data. - * - * Note 2 : targetOutputSize must be <= dstCapacity - * - * Note 3 : this function effectively stops decoding on reaching targetOutputSize, - * so dstCapacity is kind of redundant. - * This is because in older versions of this function, - * decoding operation would still write complete sequences. - * Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize, - * it could write more bytes, though only up to dstCapacity. - * Some "margin" used to be required for this operation to work properly. - * Thankfully, this is no longer necessary. - * The function nonetheless keeps the same signature, in an effort to preserve API compatibility. - * - * Note 4 : If srcSize is the exact size of the block, - * then targetOutputSize can be any value, - * including larger than the block's decompressed size. - * The function will, at most, generate block's decompressed size. - * - * Note 5 : If srcSize is _larger_ than block's compressed size, - * then targetOutputSize **MUST** be <= block's decompressed size. - * Otherwise, *silent corruption will occur*. - */ -LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity); - - -/*-********************************************* -* Streaming Compression Functions -***********************************************/ -typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ - -LZ4LIB_API LZ4_stream_t* LZ4_createStream(void); -LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr); - -/*! LZ4_resetStream_fast() : v1.9.0+ - * Use this to prepare an LZ4_stream_t for a new chain of dependent blocks - * (e.g., LZ4_compress_fast_continue()). - * - * An LZ4_stream_t must be initialized once before usage. - * This is automatically done when created by LZ4_createStream(). - * However, should the LZ4_stream_t be simply declared on stack (for example), - * it's necessary to initialize it first, using LZ4_initStream(). - * - * After init, start any new stream with LZ4_resetStream_fast(). - * A same LZ4_stream_t can be re-used multiple times consecutively - * and compress multiple streams, - * provided that it starts each new stream with LZ4_resetStream_fast(). - * - * LZ4_resetStream_fast() is much faster than LZ4_initStream(), - * but is not compatible with memory regions containing garbage data. - * - * Note: it's only useful to call LZ4_resetStream_fast() - * in the context of streaming compression. - * The *extState* functions perform their own resets. - * Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive. - */ -LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr); - -/*! LZ4_loadDict() : - * Use this function to reference a static dictionary into LZ4_stream_t. - * The dictionary must remain available during compression. - * LZ4_loadDict() triggers a reset, so any previous data will be forgotten. - * The same dictionary will have to be loaded on decompression side for successful decoding. - * Dictionary are useful for better compression of small data (KB range). - * While LZ4 accept any input as dictionary, - * results are generally better when using Zstandard's Dictionary Builder. - * Loading a size of 0 is allowed, and is the same as reset. - * @return : loaded dictionary size, in bytes (necessarily <= 64 KB) - */ -LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); - -/*! LZ4_compress_fast_continue() : - * Compress 'src' content using data from previously compressed blocks, for better compression ratio. - * 'dst' buffer must be already allocated. - * If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. - * - * @return : size of compressed block - * or 0 if there is an error (typically, cannot fit into 'dst'). - * - * Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block. - * Each block has precise boundaries. - * Each block must be decompressed separately, calling LZ4_decompress_*() with relevant metadata. - * It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together. - * - * Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory ! - * - * Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB. - * Make sure that buffers are separated, by at least one byte. - * This construction ensures that each block only depends on previous block. - * - * Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB. - * - * Note 5 : After an error, the stream status is undefined (invalid), it can only be reset or freed. - */ -LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); - -/*! LZ4_saveDict() : - * If last 64KB data cannot be guaranteed to remain available at its current memory location, - * save it into a safer place (char* safeBuffer). - * This is schematically equivalent to a memcpy() followed by LZ4_loadDict(), - * but is much faster, because LZ4_saveDict() doesn't need to rebuild tables. - * @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error. - */ -LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize); - - -/*-********************************************** -* Streaming Decompression Functions -* Bufferless synchronous API -************************************************/ -typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */ - -/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() : - * creation / destruction of streaming decompression tracking context. - * A tracking context can be re-used multiple times. - */ -LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void); -LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); - -/*! LZ4_setStreamDecode() : - * An LZ4_streamDecode_t context can be allocated once and re-used multiple times. - * Use this function to start decompression of a new stream of blocks. - * A dictionary can optionally be set. Use NULL or size 0 for a reset order. - * Dictionary is presumed stable : it must remain accessible and unmodified during next decompression. - * @return : 1 if OK, 0 if error - */ -LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); - -/*! LZ4_decoderRingBufferSize() : v1.8.2+ - * Note : in a ring buffer scenario (optional), - * blocks are presumed decompressed next to each other - * up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize), - * at which stage it resumes from beginning of ring buffer. - * When setting such a ring buffer for streaming decompression, - * provides the minimum size of this ring buffer - * to be compatible with any source respecting maxBlockSize condition. - * @return : minimum ring buffer size, - * or 0 if there is an error (invalid maxBlockSize). - */ -LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize); -#define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize)) /* for static allocation; maxBlockSize presumed valid */ - -/*! LZ4_decompress_*_continue() : - * These decoding functions allow decompression of consecutive blocks in "streaming" mode. - * A block is an unsplittable entity, it must be presented entirely to a decompression function. - * Decompression functions only accepts one block at a time. - * The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded. - * If less than 64KB of data has been decoded, all the data must be present. - * - * Special : if decompression side sets a ring buffer, it must respect one of the following conditions : - * - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize). - * maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes. - * In which case, encoding and decoding buffers do not need to be synchronized. - * Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize. - * - Synchronized mode : - * Decompression buffer size is _exactly_ the same as compression buffer size, - * and follows exactly same update rule (block boundaries at same positions), - * and decoding function is provided with exact decompressed size of each block (exception for last block of the stream), - * _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB). - * - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes. - * In which case, encoding and decoding buffers do not need to be synchronized, - * and encoding ring buffer can have any size, including small ones ( < 64 KB). - * - * Whenever these conditions are not possible, - * save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression, - * then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block. -*/ -LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity); - - -/*! LZ4_decompress_*_usingDict() : - * These decoding functions work the same as - * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue() - * They are stand-alone, and don't need an LZ4_streamDecode_t structure. - * Dictionary is presumed stable : it must remain accessible and unmodified during decompression. - * Performance tip : Decompression speed can be substantially increased - * when dst == dictStart + dictSize. - */ -LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize); - -#endif /* LZ4_H_2983827168210 */ - - -/*^************************************* - * !!!!!! STATIC LINKING ONLY !!!!!! - ***************************************/ - -/*-**************************************************************************** - * Experimental section - * - * Symbols declared in this section must be considered unstable. Their - * signatures or semantics may change, or they may be removed altogether in the - * future. They are therefore only safe to depend on when the caller is - * statically linked against the library. - * - * To protect against unsafe usage, not only are the declarations guarded, - * the definitions are hidden by default - * when building LZ4 as a shared/dynamic library. - * - * In order to access these declarations, - * define LZ4_STATIC_LINKING_ONLY in your application - * before including LZ4's headers. - * - * In order to make their implementations accessible dynamically, you must - * define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library. - ******************************************************************************/ - -#ifdef LZ4_STATIC_LINKING_ONLY - -#ifndef LZ4_STATIC_3504398509 -#define LZ4_STATIC_3504398509 - -#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS -#define LZ4LIB_STATIC_API LZ4LIB_API -#else -#define LZ4LIB_STATIC_API -#endif - - -/*! LZ4_compress_fast_extState_fastReset() : - * A variant of LZ4_compress_fast_extState(). - * - * Using this variant avoids an expensive initialization step. - * It is only safe to call if the state buffer is known to be correctly initialized already - * (see above comment on LZ4_resetStream_fast() for a definition of "correctly initialized"). - * From a high level, the difference is that - * this function initializes the provided state with a call to something like LZ4_resetStream_fast() - * while LZ4_compress_fast_extState() starts with a call to LZ4_resetStream(). - */ -LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); - -/*! LZ4_attach_dictionary() : - * This is an experimental API that allows - * efficient use of a static dictionary many times. - * - * Rather than re-loading the dictionary buffer into a working context before - * each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a - * working LZ4_stream_t, this function introduces a no-copy setup mechanism, - * in which the working stream references the dictionary stream in-place. - * - * Several assumptions are made about the state of the dictionary stream. - * Currently, only streams which have been prepared by LZ4_loadDict() should - * be expected to work. - * - * Alternatively, the provided dictionaryStream may be NULL, - * in which case any existing dictionary stream is unset. - * - * If a dictionary is provided, it replaces any pre-existing stream history. - * The dictionary contents are the only history that can be referenced and - * logically immediately precede the data compressed in the first subsequent - * compression call. - * - * The dictionary will only remain attached to the working stream through the - * first compression call, at the end of which it is cleared. The dictionary - * stream (and source buffer) must remain in-place / accessible / unchanged - * through the completion of the first compression call on the stream. - */ -LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream); - - -/*! In-place compression and decompression - * - * It's possible to have input and output sharing the same buffer, - * for highly contrained memory environments. - * In both cases, it requires input to lay at the end of the buffer, - * and decompression to start at beginning of the buffer. - * Buffer size must feature some margin, hence be larger than final size. - * - * |<------------------------buffer--------------------------------->| - * |<-----------compressed data--------->| - * |<-----------decompressed size------------------>| - * |<----margin---->| - * - * This technique is more useful for decompression, - * since decompressed size is typically larger, - * and margin is short. - * - * In-place decompression will work inside any buffer - * which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize). - * This presumes that decompressedSize > compressedSize. - * Otherwise, it means compression actually expanded data, - * and it would be more efficient to store such data with a flag indicating it's not compressed. - * This can happen when data is not compressible (already compressed, or encrypted). - * - * For in-place compression, margin is larger, as it must be able to cope with both - * history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX, - * and data expansion, which can happen when input is not compressible. - * As a consequence, buffer size requirements are much higher, - * and memory savings offered by in-place compression are more limited. - * - * There are ways to limit this cost for compression : - * - Reduce history size, by modifying LZ4_DISTANCE_MAX. - * Note that it is a compile-time constant, so all compressions will apply this limit. - * Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX, - * so it's a reasonable trick when inputs are known to be small. - * - Require the compressor to deliver a "maximum compressed size". - * This is the `dstCapacity` parameter in `LZ4_compress*()`. - * When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail, - * in which case, the return code will be 0 (zero). - * The caller must be ready for these cases to happen, - * and typically design a backup scheme to send data uncompressed. - * The combination of both techniques can significantly reduce - * the amount of margin required for in-place compression. - * - * In-place compression can work in any buffer - * which size is >= (maxCompressedSize) - * with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success. - * LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX, - * so it's possible to reduce memory requirements by playing with them. - */ - -#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize) (((compressedSize) >> 8) + 32) -#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize) ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize)) /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */ - -#ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */ -# define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */ -#endif - -#define LZ4_COMPRESS_INPLACE_MARGIN (LZ4_DISTANCE_MAX + 32) /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */ -#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize) ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN) /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */ - -#endif /* LZ4_STATIC_3504398509 */ -#endif /* LZ4_STATIC_LINKING_ONLY */ - - - -#ifndef LZ4_H_98237428734687 -#define LZ4_H_98237428734687 - -/*-************************************************************ - * Private Definitions - ************************************************************** - * Do not use these definitions directly. - * They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`. - * Accessing members will expose user code to API and/or ABI break in future versions of the library. - **************************************************************/ -#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) -#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) -#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ - -#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -# include - typedef int8_t LZ4_i8; - typedef uint8_t LZ4_byte; - typedef uint16_t LZ4_u16; - typedef uint32_t LZ4_u32; -#else - typedef signed char LZ4_i8; - typedef unsigned char LZ4_byte; - typedef unsigned short LZ4_u16; - typedef unsigned int LZ4_u32; -#endif - -typedef struct LZ4_stream_t_internal LZ4_stream_t_internal; -struct LZ4_stream_t_internal { - LZ4_u32 hashTable[LZ4_HASH_SIZE_U32]; - LZ4_u32 currentOffset; - LZ4_u32 tableType; - const LZ4_byte* dictionary; - const LZ4_stream_t_internal* dictCtx; - LZ4_u32 dictSize; -}; - -typedef struct { - const LZ4_byte* externalDict; - size_t extDictSize; - const LZ4_byte* prefixEnd; - size_t prefixSize; -} LZ4_streamDecode_t_internal; - - -/*! LZ4_stream_t : - * Do not use below internal definitions directly ! - * Declare or allocate an LZ4_stream_t instead. - * LZ4_stream_t can also be created using LZ4_createStream(), which is recommended. - * The structure definition can be convenient for static allocation - * (on stack, or as part of larger structure). - * Init this structure with LZ4_initStream() before first use. - * note : only use this definition in association with static linking ! - * this definition is not API/ABI safe, and may change in future versions. - */ -#define LZ4_STREAMSIZE 16416 /* static size, for inter-version compatibility */ -#define LZ4_STREAMSIZE_VOIDP (LZ4_STREAMSIZE / sizeof(void*)) -union LZ4_stream_u { - void* table[LZ4_STREAMSIZE_VOIDP]; - LZ4_stream_t_internal internal_donotuse; -}; /* previously typedef'd to LZ4_stream_t */ - - -/*! LZ4_initStream() : v1.9.0+ - * An LZ4_stream_t structure must be initialized at least once. - * This is automatically done when invoking LZ4_createStream(), - * but it's not when the structure is simply declared on stack (for example). - * - * Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t. - * It can also initialize any arbitrary buffer of sufficient size, - * and will @return a pointer of proper type upon initialization. - * - * Note : initialization fails if size and alignment conditions are not respected. - * In which case, the function will @return NULL. - * Note2: An LZ4_stream_t structure guarantees correct alignment and size. - * Note3: Before v1.9.0, use LZ4_resetStream() instead - */ -LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size); - - -/*! LZ4_streamDecode_t : - * information structure to track an LZ4 stream during decompression. - * init this structure using LZ4_setStreamDecode() before first use. - * note : only use in association with static linking ! - * this definition is not API/ABI safe, - * and may change in a future version ! - */ -#define LZ4_STREAMDECODESIZE_U64 (4 + ((sizeof(void*)==16) ? 2 : 0) /*AS-400*/ ) -#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) -union LZ4_streamDecode_u { - unsigned long long table[LZ4_STREAMDECODESIZE_U64]; - LZ4_streamDecode_t_internal internal_donotuse; -} ; /* previously typedef'd to LZ4_streamDecode_t */ - - - -/*-************************************ -* Obsolete Functions -**************************************/ - -/*! Deprecation warnings - * - * Deprecated functions make the compiler generate a warning when invoked. - * This is meant to invite users to update their source code. - * Should deprecation warnings be a problem, it is generally possible to disable them, - * typically with -Wno-deprecated-declarations for gcc - * or _CRT_SECURE_NO_WARNINGS in Visual. - * - * Another method is to define LZ4_DISABLE_DEPRECATE_WARNINGS - * before including the header file. - */ -#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS -# define LZ4_DEPRECATED(message) /* disable deprecation warnings */ -#else -# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ -# define LZ4_DEPRECATED(message) [[deprecated(message)]] -# elif defined(_MSC_VER) -# define LZ4_DEPRECATED(message) __declspec(deprecated(message)) -# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45)) -# define LZ4_DEPRECATED(message) __attribute__((deprecated(message))) -# elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31) -# define LZ4_DEPRECATED(message) __attribute__((deprecated)) -# else -# pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler") -# define LZ4_DEPRECATED(message) /* disabled */ -# endif -#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */ - -/*! Obsolete compression functions (since v1.7.3) */ -LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize); -LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize); -LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); -LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); -LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); -LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); - -/*! Obsolete decompression functions (since v1.8.0) */ -LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize); -LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); - -/* Obsolete streaming functions (since v1.7.0) - * degraded functionality; do not use! - * - * In order to perform streaming compression, these functions depended on data - * that is no longer tracked in the state. They have been preserved as well as - * possible: using them will still produce a correct output. However, they don't - * actually retain any history between compression calls. The compression ratio - * achieved will therefore be no better than compressing each chunk - * independently. - */ -LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer); -LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void); -LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer); -LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state); - -/*! Obsolete streaming decoding functions (since v1.7.0) */ -LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize); -LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize); - -/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) : - * These functions used to be faster than LZ4_decompress_safe(), - * but this is no longer the case. They are now slower. - * This is because LZ4_decompress_fast() doesn't know the input size, - * and therefore must progress more cautiously into the input buffer to not read beyond the end of block. - * On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability. - * As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated. - * - * The last remaining LZ4_decompress_fast() specificity is that - * it can decompress a block without knowing its compressed size. - * Such functionality can be achieved in a more secure manner - * by employing LZ4_decompress_safe_partial(). - * - * Parameters: - * originalSize : is the uncompressed size to regenerate. - * `dst` must be already allocated, its size must be >= 'originalSize' bytes. - * @return : number of bytes read from source buffer (== compressed size). - * The function expects to finish at block's end exactly. - * If the source stream is detected malformed, the function stops decoding and returns a negative result. - * note : LZ4_decompress_fast*() requires originalSize. Thanks to this information, it never writes past the output buffer. - * However, since it doesn't know its 'src' size, it may read an unknown amount of input, past input buffer bounds. - * Also, since match offsets are not validated, match reads from 'src' may underflow too. - * These issues never happen if input (compressed) data is correct. - * But they may happen if input data is invalid (error or intentional tampering). - * As a consequence, use these functions in trusted environments with trusted data **only**. - */ -LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead") -LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize); -LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead") -LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize); -LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead") -LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize); - -/*! LZ4_resetStream() : - * An LZ4_stream_t structure must be initialized at least once. - * This is done with LZ4_initStream(), or LZ4_resetStream(). - * Consider switching to LZ4_initStream(), - * invoking LZ4_resetStream() will trigger deprecation warnings in the future. - */ -LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr); - - -#endif /* LZ4_H_98237428734687 */ - - -#if defined (__cplusplus) -} -#endif diff --git a/ta6ob/lz4/lib/lz4frame.c b/ta6ob/lz4/lib/lz4frame.c deleted file mode 100644 index ec02c92..0000000 --- a/ta6ob/lz4/lib/lz4frame.c +++ /dev/null @@ -1,1899 +0,0 @@ -/* - * LZ4 auto-framing library - * Copyright (C) 2011-2016, Yann Collet. - * - * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You can contact the author at : - * - LZ4 homepage : http://www.lz4.org - * - LZ4 source repository : https://github.com/lz4/lz4 - */ - -/* LZ4F is a stand-alone API to create LZ4-compressed Frames - * in full conformance with specification v1.6.1 . - * This library rely upon memory management capabilities (malloc, free) - * provided either by , - * or redirected towards another library of user's choice - * (see Memory Routines below). - */ - - -/*-************************************ -* Compiler Options -**************************************/ -#ifdef _MSC_VER /* Visual Studio */ -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#endif - - -/*-************************************ -* Tuning parameters -**************************************/ -/* - * LZ4F_HEAPMODE : - * Select how default compression functions will allocate memory for their hash table, - * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). - */ -#ifndef LZ4F_HEAPMODE -# define LZ4F_HEAPMODE 0 -#endif - - -/*-************************************ -* Memory routines -**************************************/ -/* - * User may redirect invocations of - * malloc(), calloc() and free() - * towards another library or solution of their choice - * by modifying below section. - */ -#ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */ -# include /* malloc, calloc, free */ -# define ALLOC(s) malloc(s) -# define ALLOC_AND_ZERO(s) calloc(1,(s)) -# define FREEMEM(p) free(p) -#endif - -#include /* memset, memcpy, memmove */ -#ifndef LZ4_SRC_INCLUDED /* avoid redefinition when sources are coalesced */ -# define MEM_INIT(p,v,s) memset((p),(v),(s)) -#endif - - -/*-************************************ -* Library declarations -**************************************/ -#define LZ4F_STATIC_LINKING_ONLY -#include "lz4frame.h" -#define LZ4_STATIC_LINKING_ONLY -#include "lz4.h" -#define LZ4_HC_STATIC_LINKING_ONLY -#include "lz4hc.h" -#define XXH_STATIC_LINKING_ONLY -#include "xxhash.h" - - -/*-************************************ -* Debug -**************************************/ -#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=1) -# include -#else -# ifndef assert -# define assert(condition) ((void)0) -# endif -#endif - -#define LZ4F_STATIC_ASSERT(c) { enum { LZ4F_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ - -#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2) && !defined(DEBUGLOG) -# include -static int g_debuglog_enable = 1; -# define DEBUGLOG(l, ...) { \ - if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) { \ - fprintf(stderr, __FILE__ ": "); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, " \n"); \ - } } -#else -# define DEBUGLOG(l, ...) {} /* disabled */ -#endif - - -/*-************************************ -* Basic Types -**************************************/ -#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint8_t BYTE; - typedef uint16_t U16; - typedef uint32_t U32; - typedef int32_t S32; - typedef uint64_t U64; -#else - typedef unsigned char BYTE; - typedef unsigned short U16; - typedef unsigned int U32; - typedef signed int S32; - typedef unsigned long long U64; -#endif - - -/* unoptimized version; solves endianess & alignment issues */ -static U32 LZ4F_readLE32 (const void* src) -{ - const BYTE* const srcPtr = (const BYTE*)src; - U32 value32 = srcPtr[0]; - value32 += ((U32)srcPtr[1])<< 8; - value32 += ((U32)srcPtr[2])<<16; - value32 += ((U32)srcPtr[3])<<24; - return value32; -} - -static void LZ4F_writeLE32 (void* dst, U32 value32) -{ - BYTE* const dstPtr = (BYTE*)dst; - dstPtr[0] = (BYTE)value32; - dstPtr[1] = (BYTE)(value32 >> 8); - dstPtr[2] = (BYTE)(value32 >> 16); - dstPtr[3] = (BYTE)(value32 >> 24); -} - -static U64 LZ4F_readLE64 (const void* src) -{ - const BYTE* const srcPtr = (const BYTE*)src; - U64 value64 = srcPtr[0]; - value64 += ((U64)srcPtr[1]<<8); - value64 += ((U64)srcPtr[2]<<16); - value64 += ((U64)srcPtr[3]<<24); - value64 += ((U64)srcPtr[4]<<32); - value64 += ((U64)srcPtr[5]<<40); - value64 += ((U64)srcPtr[6]<<48); - value64 += ((U64)srcPtr[7]<<56); - return value64; -} - -static void LZ4F_writeLE64 (void* dst, U64 value64) -{ - BYTE* const dstPtr = (BYTE*)dst; - dstPtr[0] = (BYTE)value64; - dstPtr[1] = (BYTE)(value64 >> 8); - dstPtr[2] = (BYTE)(value64 >> 16); - dstPtr[3] = (BYTE)(value64 >> 24); - dstPtr[4] = (BYTE)(value64 >> 32); - dstPtr[5] = (BYTE)(value64 >> 40); - dstPtr[6] = (BYTE)(value64 >> 48); - dstPtr[7] = (BYTE)(value64 >> 56); -} - - -/*-************************************ -* Constants -**************************************/ -#ifndef LZ4_SRC_INCLUDED /* avoid double definition */ -# define KB *(1<<10) -# define MB *(1<<20) -# define GB *(1<<30) -#endif - -#define _1BIT 0x01 -#define _2BITS 0x03 -#define _3BITS 0x07 -#define _4BITS 0x0F -#define _8BITS 0xFF - -#define LZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U -#define LZ4F_MAGICNUMBER 0x184D2204U -#define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U -#define LZ4F_BLOCKSIZEID_DEFAULT LZ4F_max64KB - -static const size_t minFHSize = LZ4F_HEADER_SIZE_MIN; /* 7 */ -static const size_t maxFHSize = LZ4F_HEADER_SIZE_MAX; /* 19 */ -static const size_t BHSize = LZ4F_BLOCK_HEADER_SIZE; /* block header : size, and compress flag */ -static const size_t BFSize = LZ4F_BLOCK_CHECKSUM_SIZE; /* block footer : checksum (optional) */ - - -/*-************************************ -* Structures and local types -**************************************/ -typedef struct LZ4F_cctx_s -{ - LZ4F_preferences_t prefs; - U32 version; - U32 cStage; - const LZ4F_CDict* cdict; - size_t maxBlockSize; - size_t maxBufferSize; - BYTE* tmpBuff; - BYTE* tmpIn; - size_t tmpInSize; - U64 totalInSize; - XXH32_state_t xxh; - void* lz4CtxPtr; - U16 lz4CtxAlloc; /* sized for: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */ - U16 lz4CtxState; /* in use as: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */ -} LZ4F_cctx_t; - - -/*-************************************ -* Error management -**************************************/ -#define LZ4F_GENERATE_STRING(STRING) #STRING, -static const char* LZ4F_errorStrings[] = { LZ4F_LIST_ERRORS(LZ4F_GENERATE_STRING) }; - - -unsigned LZ4F_isError(LZ4F_errorCode_t code) -{ - return (code > (LZ4F_errorCode_t)(-LZ4F_ERROR_maxCode)); -} - -const char* LZ4F_getErrorName(LZ4F_errorCode_t code) -{ - static const char* codeError = "Unspecified error code"; - if (LZ4F_isError(code)) return LZ4F_errorStrings[-(int)(code)]; - return codeError; -} - -LZ4F_errorCodes LZ4F_getErrorCode(size_t functionResult) -{ - if (!LZ4F_isError(functionResult)) return LZ4F_OK_NoError; - return (LZ4F_errorCodes)(-(ptrdiff_t)functionResult); -} - -static LZ4F_errorCode_t err0r(LZ4F_errorCodes code) -{ - /* A compilation error here means sizeof(ptrdiff_t) is not large enough */ - LZ4F_STATIC_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t)); - return (LZ4F_errorCode_t)-(ptrdiff_t)code; -} - -unsigned LZ4F_getVersion(void) { return LZ4F_VERSION; } - -int LZ4F_compressionLevel_max(void) { return LZ4HC_CLEVEL_MAX; } - -size_t LZ4F_getBlockSize(unsigned blockSizeID) -{ - static const size_t blockSizes[4] = { 64 KB, 256 KB, 1 MB, 4 MB }; - - if (blockSizeID == 0) blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT; - if (blockSizeID < LZ4F_max64KB || blockSizeID > LZ4F_max4MB) - return err0r(LZ4F_ERROR_maxBlockSize_invalid); - blockSizeID -= LZ4F_max64KB; - return blockSizes[blockSizeID]; -} - -/*-************************************ -* Private functions -**************************************/ -#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) - -static BYTE LZ4F_headerChecksum (const void* header, size_t length) -{ - U32 const xxh = XXH32(header, length, 0); - return (BYTE)(xxh >> 8); -} - - -/*-************************************ -* Simple-pass compression functions -**************************************/ -static LZ4F_blockSizeID_t LZ4F_optimalBSID(const LZ4F_blockSizeID_t requestedBSID, - const size_t srcSize) -{ - LZ4F_blockSizeID_t proposedBSID = LZ4F_max64KB; - size_t maxBlockSize = 64 KB; - while (requestedBSID > proposedBSID) { - if (srcSize <= maxBlockSize) - return proposedBSID; - proposedBSID = (LZ4F_blockSizeID_t)((int)proposedBSID + 1); - maxBlockSize <<= 2; - } - return requestedBSID; -} - -/*! LZ4F_compressBound_internal() : - * Provides dstCapacity given a srcSize to guarantee operation success in worst case situations. - * prefsPtr is optional : if NULL is provided, preferences will be set to cover worst case scenario. - * @return is always the same for a srcSize and prefsPtr, so it can be relied upon to size reusable buffers. - * When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() operations. - */ -static size_t LZ4F_compressBound_internal(size_t srcSize, - const LZ4F_preferences_t* preferencesPtr, - size_t alreadyBuffered) -{ - LZ4F_preferences_t prefsNull = LZ4F_INIT_PREFERENCES; - prefsNull.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled; /* worst case */ - prefsNull.frameInfo.blockChecksumFlag = LZ4F_blockChecksumEnabled; /* worst case */ - { const LZ4F_preferences_t* const prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr; - U32 const flush = prefsPtr->autoFlush | (srcSize==0); - LZ4F_blockSizeID_t const blockID = prefsPtr->frameInfo.blockSizeID; - size_t const blockSize = LZ4F_getBlockSize(blockID); - size_t const maxBuffered = blockSize - 1; - size_t const bufferedSize = MIN(alreadyBuffered, maxBuffered); - size_t const maxSrcSize = srcSize + bufferedSize; - unsigned const nbFullBlocks = (unsigned)(maxSrcSize / blockSize); - size_t const partialBlockSize = maxSrcSize & (blockSize-1); - size_t const lastBlockSize = flush ? partialBlockSize : 0; - unsigned const nbBlocks = nbFullBlocks + (lastBlockSize>0); - - size_t const blockCRCSize = BFSize * prefsPtr->frameInfo.blockChecksumFlag; - size_t const frameEnd = BHSize + (prefsPtr->frameInfo.contentChecksumFlag*BFSize); - - return ((BHSize + blockCRCSize) * nbBlocks) + - (blockSize * nbFullBlocks) + lastBlockSize + frameEnd; - } -} - -size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr) -{ - LZ4F_preferences_t prefs; - size_t const headerSize = maxFHSize; /* max header size, including optional fields */ - - if (preferencesPtr!=NULL) prefs = *preferencesPtr; - else MEM_INIT(&prefs, 0, sizeof(prefs)); - prefs.autoFlush = 1; - - return headerSize + LZ4F_compressBound_internal(srcSize, &prefs, 0);; -} - - -/*! LZ4F_compressFrame_usingCDict() : - * Compress srcBuffer using a dictionary, in a single step. - * cdict can be NULL, in which case, no dictionary is used. - * dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). - * The LZ4F_preferences_t structure is optional : you may provide NULL as argument, - * however, it's the only way to provide a dictID, so it's not recommended. - * @return : number of bytes written into dstBuffer, - * or an error code if it fails (can be tested using LZ4F_isError()) - */ -size_t LZ4F_compressFrame_usingCDict(LZ4F_cctx* cctx, - void* dstBuffer, size_t dstCapacity, - const void* srcBuffer, size_t srcSize, - const LZ4F_CDict* cdict, - const LZ4F_preferences_t* preferencesPtr) -{ - LZ4F_preferences_t prefs; - LZ4F_compressOptions_t options; - BYTE* const dstStart = (BYTE*) dstBuffer; - BYTE* dstPtr = dstStart; - BYTE* const dstEnd = dstStart + dstCapacity; - - if (preferencesPtr!=NULL) - prefs = *preferencesPtr; - else - MEM_INIT(&prefs, 0, sizeof(prefs)); - if (prefs.frameInfo.contentSize != 0) - prefs.frameInfo.contentSize = (U64)srcSize; /* auto-correct content size if selected (!=0) */ - - prefs.frameInfo.blockSizeID = LZ4F_optimalBSID(prefs.frameInfo.blockSizeID, srcSize); - prefs.autoFlush = 1; - if (srcSize <= LZ4F_getBlockSize(prefs.frameInfo.blockSizeID)) - prefs.frameInfo.blockMode = LZ4F_blockIndependent; /* only one block => no need for inter-block link */ - - MEM_INIT(&options, 0, sizeof(options)); - options.stableSrc = 1; - - if (dstCapacity < LZ4F_compressFrameBound(srcSize, &prefs)) /* condition to guarantee success */ - return err0r(LZ4F_ERROR_dstMaxSize_tooSmall); - - { size_t const headerSize = LZ4F_compressBegin_usingCDict(cctx, dstBuffer, dstCapacity, cdict, &prefs); /* write header */ - if (LZ4F_isError(headerSize)) return headerSize; - dstPtr += headerSize; /* header size */ } - - assert(dstEnd >= dstPtr); - { size_t const cSize = LZ4F_compressUpdate(cctx, dstPtr, (size_t)(dstEnd-dstPtr), srcBuffer, srcSize, &options); - if (LZ4F_isError(cSize)) return cSize; - dstPtr += cSize; } - - assert(dstEnd >= dstPtr); - { size_t const tailSize = LZ4F_compressEnd(cctx, dstPtr, (size_t)(dstEnd-dstPtr), &options); /* flush last block, and generate suffix */ - if (LZ4F_isError(tailSize)) return tailSize; - dstPtr += tailSize; } - - assert(dstEnd >= dstStart); - return (size_t)(dstPtr - dstStart); -} - - -/*! LZ4F_compressFrame() : - * Compress an entire srcBuffer into a valid LZ4 frame, in a single step. - * dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). - * The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default. - * @return : number of bytes written into dstBuffer. - * or an error code if it fails (can be tested using LZ4F_isError()) - */ -size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity, - const void* srcBuffer, size_t srcSize, - const LZ4F_preferences_t* preferencesPtr) -{ - size_t result; -#if (LZ4F_HEAPMODE) - LZ4F_cctx_t *cctxPtr; - result = LZ4F_createCompressionContext(&cctxPtr, LZ4F_VERSION); - if (LZ4F_isError(result)) return result; -#else - LZ4F_cctx_t cctx; - LZ4_stream_t lz4ctx; - LZ4F_cctx_t *cctxPtr = &cctx; - - DEBUGLOG(4, "LZ4F_compressFrame"); - MEM_INIT(&cctx, 0, sizeof(cctx)); - cctx.version = LZ4F_VERSION; - cctx.maxBufferSize = 5 MB; /* mess with real buffer size to prevent dynamic allocation; works only because autoflush==1 & stableSrc==1 */ - if (preferencesPtr == NULL || - preferencesPtr->compressionLevel < LZ4HC_CLEVEL_MIN) - { - LZ4_initStream(&lz4ctx, sizeof(lz4ctx)); - cctxPtr->lz4CtxPtr = &lz4ctx; - cctxPtr->lz4CtxAlloc = 1; - cctxPtr->lz4CtxState = 1; - } -#endif - - result = LZ4F_compressFrame_usingCDict(cctxPtr, dstBuffer, dstCapacity, - srcBuffer, srcSize, - NULL, preferencesPtr); - -#if (LZ4F_HEAPMODE) - LZ4F_freeCompressionContext(cctxPtr); -#else - if (preferencesPtr != NULL && - preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN) - { - FREEMEM(cctxPtr->lz4CtxPtr); - } -#endif - return result; -} - - -/*-*************************************************** -* Dictionary compression -*****************************************************/ - -struct LZ4F_CDict_s { - void* dictContent; - LZ4_stream_t* fastCtx; - LZ4_streamHC_t* HCCtx; -}; /* typedef'd to LZ4F_CDict within lz4frame_static.h */ - -/*! LZ4F_createCDict() : - * When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once. - * LZ4F_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay. - * LZ4F_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. - * `dictBuffer` can be released after LZ4F_CDict creation, since its content is copied within CDict - * @return : digested dictionary for compression, or NULL if failed */ -LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize) -{ - const char* dictStart = (const char*)dictBuffer; - LZ4F_CDict* cdict = (LZ4F_CDict*) ALLOC(sizeof(*cdict)); - DEBUGLOG(4, "LZ4F_createCDict"); - if (!cdict) return NULL; - if (dictSize > 64 KB) { - dictStart += dictSize - 64 KB; - dictSize = 64 KB; - } - cdict->dictContent = ALLOC(dictSize); - cdict->fastCtx = LZ4_createStream(); - cdict->HCCtx = LZ4_createStreamHC(); - if (!cdict->dictContent || !cdict->fastCtx || !cdict->HCCtx) { - LZ4F_freeCDict(cdict); - return NULL; - } - memcpy(cdict->dictContent, dictStart, dictSize); - LZ4_loadDict (cdict->fastCtx, (const char*)cdict->dictContent, (int)dictSize); - LZ4_setCompressionLevel(cdict->HCCtx, LZ4HC_CLEVEL_DEFAULT); - LZ4_loadDictHC(cdict->HCCtx, (const char*)cdict->dictContent, (int)dictSize); - return cdict; -} - -void LZ4F_freeCDict(LZ4F_CDict* cdict) -{ - if (cdict==NULL) return; /* support free on NULL */ - FREEMEM(cdict->dictContent); - LZ4_freeStream(cdict->fastCtx); - LZ4_freeStreamHC(cdict->HCCtx); - FREEMEM(cdict); -} - - -/*-********************************* -* Advanced compression functions -***********************************/ - -/*! LZ4F_createCompressionContext() : - * The first thing to do is to create a compressionContext object, which will be used in all compression operations. - * This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure. - * The version provided MUST be LZ4F_VERSION. It is intended to track potential incompatible differences between different binaries. - * The function will provide a pointer to an allocated LZ4F_compressionContext_t object. - * If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation. - * Object can release its memory using LZ4F_freeCompressionContext(); - */ -LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** LZ4F_compressionContextPtr, unsigned version) -{ - LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)ALLOC_AND_ZERO(sizeof(LZ4F_cctx_t)); - if (cctxPtr==NULL) return err0r(LZ4F_ERROR_allocation_failed); - - cctxPtr->version = version; - cctxPtr->cStage = 0; /* Next stage : init stream */ - - *LZ4F_compressionContextPtr = cctxPtr; - - return LZ4F_OK_NoError; -} - - -LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctxPtr) -{ - if (cctxPtr != NULL) { /* support free on NULL */ - FREEMEM(cctxPtr->lz4CtxPtr); /* note: LZ4_streamHC_t and LZ4_stream_t are simple POD types */ - FREEMEM(cctxPtr->tmpBuff); - FREEMEM(cctxPtr); - } - - return LZ4F_OK_NoError; -} - - -/** - * This function prepares the internal LZ4(HC) stream for a new compression, - * resetting the context and attaching the dictionary, if there is one. - * - * It needs to be called at the beginning of each independent compression - * stream (i.e., at the beginning of a frame in blockLinked mode, or at the - * beginning of each block in blockIndependent mode). - */ -static void LZ4F_initStream(void* ctx, - const LZ4F_CDict* cdict, - int level, - LZ4F_blockMode_t blockMode) { - if (level < LZ4HC_CLEVEL_MIN) { - if (cdict != NULL || blockMode == LZ4F_blockLinked) { - /* In these cases, we will call LZ4_compress_fast_continue(), - * which needs an already reset context. Otherwise, we'll call a - * one-shot API. The non-continued APIs internally perform their own - * resets at the beginning of their calls, where they know what - * tableType they need the context to be in. So in that case this - * would be misguided / wasted work. */ - LZ4_resetStream_fast((LZ4_stream_t*)ctx); - } - LZ4_attach_dictionary((LZ4_stream_t *)ctx, cdict ? cdict->fastCtx : NULL); - } else { - LZ4_resetStreamHC_fast((LZ4_streamHC_t*)ctx, level); - LZ4_attach_HC_dictionary((LZ4_streamHC_t *)ctx, cdict ? cdict->HCCtx : NULL); - } -} - - -/*! LZ4F_compressBegin_usingCDict() : - * init streaming compression and writes frame header into dstBuffer. - * dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes. - * @return : number of bytes written into dstBuffer for the header - * or an error code (can be tested using LZ4F_isError()) - */ -size_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctxPtr, - void* dstBuffer, size_t dstCapacity, - const LZ4F_CDict* cdict, - const LZ4F_preferences_t* preferencesPtr) -{ - LZ4F_preferences_t prefNull; - BYTE* const dstStart = (BYTE*)dstBuffer; - BYTE* dstPtr = dstStart; - BYTE* headerStart; - - if (dstCapacity < maxFHSize) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall); - MEM_INIT(&prefNull, 0, sizeof(prefNull)); - if (preferencesPtr == NULL) preferencesPtr = &prefNull; - cctxPtr->prefs = *preferencesPtr; - - /* Ctx Management */ - { U16 const ctxTypeID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2; - if (cctxPtr->lz4CtxAlloc < ctxTypeID) { - FREEMEM(cctxPtr->lz4CtxPtr); - if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { - cctxPtr->lz4CtxPtr = LZ4_createStream(); - } else { - cctxPtr->lz4CtxPtr = LZ4_createStreamHC(); - } - if (cctxPtr->lz4CtxPtr == NULL) - return err0r(LZ4F_ERROR_allocation_failed); - cctxPtr->lz4CtxAlloc = ctxTypeID; - cctxPtr->lz4CtxState = ctxTypeID; - } else if (cctxPtr->lz4CtxState != ctxTypeID) { - /* otherwise, a sufficient buffer is allocated, but we need to - * reset it to the correct context type */ - if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) { - LZ4_initStream((LZ4_stream_t *) cctxPtr->lz4CtxPtr, sizeof (LZ4_stream_t)); - } else { - LZ4_initStreamHC((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, sizeof(LZ4_streamHC_t)); - LZ4_setCompressionLevel((LZ4_streamHC_t *) cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel); - } - cctxPtr->lz4CtxState = ctxTypeID; - } - } - - /* Buffer Management */ - if (cctxPtr->prefs.frameInfo.blockSizeID == 0) - cctxPtr->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT; - cctxPtr->maxBlockSize = LZ4F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID); - - { size_t const requiredBuffSize = preferencesPtr->autoFlush ? - ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 64 KB : 0) : /* only needs past data up to window size */ - cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 128 KB : 0); - - if (cctxPtr->maxBufferSize < requiredBuffSize) { - cctxPtr->maxBufferSize = 0; - FREEMEM(cctxPtr->tmpBuff); - cctxPtr->tmpBuff = (BYTE*)ALLOC_AND_ZERO(requiredBuffSize); - if (cctxPtr->tmpBuff == NULL) return err0r(LZ4F_ERROR_allocation_failed); - cctxPtr->maxBufferSize = requiredBuffSize; - } } - cctxPtr->tmpIn = cctxPtr->tmpBuff; - cctxPtr->tmpInSize = 0; - (void)XXH32_reset(&(cctxPtr->xxh), 0); - - /* context init */ - cctxPtr->cdict = cdict; - if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) { - /* frame init only for blockLinked : blockIndependent will be init at each block */ - LZ4F_initStream(cctxPtr->lz4CtxPtr, cdict, cctxPtr->prefs.compressionLevel, LZ4F_blockLinked); - } - if (preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN) { - LZ4_favorDecompressionSpeed((LZ4_streamHC_t*)cctxPtr->lz4CtxPtr, (int)preferencesPtr->favorDecSpeed); - } - - /* Magic Number */ - LZ4F_writeLE32(dstPtr, LZ4F_MAGICNUMBER); - dstPtr += 4; - headerStart = dstPtr; - - /* FLG Byte */ - *dstPtr++ = (BYTE)(((1 & _2BITS) << 6) /* Version('01') */ - + ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5) - + ((cctxPtr->prefs.frameInfo.blockChecksumFlag & _1BIT ) << 4) - + ((unsigned)(cctxPtr->prefs.frameInfo.contentSize > 0) << 3) - + ((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2) - + (cctxPtr->prefs.frameInfo.dictID > 0) ); - /* BD Byte */ - *dstPtr++ = (BYTE)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4); - /* Optional Frame content size field */ - if (cctxPtr->prefs.frameInfo.contentSize) { - LZ4F_writeLE64(dstPtr, cctxPtr->prefs.frameInfo.contentSize); - dstPtr += 8; - cctxPtr->totalInSize = 0; - } - /* Optional dictionary ID field */ - if (cctxPtr->prefs.frameInfo.dictID) { - LZ4F_writeLE32(dstPtr, cctxPtr->prefs.frameInfo.dictID); - dstPtr += 4; - } - /* Header CRC Byte */ - *dstPtr = LZ4F_headerChecksum(headerStart, (size_t)(dstPtr - headerStart)); - dstPtr++; - - cctxPtr->cStage = 1; /* header written, now request input data block */ - return (size_t)(dstPtr - dstStart); -} - - -/*! LZ4F_compressBegin() : - * init streaming compression and writes frame header into dstBuffer. - * dstBuffer must be >= LZ4F_HEADER_SIZE_MAX bytes. - * preferencesPtr can be NULL, in which case default parameters are selected. - * @return : number of bytes written into dstBuffer for the header - * or an error code (can be tested using LZ4F_isError()) - */ -size_t LZ4F_compressBegin(LZ4F_cctx* cctxPtr, - void* dstBuffer, size_t dstCapacity, - const LZ4F_preferences_t* preferencesPtr) -{ - return LZ4F_compressBegin_usingCDict(cctxPtr, dstBuffer, dstCapacity, - NULL, preferencesPtr); -} - - -/* LZ4F_compressBound() : - * @return minimum capacity of dstBuffer for a given srcSize to handle worst case scenario. - * LZ4F_preferences_t structure is optional : if NULL, preferences will be set to cover worst case scenario. - * This function cannot fail. - */ -size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr) -{ - if (preferencesPtr && preferencesPtr->autoFlush) { - return LZ4F_compressBound_internal(srcSize, preferencesPtr, 0); - } - return LZ4F_compressBound_internal(srcSize, preferencesPtr, (size_t)-1); -} - - -typedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level, const LZ4F_CDict* cdict); - - -/*! LZ4F_makeBlock(): - * compress a single block, add header and optional checksum. - * assumption : dst buffer capacity is >= BHSize + srcSize + crcSize - */ -static size_t LZ4F_makeBlock(void* dst, - const void* src, size_t srcSize, - compressFunc_t compress, void* lz4ctx, int level, - const LZ4F_CDict* cdict, - LZ4F_blockChecksum_t crcFlag) -{ - BYTE* const cSizePtr = (BYTE*)dst; - U32 cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+BHSize), - (int)(srcSize), (int)(srcSize-1), - level, cdict); - if (cSize == 0) { /* compression failed */ - DEBUGLOG(5, "LZ4F_makeBlock: compression failed, creating a raw block (size %u)", (U32)srcSize); - cSize = (U32)srcSize; - LZ4F_writeLE32(cSizePtr, cSize | LZ4F_BLOCKUNCOMPRESSED_FLAG); - memcpy(cSizePtr+BHSize, src, srcSize); - } else { - LZ4F_writeLE32(cSizePtr, cSize); - } - if (crcFlag) { - U32 const crc32 = XXH32(cSizePtr+BHSize, cSize, 0); /* checksum of compressed data */ - LZ4F_writeLE32(cSizePtr+BHSize+cSize, crc32); - } - return BHSize + cSize + ((U32)crcFlag)*BFSize; -} - - -static int LZ4F_compressBlock(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict) -{ - int const acceleration = (level < 0) ? -level + 1 : 1; - LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent); - if (cdict) { - return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration); - } else { - return LZ4_compress_fast_extState_fastReset(ctx, src, dst, srcSize, dstCapacity, acceleration); - } -} - -static int LZ4F_compressBlock_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict) -{ - int const acceleration = (level < 0) ? -level + 1 : 1; - (void)cdict; /* init once at beginning of frame */ - return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration); -} - -static int LZ4F_compressBlockHC(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict) -{ - LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent); - if (cdict) { - return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity); - } - return LZ4_compress_HC_extStateHC_fastReset(ctx, src, dst, srcSize, dstCapacity, level); -} - -static int LZ4F_compressBlockHC_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict) -{ - (void)level; (void)cdict; /* init once at beginning of frame */ - return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity); -} - -static compressFunc_t LZ4F_selectCompression(LZ4F_blockMode_t blockMode, int level) -{ - if (level < LZ4HC_CLEVEL_MIN) { - if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlock; - return LZ4F_compressBlock_continue; - } - if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlockHC; - return LZ4F_compressBlockHC_continue; -} - -static int LZ4F_localSaveDict(LZ4F_cctx_t* cctxPtr) -{ - if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) - return LZ4_saveDict ((LZ4_stream_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB); - return LZ4_saveDictHC ((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB); -} - -typedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LZ4F_lastBlockStatus; - -/*! LZ4F_compressUpdate() : - * LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary. - * dstBuffer MUST be >= LZ4F_compressBound(srcSize, preferencesPtr). - * LZ4F_compressOptions_t structure is optional : you can provide NULL as argument. - * @return : the number of bytes written into dstBuffer. It can be zero, meaning input data was just buffered. - * or an error code if it fails (which can be tested using LZ4F_isError()) - */ -size_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr, - void* dstBuffer, size_t dstCapacity, - const void* srcBuffer, size_t srcSize, - const LZ4F_compressOptions_t* compressOptionsPtr) -{ - LZ4F_compressOptions_t cOptionsNull; - size_t const blockSize = cctxPtr->maxBlockSize; - const BYTE* srcPtr = (const BYTE*)srcBuffer; - const BYTE* const srcEnd = srcPtr + srcSize; - BYTE* const dstStart = (BYTE*)dstBuffer; - BYTE* dstPtr = dstStart; - LZ4F_lastBlockStatus lastBlockCompressed = notDone; - compressFunc_t const compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel); - - DEBUGLOG(4, "LZ4F_compressUpdate (srcSize=%zu)", srcSize); - - if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC); - if (dstCapacity < LZ4F_compressBound_internal(srcSize, &(cctxPtr->prefs), cctxPtr->tmpInSize)) - return err0r(LZ4F_ERROR_dstMaxSize_tooSmall); - MEM_INIT(&cOptionsNull, 0, sizeof(cOptionsNull)); - if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull; - - /* complete tmp buffer */ - if (cctxPtr->tmpInSize > 0) { /* some data already within tmp buffer */ - size_t const sizeToCopy = blockSize - cctxPtr->tmpInSize; - if (sizeToCopy > srcSize) { - /* add src to tmpIn buffer */ - memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize); - srcPtr = srcEnd; - cctxPtr->tmpInSize += srcSize; - /* still needs some CRC */ - } else { - /* complete tmpIn block and then compress it */ - lastBlockCompressed = fromTmpBuffer; - memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy); - srcPtr += sizeToCopy; - - dstPtr += LZ4F_makeBlock(dstPtr, - cctxPtr->tmpIn, blockSize, - compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel, - cctxPtr->cdict, - cctxPtr->prefs.frameInfo.blockChecksumFlag); - - if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += blockSize; - cctxPtr->tmpInSize = 0; - } - } - - while ((size_t)(srcEnd - srcPtr) >= blockSize) { - /* compress full blocks */ - lastBlockCompressed = fromSrcBuffer; - dstPtr += LZ4F_makeBlock(dstPtr, - srcPtr, blockSize, - compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel, - cctxPtr->cdict, - cctxPtr->prefs.frameInfo.blockChecksumFlag); - srcPtr += blockSize; - } - - if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd)) { - /* compress remaining input < blockSize */ - lastBlockCompressed = fromSrcBuffer; - dstPtr += LZ4F_makeBlock(dstPtr, - srcPtr, (size_t)(srcEnd - srcPtr), - compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel, - cctxPtr->cdict, - cctxPtr->prefs.frameInfo.blockChecksumFlag); - srcPtr = srcEnd; - } - - /* preserve dictionary if necessary */ - if ((cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) && (lastBlockCompressed==fromSrcBuffer)) { - if (compressOptionsPtr->stableSrc) { - cctxPtr->tmpIn = cctxPtr->tmpBuff; - } else { - int const realDictSize = LZ4F_localSaveDict(cctxPtr); - if (realDictSize==0) return err0r(LZ4F_ERROR_GENERIC); - cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize; - } - } - - /* keep tmpIn within limits */ - if ((cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize) /* necessarily LZ4F_blockLinked && lastBlockCompressed==fromTmpBuffer */ - && !(cctxPtr->prefs.autoFlush)) - { - int const realDictSize = LZ4F_localSaveDict(cctxPtr); - cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize; - } - - /* some input data left, necessarily < blockSize */ - if (srcPtr < srcEnd) { - /* fill tmp buffer */ - size_t const sizeToCopy = (size_t)(srcEnd - srcPtr); - memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy); - cctxPtr->tmpInSize = sizeToCopy; - } - - if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) - (void)XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize); - - cctxPtr->totalInSize += srcSize; - return (size_t)(dstPtr - dstStart); -} - - -/*! LZ4F_flush() : - * When compressed data must be sent immediately, without waiting for a block to be filled, - * invoke LZ4_flush(), which will immediately compress any remaining data stored within LZ4F_cctx. - * The result of the function is the number of bytes written into dstBuffer. - * It can be zero, this means there was no data left within LZ4F_cctx. - * The function outputs an error code if it fails (can be tested using LZ4F_isError()) - * LZ4F_compressOptions_t* is optional. NULL is a valid argument. - */ -size_t LZ4F_flush(LZ4F_cctx* cctxPtr, - void* dstBuffer, size_t dstCapacity, - const LZ4F_compressOptions_t* compressOptionsPtr) -{ - BYTE* const dstStart = (BYTE*)dstBuffer; - BYTE* dstPtr = dstStart; - compressFunc_t compress; - - if (cctxPtr->tmpInSize == 0) return 0; /* nothing to flush */ - if (cctxPtr->cStage != 1) return err0r(LZ4F_ERROR_GENERIC); - if (dstCapacity < (cctxPtr->tmpInSize + BHSize + BFSize)) - return err0r(LZ4F_ERROR_dstMaxSize_tooSmall); - (void)compressOptionsPtr; /* not yet useful */ - - /* select compression function */ - compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel); - - /* compress tmp buffer */ - dstPtr += LZ4F_makeBlock(dstPtr, - cctxPtr->tmpIn, cctxPtr->tmpInSize, - compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel, - cctxPtr->cdict, - cctxPtr->prefs.frameInfo.blockChecksumFlag); - assert(((void)"flush overflows dstBuffer!", (size_t)(dstPtr - dstStart) <= dstCapacity)); - - if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked) - cctxPtr->tmpIn += cctxPtr->tmpInSize; - cctxPtr->tmpInSize = 0; - - /* keep tmpIn within limits */ - if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) { /* necessarily LZ4F_blockLinked */ - int const realDictSize = LZ4F_localSaveDict(cctxPtr); - cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize; - } - - return (size_t)(dstPtr - dstStart); -} - - -/*! LZ4F_compressEnd() : - * When you want to properly finish the compressed frame, just call LZ4F_compressEnd(). - * It will flush whatever data remained within compressionContext (like LZ4_flush()) - * but also properly finalize the frame, with an endMark and an (optional) checksum. - * LZ4F_compressOptions_t structure is optional : you can provide NULL as argument. - * @return: the number of bytes written into dstBuffer (necessarily >= 4 (endMark size)) - * or an error code if it fails (can be tested using LZ4F_isError()) - * The context can then be used again to compress a new frame, starting with LZ4F_compressBegin(). - */ -size_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr, - void* dstBuffer, size_t dstCapacity, - const LZ4F_compressOptions_t* compressOptionsPtr) -{ - BYTE* const dstStart = (BYTE*)dstBuffer; - BYTE* dstPtr = dstStart; - - size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr); - DEBUGLOG(5,"LZ4F_compressEnd: dstCapacity=%u", (unsigned)dstCapacity); - if (LZ4F_isError(flushSize)) return flushSize; - dstPtr += flushSize; - - assert(flushSize <= dstCapacity); - dstCapacity -= flushSize; - - if (dstCapacity < 4) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall); - LZ4F_writeLE32(dstPtr, 0); - dstPtr += 4; /* endMark */ - - if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) { - U32 const xxh = XXH32_digest(&(cctxPtr->xxh)); - if (dstCapacity < 8) return err0r(LZ4F_ERROR_dstMaxSize_tooSmall); - DEBUGLOG(5,"Writing 32-bit content checksum"); - LZ4F_writeLE32(dstPtr, xxh); - dstPtr+=4; /* content Checksum */ - } - - cctxPtr->cStage = 0; /* state is now re-usable (with identical preferences) */ - cctxPtr->maxBufferSize = 0; /* reuse HC context */ - - if (cctxPtr->prefs.frameInfo.contentSize) { - if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize) - return err0r(LZ4F_ERROR_frameSize_wrong); - } - - return (size_t)(dstPtr - dstStart); -} - - -/*-*************************************************** -* Frame Decompression -*****************************************************/ - -typedef enum { - dstage_getFrameHeader=0, dstage_storeFrameHeader, - dstage_init, - dstage_getBlockHeader, dstage_storeBlockHeader, - dstage_copyDirect, dstage_getBlockChecksum, - dstage_getCBlock, dstage_storeCBlock, - dstage_flushOut, - dstage_getSuffix, dstage_storeSuffix, - dstage_getSFrameSize, dstage_storeSFrameSize, - dstage_skipSkippable -} dStage_t; - -struct LZ4F_dctx_s { - LZ4F_frameInfo_t frameInfo; - U32 version; - dStage_t dStage; - U64 frameRemainingSize; - size_t maxBlockSize; - size_t maxBufferSize; - BYTE* tmpIn; - size_t tmpInSize; - size_t tmpInTarget; - BYTE* tmpOutBuffer; - const BYTE* dict; - size_t dictSize; - BYTE* tmpOut; - size_t tmpOutSize; - size_t tmpOutStart; - XXH32_state_t xxh; - XXH32_state_t blockChecksum; - BYTE header[LZ4F_HEADER_SIZE_MAX]; -}; /* typedef'd to LZ4F_dctx in lz4frame.h */ - - -/*! LZ4F_createDecompressionContext() : - * Create a decompressionContext object, which will track all decompression operations. - * Provides a pointer to a fully allocated and initialized LZ4F_decompressionContext object. - * Object can later be released using LZ4F_freeDecompressionContext(). - * @return : if != 0, there was an error during context creation. - */ -LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** LZ4F_decompressionContextPtr, unsigned versionNumber) -{ - LZ4F_dctx* const dctx = (LZ4F_dctx*)ALLOC_AND_ZERO(sizeof(LZ4F_dctx)); - if (dctx == NULL) { /* failed allocation */ - *LZ4F_decompressionContextPtr = NULL; - return err0r(LZ4F_ERROR_allocation_failed); - } - - dctx->version = versionNumber; - *LZ4F_decompressionContextPtr = dctx; - return LZ4F_OK_NoError; -} - -LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx) -{ - LZ4F_errorCode_t result = LZ4F_OK_NoError; - if (dctx != NULL) { /* can accept NULL input, like free() */ - result = (LZ4F_errorCode_t)dctx->dStage; - FREEMEM(dctx->tmpIn); - FREEMEM(dctx->tmpOutBuffer); - FREEMEM(dctx); - } - return result; -} - - -/*==--- Streaming Decompression operations ---==*/ - -void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx) -{ - dctx->dStage = dstage_getFrameHeader; - dctx->dict = NULL; - dctx->dictSize = 0; -} - - -/*! LZ4F_decodeHeader() : - * input : `src` points at the **beginning of the frame** - * output : set internal values of dctx, such as - * dctx->frameInfo and dctx->dStage. - * Also allocates internal buffers. - * @return : nb Bytes read from src (necessarily <= srcSize) - * or an error code (testable with LZ4F_isError()) - */ -static size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize) -{ - unsigned blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, dictIDFlag, blockSizeID; - size_t frameHeaderSize; - const BYTE* srcPtr = (const BYTE*)src; - - DEBUGLOG(5, "LZ4F_decodeHeader"); - /* need to decode header to get frameInfo */ - if (srcSize < minFHSize) return err0r(LZ4F_ERROR_frameHeader_incomplete); /* minimal frame header size */ - MEM_INIT(&(dctx->frameInfo), 0, sizeof(dctx->frameInfo)); - - /* special case : skippable frames */ - if ((LZ4F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) { - dctx->frameInfo.frameType = LZ4F_skippableFrame; - if (src == (void*)(dctx->header)) { - dctx->tmpInSize = srcSize; - dctx->tmpInTarget = 8; - dctx->dStage = dstage_storeSFrameSize; - return srcSize; - } else { - dctx->dStage = dstage_getSFrameSize; - return 4; - } - } - - /* control magic number */ -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) { - DEBUGLOG(4, "frame header error : unknown magic number"); - return err0r(LZ4F_ERROR_frameType_unknown); - } -#endif - dctx->frameInfo.frameType = LZ4F_frame; - - /* Flags */ - { U32 const FLG = srcPtr[4]; - U32 const version = (FLG>>6) & _2BITS; - blockChecksumFlag = (FLG>>4) & _1BIT; - blockMode = (FLG>>5) & _1BIT; - contentSizeFlag = (FLG>>3) & _1BIT; - contentChecksumFlag = (FLG>>2) & _1BIT; - dictIDFlag = FLG & _1BIT; - /* validate */ - if (((FLG>>1)&_1BIT) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bit */ - if (version != 1) return err0r(LZ4F_ERROR_headerVersion_wrong); /* Version Number, only supported value */ - } - - /* Frame Header Size */ - frameHeaderSize = minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0); - - if (srcSize < frameHeaderSize) { - /* not enough input to fully decode frame header */ - if (srcPtr != dctx->header) - memcpy(dctx->header, srcPtr, srcSize); - dctx->tmpInSize = srcSize; - dctx->tmpInTarget = frameHeaderSize; - dctx->dStage = dstage_storeFrameHeader; - return srcSize; - } - - { U32 const BD = srcPtr[5]; - blockSizeID = (BD>>4) & _3BITS; - /* validate */ - if (((BD>>7)&_1BIT) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bit */ - if (blockSizeID < 4) return err0r(LZ4F_ERROR_maxBlockSize_invalid); /* 4-7 only supported values for the time being */ - if (((BD>>0)&_4BITS) != 0) return err0r(LZ4F_ERROR_reservedFlag_set); /* Reserved bits */ - } - - /* check header */ - assert(frameHeaderSize > 5); -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - { BYTE const HC = LZ4F_headerChecksum(srcPtr+4, frameHeaderSize-5); - if (HC != srcPtr[frameHeaderSize-1]) - return err0r(LZ4F_ERROR_headerChecksum_invalid); - } -#endif - - /* save */ - dctx->frameInfo.blockMode = (LZ4F_blockMode_t)blockMode; - dctx->frameInfo.blockChecksumFlag = (LZ4F_blockChecksum_t)blockChecksumFlag; - dctx->frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)contentChecksumFlag; - dctx->frameInfo.blockSizeID = (LZ4F_blockSizeID_t)blockSizeID; - dctx->maxBlockSize = LZ4F_getBlockSize(blockSizeID); - if (contentSizeFlag) - dctx->frameRemainingSize = - dctx->frameInfo.contentSize = LZ4F_readLE64(srcPtr+6); - if (dictIDFlag) - dctx->frameInfo.dictID = LZ4F_readLE32(srcPtr + frameHeaderSize - 5); - - dctx->dStage = dstage_init; - - return frameHeaderSize; -} - - -/*! LZ4F_headerSize() : - * @return : size of frame header - * or an error code, which can be tested using LZ4F_isError() - */ -size_t LZ4F_headerSize(const void* src, size_t srcSize) -{ - if (src == NULL) return err0r(LZ4F_ERROR_srcPtr_wrong); - - /* minimal srcSize to determine header size */ - if (srcSize < LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH) - return err0r(LZ4F_ERROR_frameHeader_incomplete); - - /* special case : skippable frames */ - if ((LZ4F_readLE32(src) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) - return 8; - - /* control magic number */ -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - if (LZ4F_readLE32(src) != LZ4F_MAGICNUMBER) - return err0r(LZ4F_ERROR_frameType_unknown); -#endif - - /* Frame Header Size */ - { BYTE const FLG = ((const BYTE*)src)[4]; - U32 const contentSizeFlag = (FLG>>3) & _1BIT; - U32 const dictIDFlag = FLG & _1BIT; - return minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0); - } -} - -/*! LZ4F_getFrameInfo() : - * This function extracts frame parameters (max blockSize, frame checksum, etc.). - * Usage is optional. Objective is to provide relevant information for allocation purposes. - * This function works in 2 situations : - * - At the beginning of a new frame, in which case it will decode this information from `srcBuffer`, and start the decoding process. - * Amount of input data provided must be large enough to successfully decode the frame header. - * A header size is variable, but is guaranteed to be <= LZ4F_HEADER_SIZE_MAX bytes. It's possible to provide more input data than this minimum. - * - After decoding has been started. In which case, no input is read, frame parameters are extracted from dctx. - * The number of bytes consumed from srcBuffer will be updated within *srcSizePtr (necessarily <= original value). - * Decompression must resume from (srcBuffer + *srcSizePtr). - * @return : an hint about how many srcSize bytes LZ4F_decompress() expects for next call, - * or an error code which can be tested using LZ4F_isError() - * note 1 : in case of error, dctx is not modified. Decoding operations can resume from where they stopped. - * note 2 : frame parameters are *copied into* an already allocated LZ4F_frameInfo_t structure. - */ -LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx, - LZ4F_frameInfo_t* frameInfoPtr, - const void* srcBuffer, size_t* srcSizePtr) -{ - LZ4F_STATIC_ASSERT(dstage_getFrameHeader < dstage_storeFrameHeader); - if (dctx->dStage > dstage_storeFrameHeader) { - /* frameInfo already decoded */ - size_t o=0, i=0; - *srcSizePtr = 0; - *frameInfoPtr = dctx->frameInfo; - /* returns : recommended nb of bytes for LZ4F_decompress() */ - return LZ4F_decompress(dctx, NULL, &o, NULL, &i, NULL); - } else { - if (dctx->dStage == dstage_storeFrameHeader) { - /* frame decoding already started, in the middle of header => automatic fail */ - *srcSizePtr = 0; - return err0r(LZ4F_ERROR_frameDecoding_alreadyStarted); - } else { - size_t const hSize = LZ4F_headerSize(srcBuffer, *srcSizePtr); - if (LZ4F_isError(hSize)) { *srcSizePtr=0; return hSize; } - if (*srcSizePtr < hSize) { - *srcSizePtr=0; - return err0r(LZ4F_ERROR_frameHeader_incomplete); - } - - { size_t decodeResult = LZ4F_decodeHeader(dctx, srcBuffer, hSize); - if (LZ4F_isError(decodeResult)) { - *srcSizePtr = 0; - } else { - *srcSizePtr = decodeResult; - decodeResult = BHSize; /* block header size */ - } - *frameInfoPtr = dctx->frameInfo; - return decodeResult; - } } } -} - - -/* LZ4F_updateDict() : - * only used for LZ4F_blockLinked mode - * Condition : dstPtr != NULL - */ -static void LZ4F_updateDict(LZ4F_dctx* dctx, - const BYTE* dstPtr, size_t dstSize, const BYTE* dstBufferStart, - unsigned withinTmp) -{ - assert(dstPtr != NULL); - if (dctx->dictSize==0) { - dctx->dict = (const BYTE*)dstPtr; /* priority to prefix mode */ - } - assert(dctx->dict != NULL); - - if (dctx->dict + dctx->dictSize == dstPtr) { /* prefix mode, everything within dstBuffer */ - dctx->dictSize += dstSize; - return; - } - - assert(dstPtr >= dstBufferStart); - if ((size_t)(dstPtr - dstBufferStart) + dstSize >= 64 KB) { /* history in dstBuffer becomes large enough to become dictionary */ - dctx->dict = (const BYTE*)dstBufferStart; - dctx->dictSize = (size_t)(dstPtr - dstBufferStart) + dstSize; - return; - } - - assert(dstSize < 64 KB); /* if dstSize >= 64 KB, dictionary would be set into dstBuffer directly */ - - /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOutBuffer */ - assert(dctx->tmpOutBuffer != NULL); - - if (withinTmp && (dctx->dict == dctx->tmpOutBuffer)) { /* continue history within tmpOutBuffer */ - /* withinTmp expectation : content of [dstPtr,dstSize] is same as [dict+dictSize,dstSize], so we just extend it */ - assert(dctx->dict + dctx->dictSize == dctx->tmpOut + dctx->tmpOutStart); - dctx->dictSize += dstSize; - return; - } - - if (withinTmp) { /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */ - size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer); - size_t copySize = 64 KB - dctx->tmpOutSize; - const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart; - if (dctx->tmpOutSize > 64 KB) copySize = 0; - if (copySize > preserveSize) copySize = preserveSize; - - memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize); - - dctx->dict = dctx->tmpOutBuffer; - dctx->dictSize = preserveSize + dctx->tmpOutStart + dstSize; - return; - } - - if (dctx->dict == dctx->tmpOutBuffer) { /* copy dst into tmp to complete dict */ - if (dctx->dictSize + dstSize > dctx->maxBufferSize) { /* tmp buffer not large enough */ - size_t const preserveSize = 64 KB - dstSize; - memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize); - dctx->dictSize = preserveSize; - } - memcpy(dctx->tmpOutBuffer + dctx->dictSize, dstPtr, dstSize); - dctx->dictSize += dstSize; - return; - } - - /* join dict & dest into tmp */ - { size_t preserveSize = 64 KB - dstSize; - if (preserveSize > dctx->dictSize) preserveSize = dctx->dictSize; - memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize); - memcpy(dctx->tmpOutBuffer + preserveSize, dstPtr, dstSize); - dctx->dict = dctx->tmpOutBuffer; - dctx->dictSize = preserveSize + dstSize; - } -} - - - -/*! LZ4F_decompress() : - * Call this function repetitively to regenerate compressed data in srcBuffer. - * The function will attempt to decode up to *srcSizePtr bytes from srcBuffer - * into dstBuffer of capacity *dstSizePtr. - * - * The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value). - * - * The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value). - * If number of bytes read is < number of bytes provided, then decompression operation is not complete. - * Remaining data will have to be presented again in a subsequent invocation. - * - * The function result is an hint of the better srcSize to use for next call to LZ4F_decompress. - * Schematically, it's the size of the current (or remaining) compressed block + header of next block. - * Respecting the hint provides a small boost to performance, since it allows less buffer shuffling. - * Note that this is just a hint, and it's always possible to any srcSize value. - * When a frame is fully decoded, @return will be 0. - * If decompression failed, @return is an error code which can be tested using LZ4F_isError(). - */ -size_t LZ4F_decompress(LZ4F_dctx* dctx, - void* dstBuffer, size_t* dstSizePtr, - const void* srcBuffer, size_t* srcSizePtr, - const LZ4F_decompressOptions_t* decompressOptionsPtr) -{ - LZ4F_decompressOptions_t optionsNull; - const BYTE* const srcStart = (const BYTE*)srcBuffer; - const BYTE* const srcEnd = srcStart + *srcSizePtr; - const BYTE* srcPtr = srcStart; - BYTE* const dstStart = (BYTE*)dstBuffer; - BYTE* const dstEnd = dstStart ? dstStart + *dstSizePtr : NULL; - BYTE* dstPtr = dstStart; - const BYTE* selectedIn = NULL; - unsigned doAnotherStage = 1; - size_t nextSrcSizeHint = 1; - - - DEBUGLOG(5, "LZ4F_decompress : %p,%u => %p,%u", - srcBuffer, (unsigned)*srcSizePtr, dstBuffer, (unsigned)*dstSizePtr); - if (dstBuffer == NULL) assert(*dstSizePtr == 0); - MEM_INIT(&optionsNull, 0, sizeof(optionsNull)); - if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull; - *srcSizePtr = 0; - *dstSizePtr = 0; - assert(dctx != NULL); - - /* behaves as a state machine */ - - while (doAnotherStage) { - - switch(dctx->dStage) - { - - case dstage_getFrameHeader: - DEBUGLOG(6, "dstage_getFrameHeader"); - if ((size_t)(srcEnd-srcPtr) >= maxFHSize) { /* enough to decode - shortcut */ - size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, (size_t)(srcEnd-srcPtr)); /* will update dStage appropriately */ - if (LZ4F_isError(hSize)) return hSize; - srcPtr += hSize; - break; - } - dctx->tmpInSize = 0; - if (srcEnd-srcPtr == 0) return minFHSize; /* 0-size input */ - dctx->tmpInTarget = minFHSize; /* minimum size to decode header */ - dctx->dStage = dstage_storeFrameHeader; - /* fall-through */ - - case dstage_storeFrameHeader: - DEBUGLOG(6, "dstage_storeFrameHeader"); - { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd - srcPtr)); - memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy); - dctx->tmpInSize += sizeToCopy; - srcPtr += sizeToCopy; - } - if (dctx->tmpInSize < dctx->tmpInTarget) { - nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */ - doAnotherStage = 0; /* not enough src data, ask for some more */ - break; - } - { size_t const hSize = LZ4F_decodeHeader(dctx, dctx->header, dctx->tmpInTarget); /* will update dStage appropriately */ - if (LZ4F_isError(hSize)) return hSize; - } - break; - - case dstage_init: - DEBUGLOG(6, "dstage_init"); - if (dctx->frameInfo.contentChecksumFlag) (void)XXH32_reset(&(dctx->xxh), 0); - /* internal buffers allocation */ - { size_t const bufferNeeded = dctx->maxBlockSize - + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) ? 128 KB : 0); - if (bufferNeeded > dctx->maxBufferSize) { /* tmp buffers too small */ - dctx->maxBufferSize = 0; /* ensure allocation will be re-attempted on next entry*/ - FREEMEM(dctx->tmpIn); - dctx->tmpIn = (BYTE*)ALLOC(dctx->maxBlockSize + BFSize /* block checksum */); - if (dctx->tmpIn == NULL) - return err0r(LZ4F_ERROR_allocation_failed); - FREEMEM(dctx->tmpOutBuffer); - dctx->tmpOutBuffer= (BYTE*)ALLOC(bufferNeeded); - if (dctx->tmpOutBuffer== NULL) - return err0r(LZ4F_ERROR_allocation_failed); - dctx->maxBufferSize = bufferNeeded; - } } - dctx->tmpInSize = 0; - dctx->tmpInTarget = 0; - dctx->tmpOut = dctx->tmpOutBuffer; - dctx->tmpOutStart = 0; - dctx->tmpOutSize = 0; - - dctx->dStage = dstage_getBlockHeader; - /* fall-through */ - - case dstage_getBlockHeader: - if ((size_t)(srcEnd - srcPtr) >= BHSize) { - selectedIn = srcPtr; - srcPtr += BHSize; - } else { - /* not enough input to read cBlockSize field */ - dctx->tmpInSize = 0; - dctx->dStage = dstage_storeBlockHeader; - } - - if (dctx->dStage == dstage_storeBlockHeader) /* can be skipped */ - case dstage_storeBlockHeader: - { size_t const remainingInput = (size_t)(srcEnd - srcPtr); - size_t const wantedData = BHSize - dctx->tmpInSize; - size_t const sizeToCopy = MIN(wantedData, remainingInput); - memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy); - srcPtr += sizeToCopy; - dctx->tmpInSize += sizeToCopy; - - if (dctx->tmpInSize < BHSize) { /* not enough input for cBlockSize */ - nextSrcSizeHint = BHSize - dctx->tmpInSize; - doAnotherStage = 0; - break; - } - selectedIn = dctx->tmpIn; - } /* if (dctx->dStage == dstage_storeBlockHeader) */ - - /* decode block header */ - { U32 const blockHeader = LZ4F_readLE32(selectedIn); - size_t const nextCBlockSize = blockHeader & 0x7FFFFFFFU; - size_t const crcSize = dctx->frameInfo.blockChecksumFlag * BFSize; - if (blockHeader==0) { /* frameEnd signal, no more block */ - DEBUGLOG(5, "end of frame"); - dctx->dStage = dstage_getSuffix; - break; - } - if (nextCBlockSize > dctx->maxBlockSize) { - return err0r(LZ4F_ERROR_maxBlockSize_invalid); - } - if (blockHeader & LZ4F_BLOCKUNCOMPRESSED_FLAG) { - /* next block is uncompressed */ - dctx->tmpInTarget = nextCBlockSize; - DEBUGLOG(5, "next block is uncompressed (size %u)", (U32)nextCBlockSize); - if (dctx->frameInfo.blockChecksumFlag) { - (void)XXH32_reset(&dctx->blockChecksum, 0); - } - dctx->dStage = dstage_copyDirect; - break; - } - /* next block is a compressed block */ - dctx->tmpInTarget = nextCBlockSize + crcSize; - dctx->dStage = dstage_getCBlock; - if (dstPtr==dstEnd || srcPtr==srcEnd) { - nextSrcSizeHint = BHSize + nextCBlockSize + crcSize; - doAnotherStage = 0; - } - break; - } - - case dstage_copyDirect: /* uncompressed block */ - DEBUGLOG(6, "dstage_copyDirect"); - { size_t sizeToCopy; - if (dstPtr == NULL) { - sizeToCopy = 0; - } else { - size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr)); - sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize); - memcpy(dstPtr, srcPtr, sizeToCopy); - if (dctx->frameInfo.blockChecksumFlag) { - (void)XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy); - } - if (dctx->frameInfo.contentChecksumFlag) - (void)XXH32_update(&dctx->xxh, srcPtr, sizeToCopy); - if (dctx->frameInfo.contentSize) - dctx->frameRemainingSize -= sizeToCopy; - - /* history management (linked blocks only)*/ - if (dctx->frameInfo.blockMode == LZ4F_blockLinked) { - LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0); - } } - - srcPtr += sizeToCopy; - dstPtr += sizeToCopy; - if (sizeToCopy == dctx->tmpInTarget) { /* all done */ - if (dctx->frameInfo.blockChecksumFlag) { - dctx->tmpInSize = 0; - dctx->dStage = dstage_getBlockChecksum; - } else - dctx->dStage = dstage_getBlockHeader; /* new block */ - break; - } - dctx->tmpInTarget -= sizeToCopy; /* need to copy more */ - } - nextSrcSizeHint = dctx->tmpInTarget + - +(dctx->frameInfo.blockChecksumFlag ? BFSize : 0) - + BHSize /* next header size */; - doAnotherStage = 0; - break; - - /* check block checksum for recently transferred uncompressed block */ - case dstage_getBlockChecksum: - DEBUGLOG(6, "dstage_getBlockChecksum"); - { const void* crcSrc; - if ((srcEnd-srcPtr >= 4) && (dctx->tmpInSize==0)) { - crcSrc = srcPtr; - srcPtr += 4; - } else { - size_t const stillToCopy = 4 - dctx->tmpInSize; - size_t const sizeToCopy = MIN(stillToCopy, (size_t)(srcEnd-srcPtr)); - memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy); - dctx->tmpInSize += sizeToCopy; - srcPtr += sizeToCopy; - if (dctx->tmpInSize < 4) { /* all input consumed */ - doAnotherStage = 0; - break; - } - crcSrc = dctx->header; - } - { U32 const readCRC = LZ4F_readLE32(crcSrc); - U32 const calcCRC = XXH32_digest(&dctx->blockChecksum); -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - DEBUGLOG(6, "compare block checksum"); - if (readCRC != calcCRC) { - DEBUGLOG(4, "incorrect block checksum: %08X != %08X", - readCRC, calcCRC); - return err0r(LZ4F_ERROR_blockChecksum_invalid); - } -#else - (void)readCRC; - (void)calcCRC; -#endif - } } - dctx->dStage = dstage_getBlockHeader; /* new block */ - break; - - case dstage_getCBlock: - DEBUGLOG(6, "dstage_getCBlock"); - if ((size_t)(srcEnd-srcPtr) < dctx->tmpInTarget) { - dctx->tmpInSize = 0; - dctx->dStage = dstage_storeCBlock; - break; - } - /* input large enough to read full block directly */ - selectedIn = srcPtr; - srcPtr += dctx->tmpInTarget; - - if (0) /* always jump over next block */ - case dstage_storeCBlock: - { size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize; - size_t const inputLeft = (size_t)(srcEnd-srcPtr); - size_t const sizeToCopy = MIN(wantedData, inputLeft); - memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy); - dctx->tmpInSize += sizeToCopy; - srcPtr += sizeToCopy; - if (dctx->tmpInSize < dctx->tmpInTarget) { /* need more input */ - nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) - + (dctx->frameInfo.blockChecksumFlag ? BFSize : 0) - + BHSize /* next header size */; - doAnotherStage = 0; - break; - } - selectedIn = dctx->tmpIn; - } - - /* At this stage, input is large enough to decode a block */ - if (dctx->frameInfo.blockChecksumFlag) { - dctx->tmpInTarget -= 4; - assert(selectedIn != NULL); /* selectedIn is defined at this stage (either srcPtr, or dctx->tmpIn) */ - { U32 const readBlockCrc = LZ4F_readLE32(selectedIn + dctx->tmpInTarget); - U32 const calcBlockCrc = XXH32(selectedIn, dctx->tmpInTarget, 0); -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - if (readBlockCrc != calcBlockCrc) - return err0r(LZ4F_ERROR_blockChecksum_invalid); -#else - (void)readBlockCrc; - (void)calcBlockCrc; -#endif - } } - - if ((size_t)(dstEnd-dstPtr) >= dctx->maxBlockSize) { - const char* dict = (const char*)dctx->dict; - size_t dictSize = dctx->dictSize; - int decodedSize; - assert(dstPtr != NULL); - if (dict && dictSize > 1 GB) { - /* the dictSize param is an int, avoid truncation / sign issues */ - dict += dictSize - 64 KB; - dictSize = 64 KB; - } - /* enough capacity in `dst` to decompress directly there */ - decodedSize = LZ4_decompress_safe_usingDict( - (const char*)selectedIn, (char*)dstPtr, - (int)dctx->tmpInTarget, (int)dctx->maxBlockSize, - dict, (int)dictSize); - if (decodedSize < 0) return err0r(LZ4F_ERROR_GENERIC); /* decompression failed */ - if (dctx->frameInfo.contentChecksumFlag) - XXH32_update(&(dctx->xxh), dstPtr, (size_t)decodedSize); - if (dctx->frameInfo.contentSize) - dctx->frameRemainingSize -= (size_t)decodedSize; - - /* dictionary management */ - if (dctx->frameInfo.blockMode==LZ4F_blockLinked) { - LZ4F_updateDict(dctx, dstPtr, (size_t)decodedSize, dstStart, 0); - } - - dstPtr += decodedSize; - dctx->dStage = dstage_getBlockHeader; - break; - } - - /* not enough place into dst : decode into tmpOut */ - /* ensure enough place for tmpOut */ - if (dctx->frameInfo.blockMode == LZ4F_blockLinked) { - if (dctx->dict == dctx->tmpOutBuffer) { - if (dctx->dictSize > 128 KB) { - memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - 64 KB, 64 KB); - dctx->dictSize = 64 KB; - } - dctx->tmpOut = dctx->tmpOutBuffer + dctx->dictSize; - } else { /* dict not within tmp */ - size_t const reservedDictSpace = MIN(dctx->dictSize, 64 KB); - dctx->tmpOut = dctx->tmpOutBuffer + reservedDictSpace; - } } - - /* Decode block */ - { const char* dict = (const char*)dctx->dict; - size_t dictSize = dctx->dictSize; - int decodedSize; - if (dict && dictSize > 1 GB) { - /* the dictSize param is an int, avoid truncation / sign issues */ - dict += dictSize - 64 KB; - dictSize = 64 KB; - } - decodedSize = LZ4_decompress_safe_usingDict( - (const char*)selectedIn, (char*)dctx->tmpOut, - (int)dctx->tmpInTarget, (int)dctx->maxBlockSize, - dict, (int)dictSize); - if (decodedSize < 0) /* decompression failed */ - return err0r(LZ4F_ERROR_decompressionFailed); - if (dctx->frameInfo.contentChecksumFlag) - XXH32_update(&(dctx->xxh), dctx->tmpOut, (size_t)decodedSize); - if (dctx->frameInfo.contentSize) - dctx->frameRemainingSize -= (size_t)decodedSize; - dctx->tmpOutSize = (size_t)decodedSize; - dctx->tmpOutStart = 0; - dctx->dStage = dstage_flushOut; - } - /* fall-through */ - - case dstage_flushOut: /* flush decoded data from tmpOut to dstBuffer */ - DEBUGLOG(6, "dstage_flushOut"); - if (dstPtr != NULL) { - size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr)); - memcpy(dstPtr, dctx->tmpOut + dctx->tmpOutStart, sizeToCopy); - - /* dictionary management */ - if (dctx->frameInfo.blockMode == LZ4F_blockLinked) - LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 1 /*withinTmp*/); - - dctx->tmpOutStart += sizeToCopy; - dstPtr += sizeToCopy; - } - if (dctx->tmpOutStart == dctx->tmpOutSize) { /* all flushed */ - dctx->dStage = dstage_getBlockHeader; /* get next block */ - break; - } - /* could not flush everything : stop there, just request a block header */ - doAnotherStage = 0; - nextSrcSizeHint = BHSize; - break; - - case dstage_getSuffix: - if (dctx->frameRemainingSize) - return err0r(LZ4F_ERROR_frameSize_wrong); /* incorrect frame size decoded */ - if (!dctx->frameInfo.contentChecksumFlag) { /* no checksum, frame is completed */ - nextSrcSizeHint = 0; - LZ4F_resetDecompressionContext(dctx); - doAnotherStage = 0; - break; - } - if ((srcEnd - srcPtr) < 4) { /* not enough size for entire CRC */ - dctx->tmpInSize = 0; - dctx->dStage = dstage_storeSuffix; - } else { - selectedIn = srcPtr; - srcPtr += 4; - } - - if (dctx->dStage == dstage_storeSuffix) /* can be skipped */ - case dstage_storeSuffix: - { size_t const remainingInput = (size_t)(srcEnd - srcPtr); - size_t const wantedData = 4 - dctx->tmpInSize; - size_t const sizeToCopy = MIN(wantedData, remainingInput); - memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy); - srcPtr += sizeToCopy; - dctx->tmpInSize += sizeToCopy; - if (dctx->tmpInSize < 4) { /* not enough input to read complete suffix */ - nextSrcSizeHint = 4 - dctx->tmpInSize; - doAnotherStage=0; - break; - } - selectedIn = dctx->tmpIn; - } /* if (dctx->dStage == dstage_storeSuffix) */ - - /* case dstage_checkSuffix: */ /* no direct entry, avoid initialization risks */ - { U32 const readCRC = LZ4F_readLE32(selectedIn); - U32 const resultCRC = XXH32_digest(&(dctx->xxh)); -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - if (readCRC != resultCRC) - return err0r(LZ4F_ERROR_contentChecksum_invalid); -#else - (void)readCRC; - (void)resultCRC; -#endif - nextSrcSizeHint = 0; - LZ4F_resetDecompressionContext(dctx); - doAnotherStage = 0; - break; - } - - case dstage_getSFrameSize: - if ((srcEnd - srcPtr) >= 4) { - selectedIn = srcPtr; - srcPtr += 4; - } else { - /* not enough input to read cBlockSize field */ - dctx->tmpInSize = 4; - dctx->tmpInTarget = 8; - dctx->dStage = dstage_storeSFrameSize; - } - - if (dctx->dStage == dstage_storeSFrameSize) - case dstage_storeSFrameSize: - { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, - (size_t)(srcEnd - srcPtr) ); - memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy); - srcPtr += sizeToCopy; - dctx->tmpInSize += sizeToCopy; - if (dctx->tmpInSize < dctx->tmpInTarget) { - /* not enough input to get full sBlockSize; wait for more */ - nextSrcSizeHint = dctx->tmpInTarget - dctx->tmpInSize; - doAnotherStage = 0; - break; - } - selectedIn = dctx->header + 4; - } /* if (dctx->dStage == dstage_storeSFrameSize) */ - - /* case dstage_decodeSFrameSize: */ /* no direct entry */ - { size_t const SFrameSize = LZ4F_readLE32(selectedIn); - dctx->frameInfo.contentSize = SFrameSize; - dctx->tmpInTarget = SFrameSize; - dctx->dStage = dstage_skipSkippable; - break; - } - - case dstage_skipSkippable: - { size_t const skipSize = MIN(dctx->tmpInTarget, (size_t)(srcEnd-srcPtr)); - srcPtr += skipSize; - dctx->tmpInTarget -= skipSize; - doAnotherStage = 0; - nextSrcSizeHint = dctx->tmpInTarget; - if (nextSrcSizeHint) break; /* still more to skip */ - /* frame fully skipped : prepare context for a new frame */ - LZ4F_resetDecompressionContext(dctx); - break; - } - } /* switch (dctx->dStage) */ - } /* while (doAnotherStage) */ - - /* preserve history within tmp whenever necessary */ - LZ4F_STATIC_ASSERT((unsigned)dstage_init == 2); - if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked) /* next block will use up to 64KB from previous ones */ - && (dctx->dict != dctx->tmpOutBuffer) /* dictionary is not already within tmp */ - && (dctx->dict != NULL) /* dictionary exists */ - && (!decompressOptionsPtr->stableDst) /* cannot rely on dst data to remain there for next call */ - && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) ) /* valid stages : [init ... getSuffix[ */ - { - if (dctx->dStage == dstage_flushOut) { - size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer); - size_t copySize = 64 KB - dctx->tmpOutSize; - const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart; - if (dctx->tmpOutSize > 64 KB) copySize = 0; - if (copySize > preserveSize) copySize = preserveSize; - assert(dctx->tmpOutBuffer != NULL); - - memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize); - - dctx->dict = dctx->tmpOutBuffer; - dctx->dictSize = preserveSize + dctx->tmpOutStart; - } else { - const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize; - size_t const newDictSize = MIN(dctx->dictSize, 64 KB); - - memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize); - - dctx->dict = dctx->tmpOutBuffer; - dctx->dictSize = newDictSize; - dctx->tmpOut = dctx->tmpOutBuffer + newDictSize; - } - } - - *srcSizePtr = (size_t)(srcPtr - srcStart); - *dstSizePtr = (size_t)(dstPtr - dstStart); - return nextSrcSizeHint; -} - -/*! LZ4F_decompress_usingDict() : - * Same as LZ4F_decompress(), using a predefined dictionary. - * Dictionary is used "in place", without any preprocessing. - * It must remain accessible throughout the entire frame decoding. - */ -size_t LZ4F_decompress_usingDict(LZ4F_dctx* dctx, - void* dstBuffer, size_t* dstSizePtr, - const void* srcBuffer, size_t* srcSizePtr, - const void* dict, size_t dictSize, - const LZ4F_decompressOptions_t* decompressOptionsPtr) -{ - if (dctx->dStage <= dstage_init) { - dctx->dict = (const BYTE*)dict; - dctx->dictSize = dictSize; - } - return LZ4F_decompress(dctx, dstBuffer, dstSizePtr, - srcBuffer, srcSizePtr, - decompressOptionsPtr); -} diff --git a/ta6ob/lz4/lib/lz4frame.h b/ta6ob/lz4/lib/lz4frame.h deleted file mode 100644 index 4573317..0000000 --- a/ta6ob/lz4/lib/lz4frame.h +++ /dev/null @@ -1,623 +0,0 @@ -/* - LZ4 auto-framing library - Header File - Copyright (C) 2011-2017, Yann Collet. - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ - -/* LZ4F is a stand-alone API able to create and decode LZ4 frames - * conformant with specification v1.6.1 in doc/lz4_Frame_format.md . - * Generated frames are compatible with `lz4` CLI. - * - * LZ4F also offers streaming capabilities. - * - * lz4.h is not required when using lz4frame.h, - * except to extract common constant such as LZ4_VERSION_NUMBER. - * */ - -#ifndef LZ4F_H_09782039843 -#define LZ4F_H_09782039843 - -#if defined (__cplusplus) -extern "C" { -#endif - -/* --- Dependency --- */ -#include /* size_t */ - - -/** - Introduction - - lz4frame.h implements LZ4 frame specification (doc/lz4_Frame_format.md). - lz4frame.h provides frame compression functions that take care - of encoding standard metadata alongside LZ4-compressed blocks. -*/ - -/*-*************************************************************** - * Compiler specifics - *****************************************************************/ -/* LZ4_DLL_EXPORT : - * Enable exporting of functions when building a Windows DLL - * LZ4FLIB_VISIBILITY : - * Control library symbols visibility. - */ -#ifndef LZ4FLIB_VISIBILITY -# if defined(__GNUC__) && (__GNUC__ >= 4) -# define LZ4FLIB_VISIBILITY __attribute__ ((visibility ("default"))) -# else -# define LZ4FLIB_VISIBILITY -# endif -#endif -#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1) -# define LZ4FLIB_API __declspec(dllexport) LZ4FLIB_VISIBILITY -#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1) -# define LZ4FLIB_API __declspec(dllimport) LZ4FLIB_VISIBILITY -#else -# define LZ4FLIB_API LZ4FLIB_VISIBILITY -#endif - -#ifdef LZ4F_DISABLE_DEPRECATE_WARNINGS -# define LZ4F_DEPRECATE(x) x -#else -# if defined(_MSC_VER) -# define LZ4F_DEPRECATE(x) x /* __declspec(deprecated) x - only works with C++ */ -# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6)) -# define LZ4F_DEPRECATE(x) x __attribute__((deprecated)) -# else -# define LZ4F_DEPRECATE(x) x /* no deprecation warning for this compiler */ -# endif -#endif - - -/*-************************************ - * Error management - **************************************/ -typedef size_t LZ4F_errorCode_t; - -LZ4FLIB_API unsigned LZ4F_isError(LZ4F_errorCode_t code); /**< tells when a function result is an error code */ -LZ4FLIB_API const char* LZ4F_getErrorName(LZ4F_errorCode_t code); /**< return error code string; for debugging */ - - -/*-************************************ - * Frame compression types - ************************************* */ -/* #define LZ4F_ENABLE_OBSOLETE_ENUMS // uncomment to enable obsolete enums */ -#ifdef LZ4F_ENABLE_OBSOLETE_ENUMS -# define LZ4F_OBSOLETE_ENUM(x) , LZ4F_DEPRECATE(x) = LZ4F_##x -#else -# define LZ4F_OBSOLETE_ENUM(x) -#endif - -/* The larger the block size, the (slightly) better the compression ratio, - * though there are diminishing returns. - * Larger blocks also increase memory usage on both compression and decompression sides. - */ -typedef enum { - LZ4F_default=0, - LZ4F_max64KB=4, - LZ4F_max256KB=5, - LZ4F_max1MB=6, - LZ4F_max4MB=7 - LZ4F_OBSOLETE_ENUM(max64KB) - LZ4F_OBSOLETE_ENUM(max256KB) - LZ4F_OBSOLETE_ENUM(max1MB) - LZ4F_OBSOLETE_ENUM(max4MB) -} LZ4F_blockSizeID_t; - -/* Linked blocks sharply reduce inefficiencies when using small blocks, - * they compress better. - * However, some LZ4 decoders are only compatible with independent blocks */ -typedef enum { - LZ4F_blockLinked=0, - LZ4F_blockIndependent - LZ4F_OBSOLETE_ENUM(blockLinked) - LZ4F_OBSOLETE_ENUM(blockIndependent) -} LZ4F_blockMode_t; - -typedef enum { - LZ4F_noContentChecksum=0, - LZ4F_contentChecksumEnabled - LZ4F_OBSOLETE_ENUM(noContentChecksum) - LZ4F_OBSOLETE_ENUM(contentChecksumEnabled) -} LZ4F_contentChecksum_t; - -typedef enum { - LZ4F_noBlockChecksum=0, - LZ4F_blockChecksumEnabled -} LZ4F_blockChecksum_t; - -typedef enum { - LZ4F_frame=0, - LZ4F_skippableFrame - LZ4F_OBSOLETE_ENUM(skippableFrame) -} LZ4F_frameType_t; - -#ifdef LZ4F_ENABLE_OBSOLETE_ENUMS -typedef LZ4F_blockSizeID_t blockSizeID_t; -typedef LZ4F_blockMode_t blockMode_t; -typedef LZ4F_frameType_t frameType_t; -typedef LZ4F_contentChecksum_t contentChecksum_t; -#endif - -/*! LZ4F_frameInfo_t : - * makes it possible to set or read frame parameters. - * Structure must be first init to 0, using memset() or LZ4F_INIT_FRAMEINFO, - * setting all parameters to default. - * It's then possible to update selectively some parameters */ -typedef struct { - LZ4F_blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB; 0 == default */ - LZ4F_blockMode_t blockMode; /* LZ4F_blockLinked, LZ4F_blockIndependent; 0 == default */ - LZ4F_contentChecksum_t contentChecksumFlag; /* 1: frame terminated with 32-bit checksum of decompressed data; 0: disabled (default) */ - LZ4F_frameType_t frameType; /* read-only field : LZ4F_frame or LZ4F_skippableFrame */ - unsigned long long contentSize; /* Size of uncompressed content ; 0 == unknown */ - unsigned dictID; /* Dictionary ID, sent by compressor to help decoder select correct dictionary; 0 == no dictID provided */ - LZ4F_blockChecksum_t blockChecksumFlag; /* 1: each block followed by a checksum of block's compressed data; 0: disabled (default) */ -} LZ4F_frameInfo_t; - -#define LZ4F_INIT_FRAMEINFO { LZ4F_default, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame, 0ULL, 0U, LZ4F_noBlockChecksum } /* v1.8.3+ */ - -/*! LZ4F_preferences_t : - * makes it possible to supply advanced compression instructions to streaming interface. - * Structure must be first init to 0, using memset() or LZ4F_INIT_PREFERENCES, - * setting all parameters to default. - * All reserved fields must be set to zero. */ -typedef struct { - LZ4F_frameInfo_t frameInfo; - int compressionLevel; /* 0: default (fast mode); values > LZ4HC_CLEVEL_MAX count as LZ4HC_CLEVEL_MAX; values < 0 trigger "fast acceleration" */ - unsigned autoFlush; /* 1: always flush; reduces usage of internal buffers */ - unsigned favorDecSpeed; /* 1: parser favors decompression speed vs compression ratio. Only works for high compression modes (>= LZ4HC_CLEVEL_OPT_MIN) */ /* v1.8.2+ */ - unsigned reserved[3]; /* must be zero for forward compatibility */ -} LZ4F_preferences_t; - -#define LZ4F_INIT_PREFERENCES { LZ4F_INIT_FRAMEINFO, 0, 0u, 0u, { 0u, 0u, 0u } } /* v1.8.3+ */ - - -/*-********************************* -* Simple compression function -***********************************/ - -LZ4FLIB_API int LZ4F_compressionLevel_max(void); /* v1.8.0+ */ - -/*! LZ4F_compressFrameBound() : - * Returns the maximum possible compressed size with LZ4F_compressFrame() given srcSize and preferences. - * `preferencesPtr` is optional. It can be replaced by NULL, in which case, the function will assume default preferences. - * Note : this result is only usable with LZ4F_compressFrame(). - * It may also be used with LZ4F_compressUpdate() _if no flush() operation_ is performed. - */ -LZ4FLIB_API size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr); - -/*! LZ4F_compressFrame() : - * Compress an entire srcBuffer into a valid LZ4 frame. - * dstCapacity MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). - * The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default. - * @return : number of bytes written into dstBuffer. - * or an error code if it fails (can be tested using LZ4F_isError()) - */ -LZ4FLIB_API size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity, - const void* srcBuffer, size_t srcSize, - const LZ4F_preferences_t* preferencesPtr); - - -/*-*********************************** -* Advanced compression functions -*************************************/ -typedef struct LZ4F_cctx_s LZ4F_cctx; /* incomplete type */ -typedef LZ4F_cctx* LZ4F_compressionContext_t; /* for compatibility with previous API version */ - -typedef struct { - unsigned stableSrc; /* 1 == src content will remain present on future calls to LZ4F_compress(); skip copying src content within tmp buffer */ - unsigned reserved[3]; -} LZ4F_compressOptions_t; - -/*--- Resource Management ---*/ - -#define LZ4F_VERSION 100 /* This number can be used to check for an incompatible API breaking change */ -LZ4FLIB_API unsigned LZ4F_getVersion(void); - -/*! LZ4F_createCompressionContext() : - * The first thing to do is to create a compressionContext object, which will be used in all compression operations. - * This is achieved using LZ4F_createCompressionContext(), which takes as argument a version. - * The version provided MUST be LZ4F_VERSION. It is intended to track potential version mismatch, notably when using DLL. - * The function will provide a pointer to a fully allocated LZ4F_cctx object. - * If @return != zero, there was an error during context creation. - * Object can release its memory using LZ4F_freeCompressionContext(); - */ -LZ4FLIB_API LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** cctxPtr, unsigned version); -LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctx); - - -/*---- Compression ----*/ - -#define LZ4F_HEADER_SIZE_MIN 7 /* LZ4 Frame header size can vary, depending on selected paramaters */ -#define LZ4F_HEADER_SIZE_MAX 19 - -/* Size in bytes of a block header in little-endian format. Highest bit indicates if block data is uncompressed */ -#define LZ4F_BLOCK_HEADER_SIZE 4 - -/* Size in bytes of a block checksum footer in little-endian format. */ -#define LZ4F_BLOCK_CHECKSUM_SIZE 4 - -/* Size in bytes of the content checksum. */ -#define LZ4F_CONTENT_CHECKSUM_SIZE 4 - -/*! LZ4F_compressBegin() : - * will write the frame header into dstBuffer. - * dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. - * `prefsPtr` is optional : you can provide NULL as argument, all preferences will then be set to default. - * @return : number of bytes written into dstBuffer for the header - * or an error code (which can be tested using LZ4F_isError()) - */ -LZ4FLIB_API size_t LZ4F_compressBegin(LZ4F_cctx* cctx, - void* dstBuffer, size_t dstCapacity, - const LZ4F_preferences_t* prefsPtr); - -/*! LZ4F_compressBound() : - * Provides minimum dstCapacity required to guarantee success of - * LZ4F_compressUpdate(), given a srcSize and preferences, for a worst case scenario. - * When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() instead. - * Note that the result is only valid for a single invocation of LZ4F_compressUpdate(). - * When invoking LZ4F_compressUpdate() multiple times, - * if the output buffer is gradually filled up instead of emptied and re-used from its start, - * one must check if there is enough remaining capacity before each invocation, using LZ4F_compressBound(). - * @return is always the same for a srcSize and prefsPtr. - * prefsPtr is optional : when NULL is provided, preferences will be set to cover worst case scenario. - * tech details : - * @return if automatic flushing is not enabled, includes the possibility that internal buffer might already be filled by up to (blockSize-1) bytes. - * It also includes frame footer (ending + checksum), since it might be generated by LZ4F_compressEnd(). - * @return doesn't include frame header, as it was already generated by LZ4F_compressBegin(). - */ -LZ4FLIB_API size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* prefsPtr); - -/*! LZ4F_compressUpdate() : - * LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary. - * Important rule: dstCapacity MUST be large enough to ensure operation success even in worst case situations. - * This value is provided by LZ4F_compressBound(). - * If this condition is not respected, LZ4F_compress() will fail (result is an errorCode). - * LZ4F_compressUpdate() doesn't guarantee error recovery. - * When an error occurs, compression context must be freed or resized. - * `cOptPtr` is optional : NULL can be provided, in which case all options are set to default. - * @return : number of bytes written into `dstBuffer` (it can be zero, meaning input data was just buffered). - * or an error code if it fails (which can be tested using LZ4F_isError()) - */ -LZ4FLIB_API size_t LZ4F_compressUpdate(LZ4F_cctx* cctx, - void* dstBuffer, size_t dstCapacity, - const void* srcBuffer, size_t srcSize, - const LZ4F_compressOptions_t* cOptPtr); - -/*! LZ4F_flush() : - * When data must be generated and sent immediately, without waiting for a block to be completely filled, - * it's possible to call LZ4_flush(). It will immediately compress any data buffered within cctx. - * `dstCapacity` must be large enough to ensure the operation will be successful. - * `cOptPtr` is optional : it's possible to provide NULL, all options will be set to default. - * @return : nb of bytes written into dstBuffer (can be zero, when there is no data stored within cctx) - * or an error code if it fails (which can be tested using LZ4F_isError()) - * Note : LZ4F_flush() is guaranteed to be successful when dstCapacity >= LZ4F_compressBound(0, prefsPtr). - */ -LZ4FLIB_API size_t LZ4F_flush(LZ4F_cctx* cctx, - void* dstBuffer, size_t dstCapacity, - const LZ4F_compressOptions_t* cOptPtr); - -/*! LZ4F_compressEnd() : - * To properly finish an LZ4 frame, invoke LZ4F_compressEnd(). - * It will flush whatever data remained within `cctx` (like LZ4_flush()) - * and properly finalize the frame, with an endMark and a checksum. - * `cOptPtr` is optional : NULL can be provided, in which case all options will be set to default. - * @return : nb of bytes written into dstBuffer, necessarily >= 4 (endMark), - * or an error code if it fails (which can be tested using LZ4F_isError()) - * Note : LZ4F_compressEnd() is guaranteed to be successful when dstCapacity >= LZ4F_compressBound(0, prefsPtr). - * A successful call to LZ4F_compressEnd() makes `cctx` available again for another compression task. - */ -LZ4FLIB_API size_t LZ4F_compressEnd(LZ4F_cctx* cctx, - void* dstBuffer, size_t dstCapacity, - const LZ4F_compressOptions_t* cOptPtr); - - -/*-********************************* -* Decompression functions -***********************************/ -typedef struct LZ4F_dctx_s LZ4F_dctx; /* incomplete type */ -typedef LZ4F_dctx* LZ4F_decompressionContext_t; /* compatibility with previous API versions */ - -typedef struct { - unsigned stableDst; /* pledges that last 64KB decompressed data will remain available unmodified. This optimization skips storage operations in tmp buffers. */ - unsigned reserved[3]; /* must be set to zero for forward compatibility */ -} LZ4F_decompressOptions_t; - - -/* Resource management */ - -/*! LZ4F_createDecompressionContext() : - * Create an LZ4F_dctx object, to track all decompression operations. - * The version provided MUST be LZ4F_VERSION. - * The function provides a pointer to an allocated and initialized LZ4F_dctx object. - * The result is an errorCode, which can be tested using LZ4F_isError(). - * dctx memory can be released using LZ4F_freeDecompressionContext(); - * Result of LZ4F_freeDecompressionContext() indicates current state of decompressionContext when being released. - * That is, it should be == 0 if decompression has been completed fully and correctly. - */ -LZ4FLIB_API LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** dctxPtr, unsigned version); -LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx); - - -/*-*********************************** -* Streaming decompression functions -*************************************/ - -#define LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH 5 - -/*! LZ4F_headerSize() : v1.9.0+ - * Provide the header size of a frame starting at `src`. - * `srcSize` must be >= LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH, - * which is enough to decode the header length. - * @return : size of frame header - * or an error code, which can be tested using LZ4F_isError() - * note : Frame header size is variable, but is guaranteed to be - * >= LZ4F_HEADER_SIZE_MIN bytes, and <= LZ4F_HEADER_SIZE_MAX bytes. - */ -LZ4FLIB_API size_t LZ4F_headerSize(const void* src, size_t srcSize); - -/*! LZ4F_getFrameInfo() : - * This function extracts frame parameters (max blockSize, dictID, etc.). - * Its usage is optional: user can call LZ4F_decompress() directly. - * - * Extracted information will fill an existing LZ4F_frameInfo_t structure. - * This can be useful for allocation and dictionary identification purposes. - * - * LZ4F_getFrameInfo() can work in the following situations : - * - * 1) At the beginning of a new frame, before any invocation of LZ4F_decompress(). - * It will decode header from `srcBuffer`, - * consuming the header and starting the decoding process. - * - * Input size must be large enough to contain the full frame header. - * Frame header size can be known beforehand by LZ4F_headerSize(). - * Frame header size is variable, but is guaranteed to be >= LZ4F_HEADER_SIZE_MIN bytes, - * and not more than <= LZ4F_HEADER_SIZE_MAX bytes. - * Hence, blindly providing LZ4F_HEADER_SIZE_MAX bytes or more will always work. - * It's allowed to provide more input data than the header size, - * LZ4F_getFrameInfo() will only consume the header. - * - * If input size is not large enough, - * aka if it's smaller than header size, - * function will fail and return an error code. - * - * 2) After decoding has been started, - * it's possible to invoke LZ4F_getFrameInfo() anytime - * to extract already decoded frame parameters stored within dctx. - * - * Note that, if decoding has barely started, - * and not yet read enough information to decode the header, - * LZ4F_getFrameInfo() will fail. - * - * The number of bytes consumed from srcBuffer will be updated in *srcSizePtr (necessarily <= original value). - * LZ4F_getFrameInfo() only consumes bytes when decoding has not yet started, - * and when decoding the header has been successful. - * Decompression must then resume from (srcBuffer + *srcSizePtr). - * - * @return : a hint about how many srcSize bytes LZ4F_decompress() expects for next call, - * or an error code which can be tested using LZ4F_isError(). - * note 1 : in case of error, dctx is not modified. Decoding operation can resume from beginning safely. - * note 2 : frame parameters are *copied into* an already allocated LZ4F_frameInfo_t structure. - */ -LZ4FLIB_API size_t LZ4F_getFrameInfo(LZ4F_dctx* dctx, - LZ4F_frameInfo_t* frameInfoPtr, - const void* srcBuffer, size_t* srcSizePtr); - -/*! LZ4F_decompress() : - * Call this function repetitively to regenerate data compressed in `srcBuffer`. - * - * The function requires a valid dctx state. - * It will read up to *srcSizePtr bytes from srcBuffer, - * and decompress data into dstBuffer, of capacity *dstSizePtr. - * - * The nb of bytes consumed from srcBuffer will be written into *srcSizePtr (necessarily <= original value). - * The nb of bytes decompressed into dstBuffer will be written into *dstSizePtr (necessarily <= original value). - * - * The function does not necessarily read all input bytes, so always check value in *srcSizePtr. - * Unconsumed source data must be presented again in subsequent invocations. - * - * `dstBuffer` can freely change between each consecutive function invocation. - * `dstBuffer` content will be overwritten. - * - * @return : an hint of how many `srcSize` bytes LZ4F_decompress() expects for next call. - * Schematically, it's the size of the current (or remaining) compressed block + header of next block. - * Respecting the hint provides some small speed benefit, because it skips intermediate buffers. - * This is just a hint though, it's always possible to provide any srcSize. - * - * When a frame is fully decoded, @return will be 0 (no more data expected). - * When provided with more bytes than necessary to decode a frame, - * LZ4F_decompress() will stop reading exactly at end of current frame, and @return 0. - * - * If decompression failed, @return is an error code, which can be tested using LZ4F_isError(). - * After a decompression error, the `dctx` context is not resumable. - * Use LZ4F_resetDecompressionContext() to return to clean state. - * - * After a frame is fully decoded, dctx can be used again to decompress another frame. - */ -LZ4FLIB_API size_t LZ4F_decompress(LZ4F_dctx* dctx, - void* dstBuffer, size_t* dstSizePtr, - const void* srcBuffer, size_t* srcSizePtr, - const LZ4F_decompressOptions_t* dOptPtr); - - -/*! LZ4F_resetDecompressionContext() : added in v1.8.0 - * In case of an error, the context is left in "undefined" state. - * In which case, it's necessary to reset it, before re-using it. - * This method can also be used to abruptly stop any unfinished decompression, - * and start a new one using same context resources. */ -LZ4FLIB_API void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx); /* always successful */ - - - -#if defined (__cplusplus) -} -#endif - -#endif /* LZ4F_H_09782039843 */ - -#if defined(LZ4F_STATIC_LINKING_ONLY) && !defined(LZ4F_H_STATIC_09782039843) -#define LZ4F_H_STATIC_09782039843 - -#if defined (__cplusplus) -extern "C" { -#endif - -/* These declarations are not stable and may change in the future. - * They are therefore only safe to depend on - * when the caller is statically linked against the library. - * To access their declarations, define LZ4F_STATIC_LINKING_ONLY. - * - * By default, these symbols aren't published into shared/dynamic libraries. - * You can override this behavior and force them to be published - * by defining LZ4F_PUBLISH_STATIC_FUNCTIONS. - * Use at your own risk. - */ -#ifdef LZ4F_PUBLISH_STATIC_FUNCTIONS -# define LZ4FLIB_STATIC_API LZ4FLIB_API -#else -# define LZ4FLIB_STATIC_API -#endif - - -/* --- Error List --- */ -#define LZ4F_LIST_ERRORS(ITEM) \ - ITEM(OK_NoError) \ - ITEM(ERROR_GENERIC) \ - ITEM(ERROR_maxBlockSize_invalid) \ - ITEM(ERROR_blockMode_invalid) \ - ITEM(ERROR_contentChecksumFlag_invalid) \ - ITEM(ERROR_compressionLevel_invalid) \ - ITEM(ERROR_headerVersion_wrong) \ - ITEM(ERROR_blockChecksum_invalid) \ - ITEM(ERROR_reservedFlag_set) \ - ITEM(ERROR_allocation_failed) \ - ITEM(ERROR_srcSize_tooLarge) \ - ITEM(ERROR_dstMaxSize_tooSmall) \ - ITEM(ERROR_frameHeader_incomplete) \ - ITEM(ERROR_frameType_unknown) \ - ITEM(ERROR_frameSize_wrong) \ - ITEM(ERROR_srcPtr_wrong) \ - ITEM(ERROR_decompressionFailed) \ - ITEM(ERROR_headerChecksum_invalid) \ - ITEM(ERROR_contentChecksum_invalid) \ - ITEM(ERROR_frameDecoding_alreadyStarted) \ - ITEM(ERROR_maxCode) - -#define LZ4F_GENERATE_ENUM(ENUM) LZ4F_##ENUM, - -/* enum list is exposed, to handle specific errors */ -typedef enum { LZ4F_LIST_ERRORS(LZ4F_GENERATE_ENUM) - _LZ4F_dummy_error_enum_for_c89_never_used } LZ4F_errorCodes; - -LZ4FLIB_STATIC_API LZ4F_errorCodes LZ4F_getErrorCode(size_t functionResult); - -LZ4FLIB_STATIC_API size_t LZ4F_getBlockSize(unsigned); - -/********************************** - * Bulk processing dictionary API - *********************************/ - -/* A Dictionary is useful for the compression of small messages (KB range). - * It dramatically improves compression efficiency. - * - * LZ4 can ingest any input as dictionary, though only the last 64 KB are useful. - * Best results are generally achieved by using Zstandard's Dictionary Builder - * to generate a high-quality dictionary from a set of samples. - * - * Loading a dictionary has a cost, since it involves construction of tables. - * The Bulk processing dictionary API makes it possible to share this cost - * over an arbitrary number of compression jobs, even concurrently, - * markedly improving compression latency for these cases. - * - * The same dictionary will have to be used on the decompression side - * for decoding to be successful. - * To help identify the correct dictionary at decoding stage, - * the frame header allows optional embedding of a dictID field. - */ -typedef struct LZ4F_CDict_s LZ4F_CDict; - -/*! LZ4_createCDict() : - * When compressing multiple messages / blocks using the same dictionary, it's recommended to load it just once. - * LZ4_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay. - * LZ4_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only. - * `dictBuffer` can be released after LZ4_CDict creation, since its content is copied within CDict */ -LZ4FLIB_STATIC_API LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize); -LZ4FLIB_STATIC_API void LZ4F_freeCDict(LZ4F_CDict* CDict); - - -/*! LZ4_compressFrame_usingCDict() : - * Compress an entire srcBuffer into a valid LZ4 frame using a digested Dictionary. - * cctx must point to a context created by LZ4F_createCompressionContext(). - * If cdict==NULL, compress without a dictionary. - * dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr). - * If this condition is not respected, function will fail (@return an errorCode). - * The LZ4F_preferences_t structure is optional : you may provide NULL as argument, - * but it's not recommended, as it's the only way to provide dictID in the frame header. - * @return : number of bytes written into dstBuffer. - * or an error code if it fails (can be tested using LZ4F_isError()) */ -LZ4FLIB_STATIC_API size_t LZ4F_compressFrame_usingCDict( - LZ4F_cctx* cctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const LZ4F_CDict* cdict, - const LZ4F_preferences_t* preferencesPtr); - - -/*! LZ4F_compressBegin_usingCDict() : - * Inits streaming dictionary compression, and writes the frame header into dstBuffer. - * dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes. - * `prefsPtr` is optional : you may provide NULL as argument, - * however, it's the only way to provide dictID in the frame header. - * @return : number of bytes written into dstBuffer for the header, - * or an error code (which can be tested using LZ4F_isError()) */ -LZ4FLIB_STATIC_API size_t LZ4F_compressBegin_usingCDict( - LZ4F_cctx* cctx, - void* dstBuffer, size_t dstCapacity, - const LZ4F_CDict* cdict, - const LZ4F_preferences_t* prefsPtr); - - -/*! LZ4F_decompress_usingDict() : - * Same as LZ4F_decompress(), using a predefined dictionary. - * Dictionary is used "in place", without any preprocessing. - * It must remain accessible throughout the entire frame decoding. */ -LZ4FLIB_STATIC_API size_t LZ4F_decompress_usingDict( - LZ4F_dctx* dctxPtr, - void* dstBuffer, size_t* dstSizePtr, - const void* srcBuffer, size_t* srcSizePtr, - const void* dict, size_t dictSize, - const LZ4F_decompressOptions_t* decompressOptionsPtr); - -#if defined (__cplusplus) -} -#endif - -#endif /* defined(LZ4F_STATIC_LINKING_ONLY) && !defined(LZ4F_H_STATIC_09782039843) */ diff --git a/ta6ob/lz4/lib/lz4frame_static.h b/ta6ob/lz4/lib/lz4frame_static.h deleted file mode 100644 index 925a2c5..0000000 --- a/ta6ob/lz4/lib/lz4frame_static.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - LZ4 auto-framing library - Header File for static linking only - Copyright (C) 2011-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ - -#ifndef LZ4FRAME_STATIC_H_0398209384 -#define LZ4FRAME_STATIC_H_0398209384 - -/* The declarations that formerly were made here have been merged into - * lz4frame.h, protected by the LZ4F_STATIC_LINKING_ONLY macro. Going forward, - * it is recommended to simply include that header directly. - */ - -#define LZ4F_STATIC_LINKING_ONLY -#include "lz4frame.h" - -#endif /* LZ4FRAME_STATIC_H_0398209384 */ diff --git a/ta6ob/lz4/lib/lz4hc.c b/ta6ob/lz4/lib/lz4hc.c deleted file mode 100644 index 77c9f43..0000000 --- a/ta6ob/lz4/lib/lz4hc.c +++ /dev/null @@ -1,1615 +0,0 @@ -/* - LZ4 HC - High Compression Mode of LZ4 - Copyright (C) 2011-2017, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ -/* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */ - - -/* ************************************* -* Tuning Parameter -***************************************/ - -/*! HEAPMODE : - * Select how default compression function will allocate workplace memory, - * in stack (0:fastest), or in heap (1:requires malloc()). - * Since workplace is rather large, heap mode is recommended. - */ -#ifndef LZ4HC_HEAPMODE -# define LZ4HC_HEAPMODE 1 -#endif - - -/*=== Dependency ===*/ -#define LZ4_HC_STATIC_LINKING_ONLY -#include "lz4hc.h" - - -/*=== Common definitions ===*/ -#if defined(__GNUC__) -# pragma GCC diagnostic ignored "-Wunused-function" -#endif -#if defined (__clang__) -# pragma clang diagnostic ignored "-Wunused-function" -#endif - -#define LZ4_COMMONDEFS_ONLY -#ifndef LZ4_SRC_INCLUDED -#include "lz4.c" /* LZ4_count, constants, mem */ -#endif - - -/*=== Enums ===*/ -typedef enum { noDictCtx, usingDictCtxHc } dictCtx_directive; - - -/*=== Constants ===*/ -#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH) -#define LZ4_OPT_NUM (1<<12) - - -/*=== Macros ===*/ -#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) -#define MAX(a,b) ( (a) > (b) ? (a) : (b) ) -#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG)) -#define DELTANEXTMAXD(p) chainTable[(p) & LZ4HC_MAXD_MASK] /* flexible, LZ4HC_MAXD dependent */ -#define DELTANEXTU16(table, pos) table[(U16)(pos)] /* faster */ -/* Make fields passed to, and updated by LZ4HC_encodeSequence explicit */ -#define UPDATABLE(ip, op, anchor) &ip, &op, &anchor - -static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); } - - -/************************************** -* HC Compression -**************************************/ -static void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4) -{ - MEM_INIT(hc4->hashTable, 0, sizeof(hc4->hashTable)); - MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable)); -} - -static void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start) -{ - uptrval startingOffset = (uptrval)(hc4->end - hc4->base); - if (startingOffset > 1 GB) { - LZ4HC_clearTables(hc4); - startingOffset = 0; - } - startingOffset += 64 KB; - hc4->nextToUpdate = (U32) startingOffset; - hc4->base = start - startingOffset; - hc4->end = start; - hc4->dictBase = start - startingOffset; - hc4->dictLimit = (U32) startingOffset; - hc4->lowLimit = (U32) startingOffset; -} - - -/* Update chains up to ip (excluded) */ -LZ4_FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip) -{ - U16* const chainTable = hc4->chainTable; - U32* const hashTable = hc4->hashTable; - const BYTE* const base = hc4->base; - U32 const target = (U32)(ip - base); - U32 idx = hc4->nextToUpdate; - - while (idx < target) { - U32 const h = LZ4HC_hashPtr(base+idx); - size_t delta = idx - hashTable[h]; - if (delta>LZ4_DISTANCE_MAX) delta = LZ4_DISTANCE_MAX; - DELTANEXTU16(chainTable, idx) = (U16)delta; - hashTable[h] = idx; - idx++; - } - - hc4->nextToUpdate = target; -} - -/** LZ4HC_countBack() : - * @return : negative value, nb of common bytes before ip/match */ -LZ4_FORCE_INLINE -int LZ4HC_countBack(const BYTE* const ip, const BYTE* const match, - const BYTE* const iMin, const BYTE* const mMin) -{ - int back = 0; - int const min = (int)MAX(iMin - ip, mMin - match); - assert(min <= 0); - assert(ip >= iMin); assert((size_t)(ip-iMin) < (1U<<31)); - assert(match >= mMin); assert((size_t)(match - mMin) < (1U<<31)); - while ( (back > min) - && (ip[back-1] == match[back-1]) ) - back--; - return back; -} - -#if defined(_MSC_VER) -# define LZ4HC_rotl32(x,r) _rotl(x,r) -#else -# define LZ4HC_rotl32(x,r) ((x << r) | (x >> (32 - r))) -#endif - - -static U32 LZ4HC_rotatePattern(size_t const rotate, U32 const pattern) -{ - size_t const bitsToRotate = (rotate & (sizeof(pattern) - 1)) << 3; - if (bitsToRotate == 0) return pattern; - return LZ4HC_rotl32(pattern, (int)bitsToRotate); -} - -/* LZ4HC_countPattern() : - * pattern32 must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!) */ -static unsigned -LZ4HC_countPattern(const BYTE* ip, const BYTE* const iEnd, U32 const pattern32) -{ - const BYTE* const iStart = ip; - reg_t const pattern = (sizeof(pattern)==8) ? - (reg_t)pattern32 + (((reg_t)pattern32) << (sizeof(pattern)*4)) : pattern32; - - while (likely(ip < iEnd-(sizeof(pattern)-1))) { - reg_t const diff = LZ4_read_ARCH(ip) ^ pattern; - if (!diff) { ip+=sizeof(pattern); continue; } - ip += LZ4_NbCommonBytes(diff); - return (unsigned)(ip - iStart); - } - - if (LZ4_isLittleEndian()) { - reg_t patternByte = pattern; - while ((ip>= 8; - } - } else { /* big endian */ - U32 bitOffset = (sizeof(pattern)*8) - 8; - while (ip < iEnd) { - BYTE const byte = (BYTE)(pattern >> bitOffset); - if (*ip != byte) break; - ip ++; bitOffset -= 8; - } - } - - return (unsigned)(ip - iStart); -} - -/* LZ4HC_reverseCountPattern() : - * pattern must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!) - * read using natural platform endianess */ -static unsigned -LZ4HC_reverseCountPattern(const BYTE* ip, const BYTE* const iLow, U32 pattern) -{ - const BYTE* const iStart = ip; - - while (likely(ip >= iLow+4)) { - if (LZ4_read32(ip-4) != pattern) break; - ip -= 4; - } - { const BYTE* bytePtr = (const BYTE*)(&pattern) + 3; /* works for any endianess */ - while (likely(ip>iLow)) { - if (ip[-1] != *bytePtr) break; - ip--; bytePtr--; - } } - return (unsigned)(iStart - ip); -} - -/* LZ4HC_protectDictEnd() : - * Checks if the match is in the last 3 bytes of the dictionary, so reading the - * 4 byte MINMATCH would overflow. - * @returns true if the match index is okay. - */ -static int LZ4HC_protectDictEnd(U32 const dictLimit, U32 const matchIndex) -{ - return ((U32)((dictLimit - 1) - matchIndex) >= 3); -} - -typedef enum { rep_untested, rep_not, rep_confirmed } repeat_state_e; -typedef enum { favorCompressionRatio=0, favorDecompressionSpeed } HCfavor_e; - -LZ4_FORCE_INLINE int -LZ4HC_InsertAndGetWiderMatch ( - LZ4HC_CCtx_internal* hc4, - const BYTE* const ip, - const BYTE* const iLowLimit, - const BYTE* const iHighLimit, - int longest, - const BYTE** matchpos, - const BYTE** startpos, - const int maxNbAttempts, - const int patternAnalysis, - const int chainSwap, - const dictCtx_directive dict, - const HCfavor_e favorDecSpeed) -{ - U16* const chainTable = hc4->chainTable; - U32* const HashTable = hc4->hashTable; - const LZ4HC_CCtx_internal * const dictCtx = hc4->dictCtx; - const BYTE* const base = hc4->base; - const U32 dictLimit = hc4->dictLimit; - const BYTE* const lowPrefixPtr = base + dictLimit; - const U32 ipIndex = (U32)(ip - base); - const U32 lowestMatchIndex = (hc4->lowLimit + (LZ4_DISTANCE_MAX + 1) > ipIndex) ? hc4->lowLimit : ipIndex - LZ4_DISTANCE_MAX; - const BYTE* const dictBase = hc4->dictBase; - int const lookBackLength = (int)(ip-iLowLimit); - int nbAttempts = maxNbAttempts; - U32 matchChainPos = 0; - U32 const pattern = LZ4_read32(ip); - U32 matchIndex; - repeat_state_e repeat = rep_untested; - size_t srcPatternLength = 0; - - DEBUGLOG(7, "LZ4HC_InsertAndGetWiderMatch"); - /* First Match */ - LZ4HC_Insert(hc4, ip); - matchIndex = HashTable[LZ4HC_hashPtr(ip)]; - DEBUGLOG(7, "First match at index %u / %u (lowestMatchIndex)", - matchIndex, lowestMatchIndex); - - while ((matchIndex>=lowestMatchIndex) && (nbAttempts>0)) { - int matchLength=0; - nbAttempts--; - assert(matchIndex < ipIndex); - if (favorDecSpeed && (ipIndex - matchIndex < 8)) { - /* do nothing */ - } else if (matchIndex >= dictLimit) { /* within current Prefix */ - const BYTE* const matchPtr = base + matchIndex; - assert(matchPtr >= lowPrefixPtr); - assert(matchPtr < ip); - assert(longest >= 1); - if (LZ4_read16(iLowLimit + longest - 1) == LZ4_read16(matchPtr - lookBackLength + longest - 1)) { - if (LZ4_read32(matchPtr) == pattern) { - int const back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, lowPrefixPtr) : 0; - matchLength = MINMATCH + (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit); - matchLength -= back; - if (matchLength > longest) { - longest = matchLength; - *matchpos = matchPtr + back; - *startpos = ip + back; - } } } - } else { /* lowestMatchIndex <= matchIndex < dictLimit */ - const BYTE* const matchPtr = dictBase + matchIndex; - if (LZ4_read32(matchPtr) == pattern) { - const BYTE* const dictStart = dictBase + hc4->lowLimit; - int back = 0; - const BYTE* vLimit = ip + (dictLimit - matchIndex); - if (vLimit > iHighLimit) vLimit = iHighLimit; - matchLength = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; - if ((ip+matchLength == vLimit) && (vLimit < iHighLimit)) - matchLength += LZ4_count(ip+matchLength, lowPrefixPtr, iHighLimit); - back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictStart) : 0; - matchLength -= back; - if (matchLength > longest) { - longest = matchLength; - *matchpos = base + matchIndex + back; /* virtual pos, relative to ip, to retrieve offset */ - *startpos = ip + back; - } } } - - if (chainSwap && matchLength==longest) { /* better match => select a better chain */ - assert(lookBackLength==0); /* search forward only */ - if (matchIndex + (U32)longest <= ipIndex) { - int const kTrigger = 4; - U32 distanceToNextMatch = 1; - int const end = longest - MINMATCH + 1; - int step = 1; - int accel = 1 << kTrigger; - int pos; - for (pos = 0; pos < end; pos += step) { - U32 const candidateDist = DELTANEXTU16(chainTable, matchIndex + (U32)pos); - step = (accel++ >> kTrigger); - if (candidateDist > distanceToNextMatch) { - distanceToNextMatch = candidateDist; - matchChainPos = (U32)pos; - accel = 1 << kTrigger; - } - } - if (distanceToNextMatch > 1) { - if (distanceToNextMatch > matchIndex) break; /* avoid overflow */ - matchIndex -= distanceToNextMatch; - continue; - } } } - - { U32 const distNextMatch = DELTANEXTU16(chainTable, matchIndex); - if (patternAnalysis && distNextMatch==1 && matchChainPos==0) { - U32 const matchCandidateIdx = matchIndex-1; - /* may be a repeated pattern */ - if (repeat == rep_untested) { - if ( ((pattern & 0xFFFF) == (pattern >> 16)) - & ((pattern & 0xFF) == (pattern >> 24)) ) { - repeat = rep_confirmed; - srcPatternLength = LZ4HC_countPattern(ip+sizeof(pattern), iHighLimit, pattern) + sizeof(pattern); - } else { - repeat = rep_not; - } } - if ( (repeat == rep_confirmed) && (matchCandidateIdx >= lowestMatchIndex) - && LZ4HC_protectDictEnd(dictLimit, matchCandidateIdx) ) { - const int extDict = matchCandidateIdx < dictLimit; - const BYTE* const matchPtr = (extDict ? dictBase : base) + matchCandidateIdx; - if (LZ4_read32(matchPtr) == pattern) { /* good candidate */ - const BYTE* const dictStart = dictBase + hc4->lowLimit; - const BYTE* const iLimit = extDict ? dictBase + dictLimit : iHighLimit; - size_t forwardPatternLength = LZ4HC_countPattern(matchPtr+sizeof(pattern), iLimit, pattern) + sizeof(pattern); - if (extDict && matchPtr + forwardPatternLength == iLimit) { - U32 const rotatedPattern = LZ4HC_rotatePattern(forwardPatternLength, pattern); - forwardPatternLength += LZ4HC_countPattern(lowPrefixPtr, iHighLimit, rotatedPattern); - } - { const BYTE* const lowestMatchPtr = extDict ? dictStart : lowPrefixPtr; - size_t backLength = LZ4HC_reverseCountPattern(matchPtr, lowestMatchPtr, pattern); - size_t currentSegmentLength; - if (!extDict && matchPtr - backLength == lowPrefixPtr && hc4->lowLimit < dictLimit) { - U32 const rotatedPattern = LZ4HC_rotatePattern((U32)(-(int)backLength), pattern); - backLength += LZ4HC_reverseCountPattern(dictBase + dictLimit, dictStart, rotatedPattern); - } - /* Limit backLength not go further than lowestMatchIndex */ - backLength = matchCandidateIdx - MAX(matchCandidateIdx - (U32)backLength, lowestMatchIndex); - assert(matchCandidateIdx - backLength >= lowestMatchIndex); - currentSegmentLength = backLength + forwardPatternLength; - /* Adjust to end of pattern if the source pattern fits, otherwise the beginning of the pattern */ - if ( (currentSegmentLength >= srcPatternLength) /* current pattern segment large enough to contain full srcPatternLength */ - && (forwardPatternLength <= srcPatternLength) ) { /* haven't reached this position yet */ - U32 const newMatchIndex = matchCandidateIdx + (U32)forwardPatternLength - (U32)srcPatternLength; /* best position, full pattern, might be followed by more match */ - if (LZ4HC_protectDictEnd(dictLimit, newMatchIndex)) - matchIndex = newMatchIndex; - else { - /* Can only happen if started in the prefix */ - assert(newMatchIndex >= dictLimit - 3 && newMatchIndex < dictLimit && !extDict); - matchIndex = dictLimit; - } - } else { - U32 const newMatchIndex = matchCandidateIdx - (U32)backLength; /* farthest position in current segment, will find a match of length currentSegmentLength + maybe some back */ - if (!LZ4HC_protectDictEnd(dictLimit, newMatchIndex)) { - assert(newMatchIndex >= dictLimit - 3 && newMatchIndex < dictLimit && !extDict); - matchIndex = dictLimit; - } else { - matchIndex = newMatchIndex; - if (lookBackLength==0) { /* no back possible */ - size_t const maxML = MIN(currentSegmentLength, srcPatternLength); - if ((size_t)longest < maxML) { - assert(base + matchIndex != ip); - if ((size_t)(ip - base) - matchIndex > LZ4_DISTANCE_MAX) break; - assert(maxML < 2 GB); - longest = (int)maxML; - *matchpos = base + matchIndex; /* virtual pos, relative to ip, to retrieve offset */ - *startpos = ip; - } - { U32 const distToNextPattern = DELTANEXTU16(chainTable, matchIndex); - if (distToNextPattern > matchIndex) break; /* avoid overflow */ - matchIndex -= distToNextPattern; - } } } } } - continue; - } } - } } /* PA optimization */ - - /* follow current chain */ - matchIndex -= DELTANEXTU16(chainTable, matchIndex + matchChainPos); - - } /* while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) */ - - if ( dict == usingDictCtxHc - && nbAttempts > 0 - && ipIndex - lowestMatchIndex < LZ4_DISTANCE_MAX) { - size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->base); - U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)]; - assert(dictEndOffset <= 1 GB); - matchIndex = dictMatchIndex + lowestMatchIndex - (U32)dictEndOffset; - while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) { - const BYTE* const matchPtr = dictCtx->base + dictMatchIndex; - - if (LZ4_read32(matchPtr) == pattern) { - int mlt; - int back = 0; - const BYTE* vLimit = ip + (dictEndOffset - dictMatchIndex); - if (vLimit > iHighLimit) vLimit = iHighLimit; - mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH; - back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->base + dictCtx->dictLimit) : 0; - mlt -= back; - if (mlt > longest) { - longest = mlt; - *matchpos = base + matchIndex + back; - *startpos = ip + back; - } } - - { U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, dictMatchIndex); - dictMatchIndex -= nextOffset; - matchIndex -= nextOffset; - } } } - - return longest; -} - -LZ4_FORCE_INLINE -int LZ4HC_InsertAndFindBestMatch(LZ4HC_CCtx_internal* const hc4, /* Index table will be updated */ - const BYTE* const ip, const BYTE* const iLimit, - const BYTE** matchpos, - const int maxNbAttempts, - const int patternAnalysis, - const dictCtx_directive dict) -{ - const BYTE* uselessPtr = ip; - /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos), - * but this won't be the case here, as we define iLowLimit==ip, - * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */ - return LZ4HC_InsertAndGetWiderMatch(hc4, ip, ip, iLimit, MINMATCH-1, matchpos, &uselessPtr, maxNbAttempts, patternAnalysis, 0 /*chainSwap*/, dict, favorCompressionRatio); -} - -/* LZ4HC_encodeSequence() : - * @return : 0 if ok, - * 1 if buffer issue detected */ -LZ4_FORCE_INLINE int LZ4HC_encodeSequence ( - const BYTE** _ip, - BYTE** _op, - const BYTE** _anchor, - int matchLength, - const BYTE* const match, - limitedOutput_directive limit, - BYTE* oend) -{ -#define ip (*_ip) -#define op (*_op) -#define anchor (*_anchor) - - size_t length; - BYTE* const token = op++; - -#if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6) - static const BYTE* start = NULL; - static U32 totalCost = 0; - U32 const pos = (start==NULL) ? 0 : (U32)(anchor - start); - U32 const ll = (U32)(ip - anchor); - U32 const llAdd = (ll>=15) ? ((ll-15) / 255) + 1 : 0; - U32 const mlAdd = (matchLength>=19) ? ((matchLength-19) / 255) + 1 : 0; - U32 const cost = 1 + llAdd + ll + 2 + mlAdd; - if (start==NULL) start = anchor; /* only works for single segment */ - /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */ - DEBUGLOG(6, "pos:%7u -- literals:%4u, match:%4i, offset:%5u, cost:%4u + %5u", - pos, - (U32)(ip - anchor), matchLength, (U32)(ip-match), - cost, totalCost); - totalCost += cost; -#endif - - /* Encode Literal length */ - length = (size_t)(ip - anchor); - LZ4_STATIC_ASSERT(notLimited == 0); - /* Check output limit */ - if (limit && ((op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) { - DEBUGLOG(6, "Not enough room to write %i literals (%i bytes remaining)", - (int)length, (int)(oend - op)); - return 1; - } - if (length >= RUN_MASK) { - size_t len = length - RUN_MASK; - *token = (RUN_MASK << ML_BITS); - for(; len >= 255 ; len -= 255) *op++ = 255; - *op++ = (BYTE)len; - } else { - *token = (BYTE)(length << ML_BITS); - } - - /* Copy Literals */ - LZ4_wildCopy8(op, anchor, op + length); - op += length; - - /* Encode Offset */ - assert( (ip - match) <= LZ4_DISTANCE_MAX ); /* note : consider providing offset as a value, rather than as a pointer difference */ - LZ4_writeLE16(op, (U16)(ip - match)); op += 2; - - /* Encode MatchLength */ - assert(matchLength >= MINMATCH); - length = (size_t)matchLength - MINMATCH; - if (limit && (op + (length / 255) + (1 + LASTLITERALS) > oend)) { - DEBUGLOG(6, "Not enough room to write match length"); - return 1; /* Check output limit */ - } - if (length >= ML_MASK) { - *token += ML_MASK; - length -= ML_MASK; - for(; length >= 510 ; length -= 510) { *op++ = 255; *op++ = 255; } - if (length >= 255) { length -= 255; *op++ = 255; } - *op++ = (BYTE)length; - } else { - *token += (BYTE)(length); - } - - /* Prepare next loop */ - ip += matchLength; - anchor = ip; - - return 0; -} -#undef ip -#undef op -#undef anchor - -LZ4_FORCE_INLINE int LZ4HC_compress_hashChain ( - LZ4HC_CCtx_internal* const ctx, - const char* const source, - char* const dest, - int* srcSizePtr, - int const maxOutputSize, - int maxNbAttempts, - const limitedOutput_directive limit, - const dictCtx_directive dict - ) -{ - const int inputSize = *srcSizePtr; - const int patternAnalysis = (maxNbAttempts > 128); /* levels 9+ */ - - const BYTE* ip = (const BYTE*) source; - const BYTE* anchor = ip; - const BYTE* const iend = ip + inputSize; - const BYTE* const mflimit = iend - MFLIMIT; - const BYTE* const matchlimit = (iend - LASTLITERALS); - - BYTE* optr = (BYTE*) dest; - BYTE* op = (BYTE*) dest; - BYTE* oend = op + maxOutputSize; - - int ml0, ml, ml2, ml3; - const BYTE* start0; - const BYTE* ref0; - const BYTE* ref = NULL; - const BYTE* start2 = NULL; - const BYTE* ref2 = NULL; - const BYTE* start3 = NULL; - const BYTE* ref3 = NULL; - - /* init */ - *srcSizePtr = 0; - if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */ - if (inputSize < LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ - - /* Main Loop */ - while (ip <= mflimit) { - ml = LZ4HC_InsertAndFindBestMatch(ctx, ip, matchlimit, &ref, maxNbAttempts, patternAnalysis, dict); - if (ml encode ML1 */ - optr = op; - if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; - continue; - } - - if (start0 < ip) { /* first match was skipped at least once */ - if (start2 < ip + ml0) { /* squeezing ML1 between ML0(original ML1) and ML2 */ - ip = start0; ref = ref0; ml = ml0; /* restore initial ML1 */ - } } - - /* Here, start0==ip */ - if ((start2 - ip) < 3) { /* First Match too small : removed */ - ml = ml2; - ip = start2; - ref =ref2; - goto _Search2; - } - -_Search3: - /* At this stage, we have : - * ml2 > ml1, and - * ip1+3 <= ip2 (usually < ip1+ml1) */ - if ((start2 - ip) < OPTIMAL_ML) { - int correction; - int new_ml = ml; - if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML; - if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH; - correction = new_ml - (int)(start2 - ip); - if (correction > 0) { - start2 += correction; - ref2 += correction; - ml2 -= correction; - } - } - /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */ - - if (start2 + ml2 <= mflimit) { - ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, - start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, - maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio); - } else { - ml3 = ml2; - } - - if (ml3 == ml2) { /* No better match => encode ML1 and ML2 */ - /* ip & ref are known; Now for ml */ - if (start2 < ip+ml) ml = (int)(start2 - ip); - /* Now, encode 2 sequences */ - optr = op; - if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; - ip = start2; - optr = op; - if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml2, ref2, limit, oend)) { - ml = ml2; - ref = ref2; - goto _dest_overflow; - } - continue; - } - - if (start3 < ip+ml+3) { /* Not enough space for match 2 : remove it */ - if (start3 >= (ip+ml)) { /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */ - if (start2 < ip+ml) { - int correction = (int)(ip+ml - start2); - start2 += correction; - ref2 += correction; - ml2 -= correction; - if (ml2 < MINMATCH) { - start2 = start3; - ref2 = ref3; - ml2 = ml3; - } - } - - optr = op; - if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; - ip = start3; - ref = ref3; - ml = ml3; - - start0 = start2; - ref0 = ref2; - ml0 = ml2; - goto _Search2; - } - - start2 = start3; - ref2 = ref3; - ml2 = ml3; - goto _Search3; - } - - /* - * OK, now we have 3 ascending matches; - * let's write the first one ML1. - * ip & ref are known; Now decide ml. - */ - if (start2 < ip+ml) { - if ((start2 - ip) < OPTIMAL_ML) { - int correction; - if (ml > OPTIMAL_ML) ml = OPTIMAL_ML; - if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH; - correction = ml - (int)(start2 - ip); - if (correction > 0) { - start2 += correction; - ref2 += correction; - ml2 -= correction; - } - } else { - ml = (int)(start2 - ip); - } - } - optr = op; - if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, limit, oend)) goto _dest_overflow; - - /* ML2 becomes ML1 */ - ip = start2; ref = ref2; ml = ml2; - - /* ML3 becomes ML2 */ - start2 = start3; ref2 = ref3; ml2 = ml3; - - /* let's find a new ML3 */ - goto _Search3; - } - -_last_literals: - /* Encode Last Literals */ - { size_t lastRunSize = (size_t)(iend - anchor); /* literals */ - size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255; - size_t const totalSize = 1 + llAdd + lastRunSize; - if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */ - if (limit && (op + totalSize > oend)) { - if (limit == limitedOutput) return 0; - /* adapt lastRunSize to fill 'dest' */ - lastRunSize = (size_t)(oend - op) - 1 /*token*/; - llAdd = (lastRunSize + 256 - RUN_MASK) / 256; - lastRunSize -= llAdd; - } - DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize); - ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */ - - if (lastRunSize >= RUN_MASK) { - size_t accumulator = lastRunSize - RUN_MASK; - *op++ = (RUN_MASK << ML_BITS); - for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255; - *op++ = (BYTE) accumulator; - } else { - *op++ = (BYTE)(lastRunSize << ML_BITS); - } - memcpy(op, anchor, lastRunSize); - op += lastRunSize; - } - - /* End */ - *srcSizePtr = (int) (((const char*)ip) - source); - return (int) (((char*)op)-dest); - -_dest_overflow: - if (limit == fillOutput) { - /* Assumption : ip, anchor, ml and ref must be set correctly */ - size_t const ll = (size_t)(ip - anchor); - size_t const ll_addbytes = (ll + 240) / 255; - size_t const ll_totalCost = 1 + ll_addbytes + ll; - BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */ - DEBUGLOG(6, "Last sequence overflowing"); - op = optr; /* restore correct out pointer */ - if (op + ll_totalCost <= maxLitPos) { - /* ll validated; now adjust match length */ - size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost)); - size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255); - assert(maxMlSize < INT_MAX); assert(ml >= 0); - if ((size_t)ml > maxMlSize) ml = (int)maxMlSize; - if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ml >= MFLIMIT) { - LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ref, notLimited, oend); - } } - goto _last_literals; - } - /* compression failed */ - return 0; -} - - -static int LZ4HC_compress_optimal( LZ4HC_CCtx_internal* ctx, - const char* const source, char* dst, - int* srcSizePtr, int dstCapacity, - int const nbSearches, size_t sufficient_len, - const limitedOutput_directive limit, int const fullUpdate, - const dictCtx_directive dict, - const HCfavor_e favorDecSpeed); - - -LZ4_FORCE_INLINE int LZ4HC_compress_generic_internal ( - LZ4HC_CCtx_internal* const ctx, - const char* const src, - char* const dst, - int* const srcSizePtr, - int const dstCapacity, - int cLevel, - const limitedOutput_directive limit, - const dictCtx_directive dict - ) -{ - typedef enum { lz4hc, lz4opt } lz4hc_strat_e; - typedef struct { - lz4hc_strat_e strat; - int nbSearches; - U32 targetLength; - } cParams_t; - static const cParams_t clTable[LZ4HC_CLEVEL_MAX+1] = { - { lz4hc, 2, 16 }, /* 0, unused */ - { lz4hc, 2, 16 }, /* 1, unused */ - { lz4hc, 2, 16 }, /* 2, unused */ - { lz4hc, 4, 16 }, /* 3 */ - { lz4hc, 8, 16 }, /* 4 */ - { lz4hc, 16, 16 }, /* 5 */ - { lz4hc, 32, 16 }, /* 6 */ - { lz4hc, 64, 16 }, /* 7 */ - { lz4hc, 128, 16 }, /* 8 */ - { lz4hc, 256, 16 }, /* 9 */ - { lz4opt, 96, 64 }, /*10==LZ4HC_CLEVEL_OPT_MIN*/ - { lz4opt, 512,128 }, /*11 */ - { lz4opt,16384,LZ4_OPT_NUM }, /* 12==LZ4HC_CLEVEL_MAX */ - }; - - DEBUGLOG(4, "LZ4HC_compress_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)", - ctx, src, *srcSizePtr, limit); - - if (limit == fillOutput && dstCapacity < 1) return 0; /* Impossible to store anything */ - if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size (too large or negative) */ - - ctx->end += *srcSizePtr; - if (cLevel < 1) cLevel = LZ4HC_CLEVEL_DEFAULT; /* note : convention is different from lz4frame, maybe something to review */ - cLevel = MIN(LZ4HC_CLEVEL_MAX, cLevel); - { cParams_t const cParam = clTable[cLevel]; - HCfavor_e const favor = ctx->favorDecSpeed ? favorDecompressionSpeed : favorCompressionRatio; - int result; - - if (cParam.strat == lz4hc) { - result = LZ4HC_compress_hashChain(ctx, - src, dst, srcSizePtr, dstCapacity, - cParam.nbSearches, limit, dict); - } else { - assert(cParam.strat == lz4opt); - result = LZ4HC_compress_optimal(ctx, - src, dst, srcSizePtr, dstCapacity, - cParam.nbSearches, cParam.targetLength, limit, - cLevel == LZ4HC_CLEVEL_MAX, /* ultra mode */ - dict, favor); - } - if (result <= 0) ctx->dirty = 1; - return result; - } -} - -static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock); - -static int -LZ4HC_compress_generic_noDictCtx ( - LZ4HC_CCtx_internal* const ctx, - const char* const src, - char* const dst, - int* const srcSizePtr, - int const dstCapacity, - int cLevel, - limitedOutput_directive limit - ) -{ - assert(ctx->dictCtx == NULL); - return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, noDictCtx); -} - -static int -LZ4HC_compress_generic_dictCtx ( - LZ4HC_CCtx_internal* const ctx, - const char* const src, - char* const dst, - int* const srcSizePtr, - int const dstCapacity, - int cLevel, - limitedOutput_directive limit - ) -{ - const size_t position = (size_t)(ctx->end - ctx->base) - ctx->lowLimit; - assert(ctx->dictCtx != NULL); - if (position >= 64 KB) { - ctx->dictCtx = NULL; - return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); - } else if (position == 0 && *srcSizePtr > 4 KB) { - memcpy(ctx, ctx->dictCtx, sizeof(LZ4HC_CCtx_internal)); - LZ4HC_setExternalDict(ctx, (const BYTE *)src); - ctx->compressionLevel = (short)cLevel; - return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); - } else { - return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, usingDictCtxHc); - } -} - -static int -LZ4HC_compress_generic ( - LZ4HC_CCtx_internal* const ctx, - const char* const src, - char* const dst, - int* const srcSizePtr, - int const dstCapacity, - int cLevel, - limitedOutput_directive limit - ) -{ - if (ctx->dictCtx == NULL) { - return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); - } else { - return LZ4HC_compress_generic_dictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit); - } -} - - -int LZ4_sizeofStateHC(void) { return (int)sizeof(LZ4_streamHC_t); } - -static size_t LZ4_streamHC_t_alignment(void) -{ -#if LZ4_ALIGN_TEST - typedef struct { char c; LZ4_streamHC_t t; } t_a; - return sizeof(t_a) - sizeof(LZ4_streamHC_t); -#else - return 1; /* effectively disabled */ -#endif -} - -/* state is presumed correctly initialized, - * in which case its size and alignment have already been validate */ -int LZ4_compress_HC_extStateHC_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) -{ - LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)state)->internal_donotuse; - if (!LZ4_isAligned(state, LZ4_streamHC_t_alignment())) return 0; - LZ4_resetStreamHC_fast((LZ4_streamHC_t*)state, compressionLevel); - LZ4HC_init_internal (ctx, (const BYTE*)src); - if (dstCapacity < LZ4_compressBound(srcSize)) - return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, limitedOutput); - else - return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, notLimited); -} - -int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) -{ - LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx)); - if (ctx==NULL) return 0; /* init failure */ - return LZ4_compress_HC_extStateHC_fastReset(state, src, dst, srcSize, dstCapacity, compressionLevel); -} - -int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel) -{ -#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 - LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t)); -#else - LZ4_streamHC_t state; - LZ4_streamHC_t* const statePtr = &state; -#endif - int const cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, dstCapacity, compressionLevel); -#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1 - FREEMEM(statePtr); -#endif - return cSize; -} - -/* state is presumed sized correctly (>= sizeof(LZ4_streamHC_t)) */ -int LZ4_compress_HC_destSize(void* state, const char* source, char* dest, int* sourceSizePtr, int targetDestSize, int cLevel) -{ - LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx)); - if (ctx==NULL) return 0; /* init failure */ - LZ4HC_init_internal(&ctx->internal_donotuse, (const BYTE*) source); - LZ4_setCompressionLevel(ctx, cLevel); - return LZ4HC_compress_generic(&ctx->internal_donotuse, source, dest, sourceSizePtr, targetDestSize, cLevel, fillOutput); -} - - - -/************************************** -* Streaming Functions -**************************************/ -/* allocation */ -LZ4_streamHC_t* LZ4_createStreamHC(void) -{ - LZ4_streamHC_t* const state = - (LZ4_streamHC_t*)ALLOC_AND_ZERO(sizeof(LZ4_streamHC_t)); - if (state == NULL) return NULL; - LZ4_setCompressionLevel(state, LZ4HC_CLEVEL_DEFAULT); - return state; -} - -int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) -{ - DEBUGLOG(4, "LZ4_freeStreamHC(%p)", LZ4_streamHCPtr); - if (!LZ4_streamHCPtr) return 0; /* support free on NULL */ - FREEMEM(LZ4_streamHCPtr); - return 0; -} - - -LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size) -{ - LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)buffer; - /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */ - LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= LZ4_STREAMHCSIZE); - DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", buffer, (unsigned)size); - /* check conditions */ - if (buffer == NULL) return NULL; - if (size < sizeof(LZ4_streamHC_t)) return NULL; - if (!LZ4_isAligned(buffer, LZ4_streamHC_t_alignment())) return NULL; - /* init */ - { LZ4HC_CCtx_internal* const hcstate = &(LZ4_streamHCPtr->internal_donotuse); - MEM_INIT(hcstate, 0, sizeof(*hcstate)); } - LZ4_setCompressionLevel(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT); - return LZ4_streamHCPtr; -} - -/* just a stub */ -void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) -{ - LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); - LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); -} - -void LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) -{ - DEBUGLOG(4, "LZ4_resetStreamHC_fast(%p, %d)", LZ4_streamHCPtr, compressionLevel); - if (LZ4_streamHCPtr->internal_donotuse.dirty) { - LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); - } else { - /* preserve end - base : can trigger clearTable's threshold */ - LZ4_streamHCPtr->internal_donotuse.end -= (uptrval)LZ4_streamHCPtr->internal_donotuse.base; - LZ4_streamHCPtr->internal_donotuse.base = NULL; - LZ4_streamHCPtr->internal_donotuse.dictCtx = NULL; - } - LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel); -} - -void LZ4_setCompressionLevel(LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel) -{ - DEBUGLOG(5, "LZ4_setCompressionLevel(%p, %d)", LZ4_streamHCPtr, compressionLevel); - if (compressionLevel < 1) compressionLevel = LZ4HC_CLEVEL_DEFAULT; - if (compressionLevel > LZ4HC_CLEVEL_MAX) compressionLevel = LZ4HC_CLEVEL_MAX; - LZ4_streamHCPtr->internal_donotuse.compressionLevel = (short)compressionLevel; -} - -void LZ4_favorDecompressionSpeed(LZ4_streamHC_t* LZ4_streamHCPtr, int favor) -{ - LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = (favor!=0); -} - -/* LZ4_loadDictHC() : - * LZ4_streamHCPtr is presumed properly initialized */ -int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, - const char* dictionary, int dictSize) -{ - LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse; - DEBUGLOG(4, "LZ4_loadDictHC(ctx:%p, dict:%p, dictSize:%d)", LZ4_streamHCPtr, dictionary, dictSize); - assert(LZ4_streamHCPtr != NULL); - if (dictSize > 64 KB) { - dictionary += (size_t)dictSize - 64 KB; - dictSize = 64 KB; - } - /* need a full initialization, there are bad side-effects when using resetFast() */ - { int const cLevel = ctxPtr->compressionLevel; - LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr)); - LZ4_setCompressionLevel(LZ4_streamHCPtr, cLevel); - } - LZ4HC_init_internal (ctxPtr, (const BYTE*)dictionary); - ctxPtr->end = (const BYTE*)dictionary + dictSize; - if (dictSize >= 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); - return dictSize; -} - -void LZ4_attach_HC_dictionary(LZ4_streamHC_t *working_stream, const LZ4_streamHC_t *dictionary_stream) { - working_stream->internal_donotuse.dictCtx = dictionary_stream != NULL ? &(dictionary_stream->internal_donotuse) : NULL; -} - -/* compression */ - -static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock) -{ - DEBUGLOG(4, "LZ4HC_setExternalDict(%p, %p)", ctxPtr, newBlock); - if (ctxPtr->end >= ctxPtr->base + ctxPtr->dictLimit + 4) - LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */ - - /* Only one memory segment for extDict, so any previous extDict is lost at this stage */ - ctxPtr->lowLimit = ctxPtr->dictLimit; - ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base); - ctxPtr->dictBase = ctxPtr->base; - ctxPtr->base = newBlock - ctxPtr->dictLimit; - ctxPtr->end = newBlock; - ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */ - - /* cannot reference an extDict and a dictCtx at the same time */ - ctxPtr->dictCtx = NULL; -} - -static int -LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr, - const char* src, char* dst, - int* srcSizePtr, int dstCapacity, - limitedOutput_directive limit) -{ - LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse; - DEBUGLOG(5, "LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)", - LZ4_streamHCPtr, src, *srcSizePtr, limit); - assert(ctxPtr != NULL); - /* auto-init if forgotten */ - if (ctxPtr->base == NULL) LZ4HC_init_internal (ctxPtr, (const BYTE*) src); - - /* Check overflow */ - if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) { - size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit; - if (dictSize > 64 KB) dictSize = 64 KB; - LZ4_loadDictHC(LZ4_streamHCPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize); - } - - /* Check if blocks follow each other */ - if ((const BYTE*)src != ctxPtr->end) - LZ4HC_setExternalDict(ctxPtr, (const BYTE*)src); - - /* Check overlapping input/dictionary space */ - { const BYTE* sourceEnd = (const BYTE*) src + *srcSizePtr; - const BYTE* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit; - const BYTE* const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit; - if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd)) { - if (sourceEnd > dictEnd) sourceEnd = dictEnd; - ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase); - if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit; - } } - - return LZ4HC_compress_generic (ctxPtr, src, dst, srcSizePtr, dstCapacity, ctxPtr->compressionLevel, limit); -} - -int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int srcSize, int dstCapacity) -{ - if (dstCapacity < LZ4_compressBound(srcSize)) - return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, limitedOutput); - else - return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, notLimited); -} - -int LZ4_compress_HC_continue_destSize (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int* srcSizePtr, int targetDestSize) -{ - return LZ4_compressHC_continue_generic(LZ4_streamHCPtr, src, dst, srcSizePtr, targetDestSize, fillOutput); -} - - - -/* LZ4_saveDictHC : - * save history content - * into a user-provided buffer - * which is then used to continue compression - */ -int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize) -{ - LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse; - int const prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit)); - DEBUGLOG(5, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize); - assert(prefixSize >= 0); - if (dictSize > 64 KB) dictSize = 64 KB; - if (dictSize < 4) dictSize = 0; - if (dictSize > prefixSize) dictSize = prefixSize; - if (safeBuffer == NULL) assert(dictSize == 0); - if (dictSize > 0) - memmove(safeBuffer, streamPtr->end - dictSize, dictSize); - { U32 const endIndex = (U32)(streamPtr->end - streamPtr->base); - streamPtr->end = (const BYTE*)safeBuffer + dictSize; - streamPtr->base = streamPtr->end - endIndex; - streamPtr->dictLimit = endIndex - (U32)dictSize; - streamPtr->lowLimit = endIndex - (U32)dictSize; - if (streamPtr->nextToUpdate < streamPtr->dictLimit) - streamPtr->nextToUpdate = streamPtr->dictLimit; - } - return dictSize; -} - - -/*************************************************** -* Deprecated Functions -***************************************************/ - -/* These functions currently generate deprecation warnings */ - -/* Wrappers for deprecated compression functions */ -int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); } -int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); } -int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); } -int LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); } -int LZ4_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, LZ4_compressBound(srcSize), 0); } -int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); } -int LZ4_compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); } -int LZ4_compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); } -int LZ4_compressHC_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, LZ4_compressBound(srcSize)); } -int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); } - - -/* Deprecated streaming functions */ -int LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; } - -/* state is presumed correctly sized, aka >= sizeof(LZ4_streamHC_t) - * @return : 0 on success, !=0 if error */ -int LZ4_resetStreamStateHC(void* state, char* inputBuffer) -{ - LZ4_streamHC_t* const hc4 = LZ4_initStreamHC(state, sizeof(*hc4)); - if (hc4 == NULL) return 1; /* init failed */ - LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer); - return 0; -} - -void* LZ4_createHC (const char* inputBuffer) -{ - LZ4_streamHC_t* const hc4 = LZ4_createStreamHC(); - if (hc4 == NULL) return NULL; /* not enough memory */ - LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer); - return hc4; -} - -int LZ4_freeHC (void* LZ4HC_Data) -{ - if (!LZ4HC_Data) return 0; /* support free on NULL */ - FREEMEM(LZ4HC_Data); - return 0; -} - -int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int cLevel) -{ - return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, 0, cLevel, notLimited); -} - -int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int dstCapacity, int cLevel) -{ - return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, dstCapacity, cLevel, limitedOutput); -} - -char* LZ4_slideInputBufferHC(void* LZ4HC_Data) -{ - LZ4_streamHC_t *ctx = (LZ4_streamHC_t*)LZ4HC_Data; - const BYTE *bufferStart = ctx->internal_donotuse.base + ctx->internal_donotuse.lowLimit; - LZ4_resetStreamHC_fast(ctx, ctx->internal_donotuse.compressionLevel); - /* avoid const char * -> char * conversion warning :( */ - return (char *)(uptrval)bufferStart; -} - - -/* ================================================ - * LZ4 Optimal parser (levels [LZ4HC_CLEVEL_OPT_MIN - LZ4HC_CLEVEL_MAX]) - * ===============================================*/ -typedef struct { - int price; - int off; - int mlen; - int litlen; -} LZ4HC_optimal_t; - -/* price in bytes */ -LZ4_FORCE_INLINE int LZ4HC_literalsPrice(int const litlen) -{ - int price = litlen; - assert(litlen >= 0); - if (litlen >= (int)RUN_MASK) - price += 1 + ((litlen-(int)RUN_MASK) / 255); - return price; -} - - -/* requires mlen >= MINMATCH */ -LZ4_FORCE_INLINE int LZ4HC_sequencePrice(int litlen, int mlen) -{ - int price = 1 + 2 ; /* token + 16-bit offset */ - assert(litlen >= 0); - assert(mlen >= MINMATCH); - - price += LZ4HC_literalsPrice(litlen); - - if (mlen >= (int)(ML_MASK+MINMATCH)) - price += 1 + ((mlen-(int)(ML_MASK+MINMATCH)) / 255); - - return price; -} - - -typedef struct { - int off; - int len; -} LZ4HC_match_t; - -LZ4_FORCE_INLINE LZ4HC_match_t -LZ4HC_FindLongerMatch(LZ4HC_CCtx_internal* const ctx, - const BYTE* ip, const BYTE* const iHighLimit, - int minLen, int nbSearches, - const dictCtx_directive dict, - const HCfavor_e favorDecSpeed) -{ - LZ4HC_match_t match = { 0 , 0 }; - const BYTE* matchPtr = NULL; - /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos), - * but this won't be the case here, as we define iLowLimit==ip, - * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */ - int matchLength = LZ4HC_InsertAndGetWiderMatch(ctx, ip, ip, iHighLimit, minLen, &matchPtr, &ip, nbSearches, 1 /*patternAnalysis*/, 1 /*chainSwap*/, dict, favorDecSpeed); - if (matchLength <= minLen) return match; - if (favorDecSpeed) { - if ((matchLength>18) & (matchLength<=36)) matchLength=18; /* favor shortcut */ - } - match.len = matchLength; - match.off = (int)(ip-matchPtr); - return match; -} - - -static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx, - const char* const source, - char* dst, - int* srcSizePtr, - int dstCapacity, - int const nbSearches, - size_t sufficient_len, - const limitedOutput_directive limit, - int const fullUpdate, - const dictCtx_directive dict, - const HCfavor_e favorDecSpeed) -{ - int retval = 0; -#define TRAILING_LITERALS 3 -#ifdef LZ4HC_HEAPMODE - LZ4HC_optimal_t* const opt = (LZ4HC_optimal_t*)ALLOC(sizeof(LZ4HC_optimal_t) * (LZ4_OPT_NUM + TRAILING_LITERALS)); -#else - LZ4HC_optimal_t opt[LZ4_OPT_NUM + TRAILING_LITERALS]; /* ~64 KB, which is a bit large for stack... */ -#endif - - const BYTE* ip = (const BYTE*) source; - const BYTE* anchor = ip; - const BYTE* const iend = ip + *srcSizePtr; - const BYTE* const mflimit = iend - MFLIMIT; - const BYTE* const matchlimit = iend - LASTLITERALS; - BYTE* op = (BYTE*) dst; - BYTE* opSaved = (BYTE*) dst; - BYTE* oend = op + dstCapacity; - int ovml = MINMATCH; /* overflow - last sequence */ - const BYTE* ovref = NULL; - - /* init */ -#ifdef LZ4HC_HEAPMODE - if (opt == NULL) goto _return_label; -#endif - DEBUGLOG(5, "LZ4HC_compress_optimal(dst=%p, dstCapa=%u)", dst, (unsigned)dstCapacity); - *srcSizePtr = 0; - if (limit == fillOutput) oend -= LASTLITERALS; /* Hack for support LZ4 format restriction */ - if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM-1; - - /* Main Loop */ - while (ip <= mflimit) { - int const llen = (int)(ip - anchor); - int best_mlen, best_off; - int cur, last_match_pos = 0; - - LZ4HC_match_t const firstMatch = LZ4HC_FindLongerMatch(ctx, ip, matchlimit, MINMATCH-1, nbSearches, dict, favorDecSpeed); - if (firstMatch.len==0) { ip++; continue; } - - if ((size_t)firstMatch.len > sufficient_len) { - /* good enough solution : immediate encoding */ - int const firstML = firstMatch.len; - const BYTE* const matchPos = ip - firstMatch.off; - opSaved = op; - if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, matchPos, limit, oend) ) { /* updates ip, op and anchor */ - ovml = firstML; - ovref = matchPos; - goto _dest_overflow; - } - continue; - } - - /* set prices for first positions (literals) */ - { int rPos; - for (rPos = 0 ; rPos < MINMATCH ; rPos++) { - int const cost = LZ4HC_literalsPrice(llen + rPos); - opt[rPos].mlen = 1; - opt[rPos].off = 0; - opt[rPos].litlen = llen + rPos; - opt[rPos].price = cost; - DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i) -- initial setup", - rPos, cost, opt[rPos].litlen); - } } - /* set prices using initial match */ - { int mlen = MINMATCH; - int const matchML = firstMatch.len; /* necessarily < sufficient_len < LZ4_OPT_NUM */ - int const offset = firstMatch.off; - assert(matchML < LZ4_OPT_NUM); - for ( ; mlen <= matchML ; mlen++) { - int const cost = LZ4HC_sequencePrice(llen, mlen); - opt[mlen].mlen = mlen; - opt[mlen].off = offset; - opt[mlen].litlen = llen; - opt[mlen].price = cost; - DEBUGLOG(7, "rPos:%3i => price:%3i (matchlen=%i) -- initial setup", - mlen, cost, mlen); - } } - last_match_pos = firstMatch.len; - { int addLit; - for (addLit = 1; addLit <= TRAILING_LITERALS; addLit ++) { - opt[last_match_pos+addLit].mlen = 1; /* literal */ - opt[last_match_pos+addLit].off = 0; - opt[last_match_pos+addLit].litlen = addLit; - opt[last_match_pos+addLit].price = opt[last_match_pos].price + LZ4HC_literalsPrice(addLit); - DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i) -- initial setup", - last_match_pos+addLit, opt[last_match_pos+addLit].price, addLit); - } } - - /* check further positions */ - for (cur = 1; cur < last_match_pos; cur++) { - const BYTE* const curPtr = ip + cur; - LZ4HC_match_t newMatch; - - if (curPtr > mflimit) break; - DEBUGLOG(7, "rPos:%u[%u] vs [%u]%u", - cur, opt[cur].price, opt[cur+1].price, cur+1); - if (fullUpdate) { - /* not useful to search here if next position has same (or lower) cost */ - if ( (opt[cur+1].price <= opt[cur].price) - /* in some cases, next position has same cost, but cost rises sharply after, so a small match would still be beneficial */ - && (opt[cur+MINMATCH].price < opt[cur].price + 3/*min seq price*/) ) - continue; - } else { - /* not useful to search here if next position has same (or lower) cost */ - if (opt[cur+1].price <= opt[cur].price) continue; - } - - DEBUGLOG(7, "search at rPos:%u", cur); - if (fullUpdate) - newMatch = LZ4HC_FindLongerMatch(ctx, curPtr, matchlimit, MINMATCH-1, nbSearches, dict, favorDecSpeed); - else - /* only test matches of minimum length; slightly faster, but misses a few bytes */ - newMatch = LZ4HC_FindLongerMatch(ctx, curPtr, matchlimit, last_match_pos - cur, nbSearches, dict, favorDecSpeed); - if (!newMatch.len) continue; - - if ( ((size_t)newMatch.len > sufficient_len) - || (newMatch.len + cur >= LZ4_OPT_NUM) ) { - /* immediate encoding */ - best_mlen = newMatch.len; - best_off = newMatch.off; - last_match_pos = cur + 1; - goto encode; - } - - /* before match : set price with literals at beginning */ - { int const baseLitlen = opt[cur].litlen; - int litlen; - for (litlen = 1; litlen < MINMATCH; litlen++) { - int const price = opt[cur].price - LZ4HC_literalsPrice(baseLitlen) + LZ4HC_literalsPrice(baseLitlen+litlen); - int const pos = cur + litlen; - if (price < opt[pos].price) { - opt[pos].mlen = 1; /* literal */ - opt[pos].off = 0; - opt[pos].litlen = baseLitlen+litlen; - opt[pos].price = price; - DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i)", - pos, price, opt[pos].litlen); - } } } - - /* set prices using match at position = cur */ - { int const matchML = newMatch.len; - int ml = MINMATCH; - - assert(cur + newMatch.len < LZ4_OPT_NUM); - for ( ; ml <= matchML ; ml++) { - int const pos = cur + ml; - int const offset = newMatch.off; - int price; - int ll; - DEBUGLOG(7, "testing price rPos %i (last_match_pos=%i)", - pos, last_match_pos); - if (opt[cur].mlen == 1) { - ll = opt[cur].litlen; - price = ((cur > ll) ? opt[cur - ll].price : 0) - + LZ4HC_sequencePrice(ll, ml); - } else { - ll = 0; - price = opt[cur].price + LZ4HC_sequencePrice(0, ml); - } - - assert((U32)favorDecSpeed <= 1); - if (pos > last_match_pos+TRAILING_LITERALS - || price <= opt[pos].price - (int)favorDecSpeed) { - DEBUGLOG(7, "rPos:%3i => price:%3i (matchlen=%i)", - pos, price, ml); - assert(pos < LZ4_OPT_NUM); - if ( (ml == matchML) /* last pos of last match */ - && (last_match_pos < pos) ) - last_match_pos = pos; - opt[pos].mlen = ml; - opt[pos].off = offset; - opt[pos].litlen = ll; - opt[pos].price = price; - } } } - /* complete following positions with literals */ - { int addLit; - for (addLit = 1; addLit <= TRAILING_LITERALS; addLit ++) { - opt[last_match_pos+addLit].mlen = 1; /* literal */ - opt[last_match_pos+addLit].off = 0; - opt[last_match_pos+addLit].litlen = addLit; - opt[last_match_pos+addLit].price = opt[last_match_pos].price + LZ4HC_literalsPrice(addLit); - DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i)", last_match_pos+addLit, opt[last_match_pos+addLit].price, addLit); - } } - } /* for (cur = 1; cur <= last_match_pos; cur++) */ - - assert(last_match_pos < LZ4_OPT_NUM + TRAILING_LITERALS); - best_mlen = opt[last_match_pos].mlen; - best_off = opt[last_match_pos].off; - cur = last_match_pos - best_mlen; - -encode: /* cur, last_match_pos, best_mlen, best_off must be set */ - assert(cur < LZ4_OPT_NUM); - assert(last_match_pos >= 1); /* == 1 when only one candidate */ - DEBUGLOG(6, "reverse traversal, looking for shortest path (last_match_pos=%i)", last_match_pos); - { int candidate_pos = cur; - int selected_matchLength = best_mlen; - int selected_offset = best_off; - while (1) { /* from end to beginning */ - int const next_matchLength = opt[candidate_pos].mlen; /* can be 1, means literal */ - int const next_offset = opt[candidate_pos].off; - DEBUGLOG(7, "pos %i: sequence length %i", candidate_pos, selected_matchLength); - opt[candidate_pos].mlen = selected_matchLength; - opt[candidate_pos].off = selected_offset; - selected_matchLength = next_matchLength; - selected_offset = next_offset; - if (next_matchLength > candidate_pos) break; /* last match elected, first match to encode */ - assert(next_matchLength > 0); /* can be 1, means literal */ - candidate_pos -= next_matchLength; - } } - - /* encode all recorded sequences in order */ - { int rPos = 0; /* relative position (to ip) */ - while (rPos < last_match_pos) { - int const ml = opt[rPos].mlen; - int const offset = opt[rPos].off; - if (ml == 1) { ip++; rPos++; continue; } /* literal; note: can end up with several literals, in which case, skip them */ - rPos += ml; - assert(ml >= MINMATCH); - assert((offset >= 1) && (offset <= LZ4_DISTANCE_MAX)); - opSaved = op; - if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, ip - offset, limit, oend) ) { /* updates ip, op and anchor */ - ovml = ml; - ovref = ip - offset; - goto _dest_overflow; - } } } - } /* while (ip <= mflimit) */ - -_last_literals: - /* Encode Last Literals */ - { size_t lastRunSize = (size_t)(iend - anchor); /* literals */ - size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255; - size_t const totalSize = 1 + llAdd + lastRunSize; - if (limit == fillOutput) oend += LASTLITERALS; /* restore correct value */ - if (limit && (op + totalSize > oend)) { - if (limit == limitedOutput) { /* Check output limit */ - retval = 0; - goto _return_label; - } - /* adapt lastRunSize to fill 'dst' */ - lastRunSize = (size_t)(oend - op) - 1 /*token*/; - llAdd = (lastRunSize + 256 - RUN_MASK) / 256; - lastRunSize -= llAdd; - } - DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize); - ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */ - - if (lastRunSize >= RUN_MASK) { - size_t accumulator = lastRunSize - RUN_MASK; - *op++ = (RUN_MASK << ML_BITS); - for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255; - *op++ = (BYTE) accumulator; - } else { - *op++ = (BYTE)(lastRunSize << ML_BITS); - } - memcpy(op, anchor, lastRunSize); - op += lastRunSize; - } - - /* End */ - *srcSizePtr = (int) (((const char*)ip) - source); - retval = (int) ((char*)op-dst); - goto _return_label; - -_dest_overflow: -if (limit == fillOutput) { - /* Assumption : ip, anchor, ovml and ovref must be set correctly */ - size_t const ll = (size_t)(ip - anchor); - size_t const ll_addbytes = (ll + 240) / 255; - size_t const ll_totalCost = 1 + ll_addbytes + ll; - BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */ - DEBUGLOG(6, "Last sequence overflowing (only %i bytes remaining)", (int)(oend-1-opSaved)); - op = opSaved; /* restore correct out pointer */ - if (op + ll_totalCost <= maxLitPos) { - /* ll validated; now adjust match length */ - size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost)); - size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255); - assert(maxMlSize < INT_MAX); assert(ovml >= 0); - if ((size_t)ovml > maxMlSize) ovml = (int)maxMlSize; - if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ovml >= MFLIMIT) { - DEBUGLOG(6, "Space to end : %i + ml (%i)", (int)((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1), ovml); - DEBUGLOG(6, "Before : ip = %p, anchor = %p", ip, anchor); - LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ovml, ovref, notLimited, oend); - DEBUGLOG(6, "After : ip = %p, anchor = %p", ip, anchor); - } } - goto _last_literals; -} -_return_label: -#ifdef LZ4HC_HEAPMODE - FREEMEM(opt); -#endif - return retval; -} diff --git a/ta6ob/lz4/lib/lz4hc.h b/ta6ob/lz4/lib/lz4hc.h deleted file mode 100644 index 3d441fb..0000000 --- a/ta6ob/lz4/lib/lz4hc.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - LZ4 HC - High Compression Mode of LZ4 - Header File - Copyright (C) 2011-2017, Yann Collet. - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ -#ifndef LZ4_HC_H_19834876238432 -#define LZ4_HC_H_19834876238432 - -#if defined (__cplusplus) -extern "C" { -#endif - -/* --- Dependency --- */ -/* note : lz4hc requires lz4.h/lz4.c for compilation */ -#include "lz4.h" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */ - - -/* --- Useful constants --- */ -#define LZ4HC_CLEVEL_MIN 3 -#define LZ4HC_CLEVEL_DEFAULT 9 -#define LZ4HC_CLEVEL_OPT_MIN 10 -#define LZ4HC_CLEVEL_MAX 12 - - -/*-************************************ - * Block Compression - **************************************/ -/*! LZ4_compress_HC() : - * Compress data from `src` into `dst`, using the powerful but slower "HC" algorithm. - * `dst` must be already allocated. - * Compression is guaranteed to succeed if `dstCapacity >= LZ4_compressBound(srcSize)` (see "lz4.h") - * Max supported `srcSize` value is LZ4_MAX_INPUT_SIZE (see "lz4.h") - * `compressionLevel` : any value between 1 and LZ4HC_CLEVEL_MAX will work. - * Values > LZ4HC_CLEVEL_MAX behave the same as LZ4HC_CLEVEL_MAX. - * @return : the number of bytes written into 'dst' - * or 0 if compression fails. - */ -LZ4LIB_API int LZ4_compress_HC (const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel); - - -/* Note : - * Decompression functions are provided within "lz4.h" (BSD license) - */ - - -/*! LZ4_compress_HC_extStateHC() : - * Same as LZ4_compress_HC(), but using an externally allocated memory segment for `state`. - * `state` size is provided by LZ4_sizeofStateHC(). - * Memory segment must be aligned on 8-bytes boundaries (which a normal malloc() should do properly). - */ -LZ4LIB_API int LZ4_sizeofStateHC(void); -LZ4LIB_API int LZ4_compress_HC_extStateHC(void* stateHC, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel); - - -/*! LZ4_compress_HC_destSize() : v1.9.0+ - * Will compress as much data as possible from `src` - * to fit into `targetDstSize` budget. - * Result is provided in 2 parts : - * @return : the number of bytes written into 'dst' (necessarily <= targetDstSize) - * or 0 if compression fails. - * `srcSizePtr` : on success, *srcSizePtr is updated to indicate how much bytes were read from `src` - */ -LZ4LIB_API int LZ4_compress_HC_destSize(void* stateHC, - const char* src, char* dst, - int* srcSizePtr, int targetDstSize, - int compressionLevel); - - -/*-************************************ - * Streaming Compression - * Bufferless synchronous API - **************************************/ - typedef union LZ4_streamHC_u LZ4_streamHC_t; /* incomplete type (defined later) */ - -/*! LZ4_createStreamHC() and LZ4_freeStreamHC() : - * These functions create and release memory for LZ4 HC streaming state. - * Newly created states are automatically initialized. - * A same state can be used multiple times consecutively, - * starting with LZ4_resetStreamHC_fast() to start a new stream of blocks. - */ -LZ4LIB_API LZ4_streamHC_t* LZ4_createStreamHC(void); -LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr); - -/* - These functions compress data in successive blocks of any size, - using previous blocks as dictionary, to improve compression ratio. - One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks. - There is an exception for ring buffers, which can be smaller than 64 KB. - Ring-buffer scenario is automatically detected and handled within LZ4_compress_HC_continue(). - - Before starting compression, state must be allocated and properly initialized. - LZ4_createStreamHC() does both, though compression level is set to LZ4HC_CLEVEL_DEFAULT. - - Selecting the compression level can be done with LZ4_resetStreamHC_fast() (starts a new stream) - or LZ4_setCompressionLevel() (anytime, between blocks in the same stream) (experimental). - LZ4_resetStreamHC_fast() only works on states which have been properly initialized at least once, - which is automatically the case when state is created using LZ4_createStreamHC(). - - After reset, a first "fictional block" can be designated as initial dictionary, - using LZ4_loadDictHC() (Optional). - - Invoke LZ4_compress_HC_continue() to compress each successive block. - The number of blocks is unlimited. - Previous input blocks, including initial dictionary when present, - must remain accessible and unmodified during compression. - - It's allowed to update compression level anytime between blocks, - using LZ4_setCompressionLevel() (experimental). - - 'dst' buffer should be sized to handle worst case scenarios - (see LZ4_compressBound(), it ensures compression success). - In case of failure, the API does not guarantee recovery, - so the state _must_ be reset. - To ensure compression success - whenever `dst` buffer size cannot be made >= LZ4_compressBound(), - consider using LZ4_compress_HC_continue_destSize(). - - Whenever previous input blocks can't be preserved unmodified in-place during compression of next blocks, - it's possible to copy the last blocks into a more stable memory space, using LZ4_saveDictHC(). - Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer' (<= 64 KB) - - After completing a streaming compression, - it's possible to start a new stream of blocks, using the same LZ4_streamHC_t state, - just by resetting it, using LZ4_resetStreamHC_fast(). -*/ - -LZ4LIB_API void LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, int compressionLevel); /* v1.9.0+ */ -LZ4LIB_API int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize); - -LZ4LIB_API int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr, - const char* src, char* dst, - int srcSize, int maxDstSize); - -/*! LZ4_compress_HC_continue_destSize() : v1.9.0+ - * Similar to LZ4_compress_HC_continue(), - * but will read as much data as possible from `src` - * to fit into `targetDstSize` budget. - * Result is provided into 2 parts : - * @return : the number of bytes written into 'dst' (necessarily <= targetDstSize) - * or 0 if compression fails. - * `srcSizePtr` : on success, *srcSizePtr will be updated to indicate how much bytes were read from `src`. - * Note that this function may not consume the entire input. - */ -LZ4LIB_API int LZ4_compress_HC_continue_destSize(LZ4_streamHC_t* LZ4_streamHCPtr, - const char* src, char* dst, - int* srcSizePtr, int targetDstSize); - -LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize); - - - -/*^********************************************** - * !!!!!! STATIC LINKING ONLY !!!!!! - ***********************************************/ - -/*-****************************************************************** - * PRIVATE DEFINITIONS : - * Do not use these definitions directly. - * They are merely exposed to allow static allocation of `LZ4_streamHC_t`. - * Declare an `LZ4_streamHC_t` directly, rather than any type below. - * Even then, only do so in the context of static linking, as definitions may change between versions. - ********************************************************************/ - -#define LZ4HC_DICTIONARY_LOGSIZE 16 -#define LZ4HC_MAXD (1<= LZ4HC_CLEVEL_OPT_MIN. - */ -LZ4LIB_STATIC_API void LZ4_favorDecompressionSpeed( - LZ4_streamHC_t* LZ4_streamHCPtr, int favor); - -/*! LZ4_resetStreamHC_fast() : v1.9.0+ - * When an LZ4_streamHC_t is known to be in a internally coherent state, - * it can often be prepared for a new compression with almost no work, only - * sometimes falling back to the full, expensive reset that is always required - * when the stream is in an indeterminate state (i.e., the reset performed by - * LZ4_resetStreamHC()). - * - * LZ4_streamHCs are guaranteed to be in a valid state when: - * - returned from LZ4_createStreamHC() - * - reset by LZ4_resetStreamHC() - * - memset(stream, 0, sizeof(LZ4_streamHC_t)) - * - the stream was in a valid state and was reset by LZ4_resetStreamHC_fast() - * - the stream was in a valid state and was then used in any compression call - * that returned success - * - the stream was in an indeterminate state and was used in a compression - * call that fully reset the state (LZ4_compress_HC_extStateHC()) and that - * returned success - * - * Note: - * A stream that was last used in a compression call that returned an error - * may be passed to this function. However, it will be fully reset, which will - * clear any existing history and settings from the context. - */ -LZ4LIB_STATIC_API void LZ4_resetStreamHC_fast( - LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel); - -/*! LZ4_compress_HC_extStateHC_fastReset() : - * A variant of LZ4_compress_HC_extStateHC(). - * - * Using this variant avoids an expensive initialization step. It is only safe - * to call if the state buffer is known to be correctly initialized already - * (see above comment on LZ4_resetStreamHC_fast() for a definition of - * "correctly initialized"). From a high level, the difference is that this - * function initializes the provided state with a call to - * LZ4_resetStreamHC_fast() while LZ4_compress_HC_extStateHC() starts with a - * call to LZ4_resetStreamHC(). - */ -LZ4LIB_STATIC_API int LZ4_compress_HC_extStateHC_fastReset ( - void* state, - const char* src, char* dst, - int srcSize, int dstCapacity, - int compressionLevel); - -/*! LZ4_attach_HC_dictionary() : - * This is an experimental API that allows for the efficient use of a - * static dictionary many times. - * - * Rather than re-loading the dictionary buffer into a working context before - * each compression, or copying a pre-loaded dictionary's LZ4_streamHC_t into a - * working LZ4_streamHC_t, this function introduces a no-copy setup mechanism, - * in which the working stream references the dictionary stream in-place. - * - * Several assumptions are made about the state of the dictionary stream. - * Currently, only streams which have been prepared by LZ4_loadDictHC() should - * be expected to work. - * - * Alternatively, the provided dictionary stream pointer may be NULL, in which - * case any existing dictionary stream is unset. - * - * A dictionary should only be attached to a stream without any history (i.e., - * a stream that has just been reset). - * - * The dictionary will remain attached to the working stream only for the - * current stream session. Calls to LZ4_resetStreamHC(_fast) will remove the - * dictionary context association from the working stream. The dictionary - * stream (and source buffer) must remain in-place / accessible / unchanged - * through the lifetime of the stream session. - */ -LZ4LIB_STATIC_API void LZ4_attach_HC_dictionary( - LZ4_streamHC_t *working_stream, - const LZ4_streamHC_t *dictionary_stream); - -#if defined (__cplusplus) -} -#endif - -#endif /* LZ4_HC_SLO_098092834 */ -#endif /* LZ4_HC_STATIC_LINKING_ONLY */ diff --git a/ta6ob/lz4/lib/xxhash.c b/ta6ob/lz4/lib/xxhash.c deleted file mode 100644 index ff28749..0000000 --- a/ta6ob/lz4/lib/xxhash.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* -* xxHash - Fast Hash algorithm -* Copyright (C) 2012-2016, Yann Collet -* -* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are -* met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above -* copyright notice, this list of conditions and the following disclaimer -* in the documentation and/or other materials provided with the -* distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* You can contact the author at : -* - xxHash homepage: http://www.xxhash.com -* - xxHash source repository : https://github.com/Cyan4973/xxHash -*/ - - -/* ************************************* -* Tuning parameters -***************************************/ -/*!XXH_FORCE_MEMORY_ACCESS : - * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. - * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. - * The below switch allow to select different access method for improved performance. - * Method 0 (default) : use `memcpy()`. Safe and portable. - * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). - * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. - * Method 2 : direct access. This method doesn't depend on compiler but violate C standard. - * It can generate buggy code on targets which do not support unaligned memory accesses. - * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) - * See http://stackoverflow.com/a/32095106/646947 for details. - * Prefer these methods in priority order (0 > 1 > 2) - */ -#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ -# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ - || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ - || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) -# define XXH_FORCE_MEMORY_ACCESS 2 -# elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || \ - (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ - || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ - || defined(__ARM_ARCH_7S__) )) -# define XXH_FORCE_MEMORY_ACCESS 1 -# endif -#endif - -/*!XXH_ACCEPT_NULL_INPUT_POINTER : - * If input pointer is NULL, xxHash default behavior is to dereference it, triggering a segfault. - * When this macro is enabled, xxHash actively checks input for null pointer. - * It it is, result for null input pointers is the same as a null-length input. - */ -#ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */ -# define XXH_ACCEPT_NULL_INPUT_POINTER 0 -#endif - -/*!XXH_FORCE_NATIVE_FORMAT : - * By default, xxHash library provides endian-independent Hash values, based on little-endian convention. - * Results are therefore identical for little-endian and big-endian CPU. - * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. - * Should endian-independence be of no importance for your application, you may set the #define below to 1, - * to improve speed for Big-endian CPU. - * This option has no impact on Little_Endian CPU. - */ -#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */ -# define XXH_FORCE_NATIVE_FORMAT 0 -#endif - -/*!XXH_FORCE_ALIGN_CHECK : - * This is a minor performance trick, only useful with lots of very small keys. - * It means : check for aligned/unaligned input. - * The check costs one initial branch per hash; - * set it to 0 when the input is guaranteed to be aligned, - * or when alignment doesn't matter for performance. - */ -#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ -# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) -# define XXH_FORCE_ALIGN_CHECK 0 -# else -# define XXH_FORCE_ALIGN_CHECK 1 -# endif -#endif - - -/* ************************************* -* Includes & Memory related functions -***************************************/ -/*! Modify the local functions below should you wish to use some other memory routines -* for malloc(), free() */ -#include -static void* XXH_malloc(size_t s) { return malloc(s); } -static void XXH_free (void* p) { free(p); } -/*! and for memcpy() */ -#include -static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } - -#include /* assert */ - -#define XXH_STATIC_LINKING_ONLY -#include "xxhash.h" - - -/* ************************************* -* Compiler Specific Options -***************************************/ -#ifdef _MSC_VER /* Visual Studio */ -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -# define FORCE_INLINE static __forceinline -#else -# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -# ifdef __GNUC__ -# define FORCE_INLINE static inline __attribute__((always_inline)) -# else -# define FORCE_INLINE static inline -# endif -# else -# define FORCE_INLINE static -# endif /* __STDC_VERSION__ */ -#endif - - -/* ************************************* -* Basic Types -***************************************/ -#ifndef MEM_MODULE -# if !defined (__VMS) \ - && (defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint8_t BYTE; - typedef uint16_t U16; - typedef uint32_t U32; -# else - typedef unsigned char BYTE; - typedef unsigned short U16; - typedef unsigned int U32; -# endif -#endif - -#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) - -/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ -static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; } - -#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) - -/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ -/* currently only defined for gcc and icc */ -typedef union { U32 u32; } __attribute__((packed)) unalign; -static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } - -#else - -/* portable and safe solution. Generally efficient. - * see : http://stackoverflow.com/a/32095106/646947 - */ -static U32 XXH_read32(const void* memPtr) -{ - U32 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ - - -/* **************************************** -* Compiler-specific Functions and Macros -******************************************/ -#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) - -/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ -#if defined(_MSC_VER) -# define XXH_rotl32(x,r) _rotl(x,r) -# define XXH_rotl64(x,r) _rotl64(x,r) -#else -# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) -# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) -#endif - -#if defined(_MSC_VER) /* Visual Studio */ -# define XXH_swap32 _byteswap_ulong -#elif XXH_GCC_VERSION >= 403 -# define XXH_swap32 __builtin_bswap32 -#else -static U32 XXH_swap32 (U32 x) -{ - return ((x << 24) & 0xff000000 ) | - ((x << 8) & 0x00ff0000 ) | - ((x >> 8) & 0x0000ff00 ) | - ((x >> 24) & 0x000000ff ); -} -#endif - - -/* ************************************* -* Architecture Macros -***************************************/ -typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; - -/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ -#ifndef XXH_CPU_LITTLE_ENDIAN -static int XXH_isLittleEndian(void) -{ - const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ - return one.c[0]; -} -# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() -#endif - - -/* *************************** -* Memory reads -*****************************/ -typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; - -FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align) -{ - if (align==XXH_unaligned) - return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); - else - return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr); -} - -FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian) -{ - return XXH_readLE32_align(ptr, endian, XXH_unaligned); -} - -static U32 XXH_readBE32(const void* ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); -} - - -/* ************************************* -* Macros -***************************************/ -#define XXH_STATIC_ASSERT(c) { enum { XXH_sa = 1/(int)(!!(c)) }; } /* use after variable declarations */ -XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } - - -/* ******************************************************************* -* 32-bit hash functions -*********************************************************************/ -static const U32 PRIME32_1 = 2654435761U; -static const U32 PRIME32_2 = 2246822519U; -static const U32 PRIME32_3 = 3266489917U; -static const U32 PRIME32_4 = 668265263U; -static const U32 PRIME32_5 = 374761393U; - -static U32 XXH32_round(U32 seed, U32 input) -{ - seed += input * PRIME32_2; - seed = XXH_rotl32(seed, 13); - seed *= PRIME32_1; - return seed; -} - -/* mix all bits */ -static U32 XXH32_avalanche(U32 h32) -{ - h32 ^= h32 >> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - return(h32); -} - -#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) - -static U32 -XXH32_finalize(U32 h32, const void* ptr, size_t len, - XXH_endianess endian, XXH_alignment align) - -{ - const BYTE* p = (const BYTE*)ptr; - -#define PROCESS1 \ - h32 += (*p++) * PRIME32_5; \ - h32 = XXH_rotl32(h32, 11) * PRIME32_1 ; - -#define PROCESS4 \ - h32 += XXH_get32bits(p) * PRIME32_3; \ - p+=4; \ - h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; - - switch(len&15) /* or switch(bEnd - p) */ - { - case 12: PROCESS4; - /* fallthrough */ - case 8: PROCESS4; - /* fallthrough */ - case 4: PROCESS4; - return XXH32_avalanche(h32); - - case 13: PROCESS4; - /* fallthrough */ - case 9: PROCESS4; - /* fallthrough */ - case 5: PROCESS4; - PROCESS1; - return XXH32_avalanche(h32); - - case 14: PROCESS4; - /* fallthrough */ - case 10: PROCESS4; - /* fallthrough */ - case 6: PROCESS4; - PROCESS1; - PROCESS1; - return XXH32_avalanche(h32); - - case 15: PROCESS4; - /* fallthrough */ - case 11: PROCESS4; - /* fallthrough */ - case 7: PROCESS4; - /* fallthrough */ - case 3: PROCESS1; - /* fallthrough */ - case 2: PROCESS1; - /* fallthrough */ - case 1: PROCESS1; - /* fallthrough */ - case 0: return XXH32_avalanche(h32); - } - assert(0); - return h32; /* reaching this point is deemed impossible */ -} - - -FORCE_INLINE U32 -XXH32_endian_align(const void* input, size_t len, U32 seed, - XXH_endianess endian, XXH_alignment align) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* bEnd = p + len; - U32 h32; - -#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) - if (p==NULL) { - len=0; - bEnd=p=(const BYTE*)(size_t)16; - } -#endif - - if (len>=16) { - const BYTE* const limit = bEnd - 15; - U32 v1 = seed + PRIME32_1 + PRIME32_2; - U32 v2 = seed + PRIME32_2; - U32 v3 = seed + 0; - U32 v4 = seed - PRIME32_1; - - do { - v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4; - v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4; - v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4; - v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4; - } while (p < limit); - - h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) - + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); - } else { - h32 = seed + PRIME32_5; - } - - h32 += (U32)len; - - return XXH32_finalize(h32, p, len&15, endian, align); -} - - -XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed) -{ -#if 0 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH32_state_t state; - XXH32_reset(&state, seed); - XXH32_update(&state, input, len); - return XXH32_digest(&state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if (XXH_FORCE_ALIGN_CHECK) { - if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); - } } - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - - - -/*====== Hash streaming ======*/ - -XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) -{ - return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); -} -XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -} - -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) -{ - memcpy(dstState, srcState, sizeof(*dstState)); -} - -XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed) -{ - XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)); - state.v1 = seed + PRIME32_1 + PRIME32_2; - state.v2 = seed + PRIME32_2; - state.v3 = seed + 0; - state.v4 = seed - PRIME32_1; - /* do not write into reserved, planned to be removed in a future version */ - memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); - return XXH_OK; -} - - -FORCE_INLINE XXH_errorcode -XXH32_update_endian(XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian) -{ - if (input==NULL) -#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) - return XXH_OK; -#else - return XXH_ERROR; -#endif - - { const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - - state->total_len_32 += (unsigned)len; - state->large_len |= (len>=16) | (state->total_len_32>=16); - - if (state->memsize + len < 16) { /* fill in tmp buffer */ - XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len); - state->memsize += (unsigned)len; - return XXH_OK; - } - - if (state->memsize) { /* some data left from previous update */ - XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize); - { const U32* p32 = state->mem32; - state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++; - state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++; - state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++; - state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); - } - p += 16-state->memsize; - state->memsize = 0; - } - - if (p <= bEnd-16) { - const BYTE* const limit = bEnd - 16; - U32 v1 = state->v1; - U32 v2 = state->v2; - U32 v3 = state->v3; - U32 v4 = state->v4; - - do { - v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4; - v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4; - v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4; - v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4; - } while (p<=limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) { - XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); - } - } - - return XXH_OK; -} - - -XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH32_update_endian(state_in, input, len, XXH_bigEndian); -} - - -FORCE_INLINE U32 -XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian) -{ - U32 h32; - - if (state->large_len) { - h32 = XXH_rotl32(state->v1, 1) - + XXH_rotl32(state->v2, 7) - + XXH_rotl32(state->v3, 12) - + XXH_rotl32(state->v4, 18); - } else { - h32 = state->v3 /* == seed */ + PRIME32_5; - } - - h32 += state->total_len_32; - - return XXH32_finalize(h32, state->mem32, state->memsize, endian, XXH_aligned); -} - - -XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_digest_endian(state_in, XXH_littleEndian); - else - return XXH32_digest_endian(state_in, XXH_bigEndian); -} - - -/*====== Canonical representation ======*/ - -/*! Default XXH result types are basic unsigned 32 and 64 bits. -* The canonical representation follows human-readable write convention, aka big-endian (large digits first). -* These functions allow transformation of hash result into and from its canonical format. -* This way, hash values can be written into a file or buffer, remaining comparable across different systems. -*/ - -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); - memcpy(dst, &hash, sizeof(*dst)); -} - -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) -{ - return XXH_readBE32(src); -} - - -#ifndef XXH_NO_LONG_LONG - -/* ******************************************************************* -* 64-bit hash functions -*********************************************************************/ - -/*====== Memory access ======*/ - -#ifndef MEM_MODULE -# define MEM_MODULE -# if !defined (__VMS) \ - && (defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint64_t U64; -# else - /* if compiler doesn't support unsigned long long, replace by another 64-bit type */ - typedef unsigned long long U64; -# endif -#endif - - -#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) - -/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ -static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; } - -#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) - -/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ -/* currently only defined for gcc and icc */ -typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign64; -static U64 XXH_read64(const void* ptr) { return ((const unalign64*)ptr)->u64; } - -#else - -/* portable and safe solution. Generally efficient. - * see : http://stackoverflow.com/a/32095106/646947 - */ - -static U64 XXH_read64(const void* memPtr) -{ - U64 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ - -#if defined(_MSC_VER) /* Visual Studio */ -# define XXH_swap64 _byteswap_uint64 -#elif XXH_GCC_VERSION >= 403 -# define XXH_swap64 __builtin_bswap64 -#else -static U64 XXH_swap64 (U64 x) -{ - return ((x << 56) & 0xff00000000000000ULL) | - ((x << 40) & 0x00ff000000000000ULL) | - ((x << 24) & 0x0000ff0000000000ULL) | - ((x << 8) & 0x000000ff00000000ULL) | - ((x >> 8) & 0x00000000ff000000ULL) | - ((x >> 24) & 0x0000000000ff0000ULL) | - ((x >> 40) & 0x000000000000ff00ULL) | - ((x >> 56) & 0x00000000000000ffULL); -} -#endif - -FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align) -{ - if (align==XXH_unaligned) - return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); - else - return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr); -} - -FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian) -{ - return XXH_readLE64_align(ptr, endian, XXH_unaligned); -} - -static U64 XXH_readBE64(const void* ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); -} - - -/*====== xxh64 ======*/ - -static const U64 PRIME64_1 = 11400714785074694791ULL; -static const U64 PRIME64_2 = 14029467366897019727ULL; -static const U64 PRIME64_3 = 1609587929392839161ULL; -static const U64 PRIME64_4 = 9650029242287828579ULL; -static const U64 PRIME64_5 = 2870177450012600261ULL; - -static U64 XXH64_round(U64 acc, U64 input) -{ - acc += input * PRIME64_2; - acc = XXH_rotl64(acc, 31); - acc *= PRIME64_1; - return acc; -} - -static U64 XXH64_mergeRound(U64 acc, U64 val) -{ - val = XXH64_round(0, val); - acc ^= val; - acc = acc * PRIME64_1 + PRIME64_4; - return acc; -} - -static U64 XXH64_avalanche(U64 h64) -{ - h64 ^= h64 >> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - return h64; -} - - -#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) - -static U64 -XXH64_finalize(U64 h64, const void* ptr, size_t len, - XXH_endianess endian, XXH_alignment align) -{ - const BYTE* p = (const BYTE*)ptr; - -#define PROCESS1_64 \ - h64 ^= (*p++) * PRIME64_5; \ - h64 = XXH_rotl64(h64, 11) * PRIME64_1; - -#define PROCESS4_64 \ - h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; \ - p+=4; \ - h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; - -#define PROCESS8_64 { \ - U64 const k1 = XXH64_round(0, XXH_get64bits(p)); \ - p+=8; \ - h64 ^= k1; \ - h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; \ -} - - switch(len&31) { - case 24: PROCESS8_64; - /* fallthrough */ - case 16: PROCESS8_64; - /* fallthrough */ - case 8: PROCESS8_64; - return XXH64_avalanche(h64); - - case 28: PROCESS8_64; - /* fallthrough */ - case 20: PROCESS8_64; - /* fallthrough */ - case 12: PROCESS8_64; - /* fallthrough */ - case 4: PROCESS4_64; - return XXH64_avalanche(h64); - - case 25: PROCESS8_64; - /* fallthrough */ - case 17: PROCESS8_64; - /* fallthrough */ - case 9: PROCESS8_64; - PROCESS1_64; - return XXH64_avalanche(h64); - - case 29: PROCESS8_64; - /* fallthrough */ - case 21: PROCESS8_64; - /* fallthrough */ - case 13: PROCESS8_64; - /* fallthrough */ - case 5: PROCESS4_64; - PROCESS1_64; - return XXH64_avalanche(h64); - - case 26: PROCESS8_64; - /* fallthrough */ - case 18: PROCESS8_64; - /* fallthrough */ - case 10: PROCESS8_64; - PROCESS1_64; - PROCESS1_64; - return XXH64_avalanche(h64); - - case 30: PROCESS8_64; - /* fallthrough */ - case 22: PROCESS8_64; - /* fallthrough */ - case 14: PROCESS8_64; - /* fallthrough */ - case 6: PROCESS4_64; - PROCESS1_64; - PROCESS1_64; - return XXH64_avalanche(h64); - - case 27: PROCESS8_64; - /* fallthrough */ - case 19: PROCESS8_64; - /* fallthrough */ - case 11: PROCESS8_64; - PROCESS1_64; - PROCESS1_64; - PROCESS1_64; - return XXH64_avalanche(h64); - - case 31: PROCESS8_64; - /* fallthrough */ - case 23: PROCESS8_64; - /* fallthrough */ - case 15: PROCESS8_64; - /* fallthrough */ - case 7: PROCESS4_64; - /* fallthrough */ - case 3: PROCESS1_64; - /* fallthrough */ - case 2: PROCESS1_64; - /* fallthrough */ - case 1: PROCESS1_64; - /* fallthrough */ - case 0: return XXH64_avalanche(h64); - } - - /* impossible to reach */ - assert(0); - return 0; /* unreachable, but some compilers complain without it */ -} - -FORCE_INLINE U64 -XXH64_endian_align(const void* input, size_t len, U64 seed, - XXH_endianess endian, XXH_alignment align) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* bEnd = p + len; - U64 h64; - -#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) - if (p==NULL) { - len=0; - bEnd=p=(const BYTE*)(size_t)32; - } -#endif - - if (len>=32) { - const BYTE* const limit = bEnd - 32; - U64 v1 = seed + PRIME64_1 + PRIME64_2; - U64 v2 = seed + PRIME64_2; - U64 v3 = seed + 0; - U64 v4 = seed - PRIME64_1; - - do { - v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8; - v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8; - v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8; - v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8; - } while (p<=limit); - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); - h64 = XXH64_mergeRound(h64, v1); - h64 = XXH64_mergeRound(h64, v2); - h64 = XXH64_mergeRound(h64, v3); - h64 = XXH64_mergeRound(h64, v4); - - } else { - h64 = seed + PRIME64_5; - } - - h64 += (U64) len; - - return XXH64_finalize(h64, p, len, endian, align); -} - - -XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed) -{ -#if 0 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH64_state_t state; - XXH64_reset(&state, seed); - XXH64_update(&state, input, len); - return XXH64_digest(&state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if (XXH_FORCE_ALIGN_CHECK) { - if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); - } } - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - -/*====== Hash Streaming ======*/ - -XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) -{ - return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); -} -XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -} - -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState) -{ - memcpy(dstState, srcState, sizeof(*dstState)); -} - -XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed) -{ - XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)); - state.v1 = seed + PRIME64_1 + PRIME64_2; - state.v2 = seed + PRIME64_2; - state.v3 = seed + 0; - state.v4 = seed - PRIME64_1; - /* do not write into reserved, planned to be removed in a future version */ - memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); - return XXH_OK; -} - -FORCE_INLINE XXH_errorcode -XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian) -{ - if (input==NULL) -#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) - return XXH_OK; -#else - return XXH_ERROR; -#endif - - { const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - - state->total_len += len; - - if (state->memsize + len < 32) { /* fill in tmp buffer */ - XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); - state->memsize += (U32)len; - return XXH_OK; - } - - if (state->memsize) { /* tmp buffer is full */ - XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize); - state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian)); - state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian)); - state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian)); - state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian)); - p += 32-state->memsize; - state->memsize = 0; - } - - if (p+32 <= bEnd) { - const BYTE* const limit = bEnd - 32; - U64 v1 = state->v1; - U64 v2 = state->v2; - U64 v3 = state->v3; - U64 v4 = state->v4; - - do { - v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8; - v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8; - v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8; - v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8; - } while (p<=limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) { - XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); - } - } - - return XXH_OK; -} - -XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH64_update_endian(state_in, input, len, XXH_bigEndian); -} - -FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian) -{ - U64 h64; - - if (state->total_len >= 32) { - U64 const v1 = state->v1; - U64 const v2 = state->v2; - U64 const v3 = state->v3; - U64 const v4 = state->v4; - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); - h64 = XXH64_mergeRound(h64, v1); - h64 = XXH64_mergeRound(h64, v2); - h64 = XXH64_mergeRound(h64, v3); - h64 = XXH64_mergeRound(h64, v4); - } else { - h64 = state->v3 /*seed*/ + PRIME64_5; - } - - h64 += (U64) state->total_len; - - return XXH64_finalize(h64, state->mem64, (size_t)state->total_len, endian, XXH_aligned); -} - -XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_digest_endian(state_in, XXH_littleEndian); - else - return XXH64_digest_endian(state_in, XXH_bigEndian); -} - - -/*====== Canonical representation ======*/ - -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); - memcpy(dst, &hash, sizeof(*dst)); -} - -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) -{ - return XXH_readBE64(src); -} - -#endif /* XXH_NO_LONG_LONG */ diff --git a/ta6ob/lz4/lib/xxhash.h b/ta6ob/lz4/lib/xxhash.h deleted file mode 100644 index d6bad94..0000000 --- a/ta6ob/lz4/lib/xxhash.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - xxHash - Extremely Fast Hash algorithm - Header File - Copyright (C) 2012-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - xxHash source repository : https://github.com/Cyan4973/xxHash -*/ - -/* Notice extracted from xxHash homepage : - -xxHash is an extremely fast Hash algorithm, running at RAM speed limits. -It also successfully passes all tests from the SMHasher suite. - -Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) - -Name Speed Q.Score Author -xxHash 5.4 GB/s 10 -CrapWow 3.2 GB/s 2 Andrew -MumurHash 3a 2.7 GB/s 10 Austin Appleby -SpookyHash 2.0 GB/s 10 Bob Jenkins -SBox 1.4 GB/s 9 Bret Mulvey -Lookup3 1.2 GB/s 9 Bob Jenkins -SuperFastHash 1.2 GB/s 1 Paul Hsieh -CityHash64 1.05 GB/s 10 Pike & Alakuijala -FNV 0.55 GB/s 5 Fowler, Noll, Vo -CRC32 0.43 GB/s 9 -MD5-32 0.33 GB/s 10 Ronald L. Rivest -SHA1-32 0.28 GB/s 10 - -Q.Score is a measure of quality of the hash function. -It depends on successfully passing SMHasher test set. -10 is a perfect score. - -A 64-bit version, named XXH64, is available since r35. -It offers much better speed, but for 64-bit applications only. -Name Speed on 64 bits Speed on 32 bits -XXH64 13.8 GB/s 1.9 GB/s -XXH32 6.8 GB/s 6.0 GB/s -*/ - -#ifndef XXHASH_H_5627135585666179 -#define XXHASH_H_5627135585666179 1 - -#if defined (__cplusplus) -extern "C" { -#endif - - -/* **************************** -* Definitions -******************************/ -#include /* size_t */ -typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; - - -/* **************************** - * API modifier - ******************************/ -/** XXH_INLINE_ALL (and XXH_PRIVATE_API) - * This is useful to include xxhash functions in `static` mode - * in order to inline them, and remove their symbol from the public list. - * Inlining can offer dramatic performance improvement on small keys. - * Methodology : - * #define XXH_INLINE_ALL - * #include "xxhash.h" - * `xxhash.c` is automatically included. - * It's not useful to compile and link it as a separate module. - */ -#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) -# ifndef XXH_STATIC_LINKING_ONLY -# define XXH_STATIC_LINKING_ONLY -# endif -# if defined(__GNUC__) -# define XXH_PUBLIC_API static __inline __attribute__((unused)) -# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -# define XXH_PUBLIC_API static inline -# elif defined(_MSC_VER) -# define XXH_PUBLIC_API static __inline -# else - /* this version may generate warnings for unused static functions */ -# define XXH_PUBLIC_API static -# endif -#else -# define XXH_PUBLIC_API /* do nothing */ -#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ - -/*! XXH_NAMESPACE, aka Namespace Emulation : - * - * If you want to include _and expose_ xxHash functions from within your own library, - * but also want to avoid symbol collisions with other libraries which may also include xxHash, - * - * you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library - * with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values). - * - * Note that no change is required within the calling program as long as it includes `xxhash.h` : - * regular symbol name will be automatically translated by this header. - */ -#ifdef XXH_NAMESPACE -# define XXH_CAT(A,B) A##B -# define XXH_NAME2(A,B) XXH_CAT(A,B) -# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) -# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) -# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) -# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) -# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) -# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) -# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) -# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) -# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) -# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) -# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) -# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) -# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) -# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) -# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) -# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) -# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) -# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) -# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) -#endif - - -/* ************************************* -* Version -***************************************/ -#define XXH_VERSION_MAJOR 0 -#define XXH_VERSION_MINOR 6 -#define XXH_VERSION_RELEASE 5 -#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) -XXH_PUBLIC_API unsigned XXH_versionNumber (void); - - -/*-********************************************************************** -* 32-bit hash -************************************************************************/ -typedef unsigned int XXH32_hash_t; - -/*! XXH32() : - Calculate the 32-bit hash of sequence "length" bytes stored at memory address "input". - The memory between input & input+length must be valid (allocated and read-accessible). - "seed" can be used to alter the result predictably. - Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */ -XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed); - -/*====== Streaming ======*/ -typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ -XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void); -XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); - -XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed); -XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); - -/* - * Streaming functions generate the xxHash of an input provided in multiple segments. - * Note that, for small input, they are slower than single-call functions, due to state management. - * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. - * - * XXH state must first be allocated, using XXH*_createState() . - * - * Start a new hash by initializing state with a seed, using XXH*_reset(). - * - * Then, feed the hash state by calling XXH*_update() as many times as necessary. - * The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. - * - * Finally, a hash value can be produced anytime, by using XXH*_digest(). - * This function returns the nn-bits hash as an int or long long. - * - * It's still possible to continue inserting input into the hash state after a digest, - * and generate some new hashes later on, by calling again XXH*_digest(). - * - * When done, free XXH state space if it was allocated dynamically. - */ - -/*====== Canonical representation ======*/ - -typedef struct { unsigned char digest[4]; } XXH32_canonical_t; -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); - -/* Default result type for XXH functions are primitive unsigned 32 and 64 bits. - * The canonical representation uses human-readable write convention, aka big-endian (large digits first). - * These functions allow transformation of hash result into and from its canonical format. - * This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. - */ - - -#ifndef XXH_NO_LONG_LONG -/*-********************************************************************** -* 64-bit hash -************************************************************************/ -typedef unsigned long long XXH64_hash_t; - -/*! XXH64() : - Calculate the 64-bit hash of sequence of length "len" stored at memory address "input". - "seed" can be used to alter the result predictably. - This function runs faster on 64-bit systems, but slower on 32-bit systems (see benchmark). -*/ -XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed); - -/*====== Streaming ======*/ -typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ -XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void); -XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state); - -XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); -XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); - -/*====== Canonical representation ======*/ -typedef struct { unsigned char digest[8]; } XXH64_canonical_t; -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); -#endif /* XXH_NO_LONG_LONG */ - - - -#ifdef XXH_STATIC_LINKING_ONLY - -/* ================================================================================================ - This section contains declarations which are not guaranteed to remain stable. - They may change in future versions, becoming incompatible with a different version of the library. - These declarations should only be used with static linking. - Never use them in association with dynamic linking ! -=================================================================================================== */ - -/* These definitions are only present to allow - * static allocation of XXH state, on stack or in a struct for example. - * Never **ever** use members directly. */ - -#if !defined (__VMS) \ - && (defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - -struct XXH32_state_s { - uint32_t total_len_32; - uint32_t large_len; - uint32_t v1; - uint32_t v2; - uint32_t v3; - uint32_t v4; - uint32_t mem32[4]; - uint32_t memsize; - uint32_t reserved; /* never read nor write, might be removed in a future version */ -}; /* typedef'd to XXH32_state_t */ - -struct XXH64_state_s { - uint64_t total_len; - uint64_t v1; - uint64_t v2; - uint64_t v3; - uint64_t v4; - uint64_t mem64[4]; - uint32_t memsize; - uint32_t reserved[2]; /* never read nor write, might be removed in a future version */ -}; /* typedef'd to XXH64_state_t */ - -# else - -struct XXH32_state_s { - unsigned total_len_32; - unsigned large_len; - unsigned v1; - unsigned v2; - unsigned v3; - unsigned v4; - unsigned mem32[4]; - unsigned memsize; - unsigned reserved; /* never read nor write, might be removed in a future version */ -}; /* typedef'd to XXH32_state_t */ - -# ifndef XXH_NO_LONG_LONG /* remove 64-bit support */ -struct XXH64_state_s { - unsigned long long total_len; - unsigned long long v1; - unsigned long long v2; - unsigned long long v3; - unsigned long long v4; - unsigned long long mem64[4]; - unsigned memsize; - unsigned reserved[2]; /* never read nor write, might be removed in a future version */ -}; /* typedef'd to XXH64_state_t */ -# endif - -# endif - - -#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) -# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */ -#endif - -#endif /* XXH_STATIC_LINKING_ONLY */ - - -#if defined (__cplusplus) -} -#endif - -#endif /* XXHASH_H_5627135585666179 */ diff --git a/ta6ob/lz4/ossfuzz/Makefile b/ta6ob/lz4/ossfuzz/Makefile deleted file mode 100644 index 2ec1675..0000000 --- a/ta6ob/lz4/ossfuzz/Makefile +++ /dev/null @@ -1,78 +0,0 @@ -# ########################################################################## -# LZ4 oss fuzzer - Makefile -# -# GPL v2 License -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# You can contact the author at : -# - LZ4 homepage : http://www.lz4.org -# - LZ4 source repository : https://github.com/lz4/lz4 -# ########################################################################## -# compress_fuzzer : OSS Fuzz test tool -# decompress_fuzzer : OSS Fuzz test tool -# ########################################################################## - -LZ4DIR := ../lib -LIB_FUZZING_ENGINE ?= - -DEBUGLEVEL?= 1 -DEBUGFLAGS = -g -DLZ4_DEBUG=$(DEBUGLEVEL) - -LZ4_CFLAGS = $(CFLAGS) $(DEBUGFLAGS) $(MOREFLAGS) -LZ4_CXXFLAGS = $(CXXFLAGS) $(DEBUGFLAGS) $(MOREFLAGS) -LZ4_CPPFLAGS = $(CPPFLAGS) -I$(LZ4DIR) -DXXH_NAMESPACE=LZ4_ \ - -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - -FUZZERS := \ - compress_fuzzer \ - decompress_fuzzer \ - round_trip_fuzzer \ - round_trip_stream_fuzzer \ - compress_hc_fuzzer \ - round_trip_hc_fuzzer \ - compress_frame_fuzzer \ - round_trip_frame_fuzzer \ - decompress_frame_fuzzer - -.PHONY: all -all: $(FUZZERS) - -# Include a rule to build the static library if calling this target -# directly. -$(LZ4DIR)/liblz4.a: - $(MAKE) -C $(LZ4DIR) CFLAGS="$(LZ4_CFLAGS)" liblz4.a - -%.o: %.c - $(CC) -c $(LZ4_CFLAGS) $(LZ4_CPPFLAGS) $< -o $@ - -# Generic rule for generating fuzzers -ifeq ($(LIB_FUZZING_ENGINE),) - LIB_FUZZING_DEPS := standaloneengine.o -else - LIB_FUZZING_DEPS := -endif -%_fuzzer: %_fuzzer.o lz4_helpers.o fuzz_data_producer.o $(LZ4DIR)/liblz4.a $(LIB_FUZZING_DEPS) - $(CXX) $(LZ4_CXXFLAGS) $(LZ4_CPPFLAGS) $(LDFLAGS) $(LIB_FUZZING_ENGINE) $^ -o $@$(EXT) - -%_fuzzer_clean: - $(RM) $*_fuzzer $*_fuzzer.o standaloneengine.o - -.PHONY: clean -clean: compress_fuzzer_clean decompress_fuzzer_clean \ - compress_frame_fuzzer_clean compress_hc_fuzzer_clean \ - decompress_frame_fuzzer_clean round_trip_frame_fuzzer_clean \ - round_trip_fuzzer_clean round_trip_hc_fuzzer_clean round_trip_stream_fuzzer_clean - $(MAKE) -C $(LZ4DIR) clean diff --git a/ta6ob/lz4/ossfuzz/compress_frame_fuzzer.c b/ta6ob/lz4/ossfuzz/compress_frame_fuzzer.c deleted file mode 100644 index 568ae14..0000000 --- a/ta6ob/lz4/ossfuzz/compress_frame_fuzzer.c +++ /dev/null @@ -1,48 +0,0 @@ -/** - * This fuzz target attempts to compress the fuzzed data with the simple - * compression function with an output buffer that may be too small to - * ensure that the compressor never crashes. - */ - -#include -#include -#include -#include - -#include "fuzz_helpers.h" -#include "lz4.h" -#include "lz4frame.h" -#include "lz4_helpers.h" -#include "fuzz_data_producer.h" - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size); - LZ4F_preferences_t const prefs = FUZZ_dataProducer_preferences(producer); - size_t const dstCapacitySeed = FUZZ_dataProducer_retrieve32(producer); - size = FUZZ_dataProducer_remainingBytes(producer); - - size_t const compressBound = LZ4F_compressFrameBound(size, &prefs); - size_t const dstCapacity = FUZZ_getRange_from_uint32(dstCapacitySeed, 0, compressBound); - - char* const dst = (char*)malloc(dstCapacity); - char* const rt = (char*)malloc(size); - - FUZZ_ASSERT(dst!=NULL); - FUZZ_ASSERT(rt!=NULL); - - /* If compression succeeds it must round trip correctly. */ - size_t const dstSize = - LZ4F_compressFrame(dst, dstCapacity, data, size, &prefs); - if (!LZ4F_isError(dstSize)) { - size_t const rtSize = FUZZ_decompressFrame(rt, size, dst, dstSize); - FUZZ_ASSERT_MSG(rtSize == size, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!"); - } - - free(dst); - free(rt); - FUZZ_dataProducer_free(producer); - - return 0; -} diff --git a/ta6ob/lz4/ossfuzz/compress_fuzzer.c b/ta6ob/lz4/ossfuzz/compress_fuzzer.c deleted file mode 100644 index edc8aad..0000000 --- a/ta6ob/lz4/ossfuzz/compress_fuzzer.c +++ /dev/null @@ -1,58 +0,0 @@ -/** - * This fuzz target attempts to compress the fuzzed data with the simple - * compression function with an output buffer that may be too small to - * ensure that the compressor never crashes. - */ - -#include -#include -#include -#include - -#include "fuzz_helpers.h" -#include "fuzz_data_producer.h" -#include "lz4.h" - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size); - size_t const dstCapacitySeed = FUZZ_dataProducer_retrieve32(producer); - size = FUZZ_dataProducer_remainingBytes(producer); - - size_t const compressBound = LZ4_compressBound(size); - size_t const dstCapacity = FUZZ_getRange_from_uint32(dstCapacitySeed, 0, compressBound); - - char* const dst = (char*)malloc(dstCapacity); - char* const rt = (char*)malloc(size); - - FUZZ_ASSERT(dst); - FUZZ_ASSERT(rt); - - /* If compression succeeds it must round trip correctly. */ - { - int const dstSize = LZ4_compress_default((const char*)data, dst, - size, dstCapacity); - if (dstSize > 0) { - int const rtSize = LZ4_decompress_safe(dst, rt, dstSize, size); - FUZZ_ASSERT_MSG(rtSize == size, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!"); - } - } - - if (dstCapacity > 0) { - /* Compression succeeds and must round trip correctly. */ - int compressedSize = size; - int const dstSize = LZ4_compress_destSize((const char*)data, dst, - &compressedSize, dstCapacity); - FUZZ_ASSERT(dstSize > 0); - int const rtSize = LZ4_decompress_safe(dst, rt, dstSize, size); - FUZZ_ASSERT_MSG(rtSize == compressedSize, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(data, rt, compressedSize), "Corruption!"); - } - - free(dst); - free(rt); - FUZZ_dataProducer_free(producer); - - return 0; -} diff --git a/ta6ob/lz4/ossfuzz/compress_hc_fuzzer.c b/ta6ob/lz4/ossfuzz/compress_hc_fuzzer.c deleted file mode 100644 index 7d8e45a..0000000 --- a/ta6ob/lz4/ossfuzz/compress_hc_fuzzer.c +++ /dev/null @@ -1,64 +0,0 @@ -/** - * This fuzz target attempts to compress the fuzzed data with the simple - * compression function with an output buffer that may be too small to - * ensure that the compressor never crashes. - */ - -#include -#include -#include -#include - -#include "fuzz_helpers.h" -#include "fuzz_data_producer.h" -#include "lz4.h" -#include "lz4hc.h" - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size); - size_t const dstCapacitySeed = FUZZ_dataProducer_retrieve32(producer); - size_t const levelSeed = FUZZ_dataProducer_retrieve32(producer); - size = FUZZ_dataProducer_remainingBytes(producer); - - size_t const dstCapacity = FUZZ_getRange_from_uint32(dstCapacitySeed, 0, size); - int const level = FUZZ_getRange_from_uint32(levelSeed, LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX); - - char* const dst = (char*)malloc(dstCapacity); - char* const rt = (char*)malloc(size); - - FUZZ_ASSERT(dst); - FUZZ_ASSERT(rt); - - /* If compression succeeds it must round trip correctly. */ - { - int const dstSize = LZ4_compress_HC((const char*)data, dst, size, - dstCapacity, level); - if (dstSize > 0) { - int const rtSize = LZ4_decompress_safe(dst, rt, dstSize, size); - FUZZ_ASSERT_MSG(rtSize == size, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!"); - } - } - - if (dstCapacity > 0) { - /* Compression succeeds and must round trip correctly. */ - void* state = malloc(LZ4_sizeofStateHC()); - FUZZ_ASSERT(state); - int compressedSize = size; - int const dstSize = LZ4_compress_HC_destSize(state, (const char*)data, - dst, &compressedSize, - dstCapacity, level); - FUZZ_ASSERT(dstSize > 0); - int const rtSize = LZ4_decompress_safe(dst, rt, dstSize, size); - FUZZ_ASSERT_MSG(rtSize == compressedSize, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(data, rt, compressedSize), "Corruption!"); - free(state); - } - - free(dst); - free(rt); - FUZZ_dataProducer_free(producer); - - return 0; -} diff --git a/ta6ob/lz4/ossfuzz/decompress_frame_fuzzer.c b/ta6ob/lz4/ossfuzz/decompress_frame_fuzzer.c deleted file mode 100644 index 0fcbb16..0000000 --- a/ta6ob/lz4/ossfuzz/decompress_frame_fuzzer.c +++ /dev/null @@ -1,75 +0,0 @@ -/** - * This fuzz target attempts to decompress the fuzzed data with the simple - * decompression function to ensure the decompressor never crashes. - */ - -#include -#include -#include -#include - -#include "fuzz_helpers.h" -#include "fuzz_data_producer.h" -#include "lz4.h" -#define LZ4F_STATIC_LINKING_ONLY -#include "lz4frame.h" -#include "lz4_helpers.h" - -static void decompress(LZ4F_dctx* dctx, void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const void* dict, size_t dictSize, - const LZ4F_decompressOptions_t* opts) -{ - LZ4F_resetDecompressionContext(dctx); - if (dictSize == 0) - LZ4F_decompress(dctx, dst, &dstCapacity, src, &srcSize, opts); - else - LZ4F_decompress_usingDict(dctx, dst, &dstCapacity, src, &srcSize, - dict, dictSize, opts); -} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size); - size_t const dstCapacitySeed = FUZZ_dataProducer_retrieve32(producer); - size_t const dictSizeSeed = FUZZ_dataProducer_retrieve32(producer); - size = FUZZ_dataProducer_remainingBytes(producer); - - size_t const dstCapacity = FUZZ_getRange_from_uint32( - dstCapacitySeed, 0, 4 * size); - size_t const largeDictSize = 64 * 1024; - size_t const dictSize = FUZZ_getRange_from_uint32( - dictSizeSeed, 0, largeDictSize); - - char* const dst = (char*)malloc(dstCapacity); - char* const dict = (char*)malloc(dictSize); - LZ4F_decompressOptions_t opts; - LZ4F_dctx* dctx; - LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION); - - FUZZ_ASSERT(dctx); - FUZZ_ASSERT(dst); - FUZZ_ASSERT(dict); - - /* Prepare the dictionary. The data doesn't matter for decompression. */ - memset(dict, 0, dictSize); - - - /* Decompress using multiple configurations. */ - memset(&opts, 0, sizeof(opts)); - opts.stableDst = 0; - decompress(dctx, dst, dstCapacity, data, size, NULL, 0, &opts); - opts.stableDst = 1; - decompress(dctx, dst, dstCapacity, data, size, NULL, 0, &opts); - opts.stableDst = 0; - decompress(dctx, dst, dstCapacity, data, size, dict, dictSize, &opts); - opts.stableDst = 1; - decompress(dctx, dst, dstCapacity, data, size, dict, dictSize, &opts); - - LZ4F_freeDecompressionContext(dctx); - free(dst); - free(dict); - FUZZ_dataProducer_free(producer); - - return 0; -} diff --git a/ta6ob/lz4/ossfuzz/decompress_fuzzer.c b/ta6ob/lz4/ossfuzz/decompress_fuzzer.c deleted file mode 100644 index 6f48e30..0000000 --- a/ta6ob/lz4/ossfuzz/decompress_fuzzer.c +++ /dev/null @@ -1,62 +0,0 @@ -/** - * This fuzz target attempts to decompress the fuzzed data with the simple - * decompression function to ensure the decompressor never crashes. - */ - -#include -#include -#include -#include - -#include "fuzz_helpers.h" -#include "fuzz_data_producer.h" -#include "lz4.h" - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size); - size_t const dstCapacitySeed = FUZZ_dataProducer_retrieve32(producer); - size = FUZZ_dataProducer_remainingBytes(producer); - - size_t const dstCapacity = FUZZ_getRange_from_uint32(dstCapacitySeed, 0, 4 * size); - size_t const smallDictSize = size + 1; - size_t const largeDictSize = 64 * 1024 - 1; - size_t const dictSize = MAX(smallDictSize, largeDictSize); - char* const dst = (char*)malloc(dstCapacity); - char* const dict = (char*)malloc(dictSize + size); - char* const largeDict = dict; - char* const dataAfterDict = dict + dictSize; - char* const smallDict = dataAfterDict - smallDictSize; - - FUZZ_ASSERT(dst); - FUZZ_ASSERT(dict); - - /* Prepare the dictionary. The data doesn't matter for decompression. */ - memset(dict, 0, dictSize); - memcpy(dataAfterDict, data, size); - - /* Decompress using each possible dictionary configuration. */ - /* No dictionary. */ - LZ4_decompress_safe_usingDict((char const*)data, dst, size, - dstCapacity, NULL, 0); - /* Small external dictonary. */ - LZ4_decompress_safe_usingDict((char const*)data, dst, size, - dstCapacity, smallDict, smallDictSize); - /* Large external dictionary. */ - LZ4_decompress_safe_usingDict((char const*)data, dst, size, - dstCapacity, largeDict, largeDictSize); - /* Small prefix. */ - LZ4_decompress_safe_usingDict((char const*)dataAfterDict, dst, size, - dstCapacity, smallDict, smallDictSize); - /* Large prefix. */ - LZ4_decompress_safe_usingDict((char const*)data, dst, size, - dstCapacity, largeDict, largeDictSize); - /* Partial decompression. */ - LZ4_decompress_safe_partial((char const*)data, dst, size, - dstCapacity, dstCapacity); - free(dst); - free(dict); - FUZZ_dataProducer_free(producer); - - return 0; -} diff --git a/ta6ob/lz4/ossfuzz/fuzz.h b/ta6ob/lz4/ossfuzz/fuzz.h deleted file mode 100644 index eefac63..0000000 --- a/ta6ob/lz4/ossfuzz/fuzz.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Fuzz target interface. - * Fuzz targets have some common parameters passed as macros during compilation. - * Check the documentation for each individual fuzzer for more parameters. - * - * @param FUZZ_RNG_SEED_SIZE: - * The number of bytes of the source to look at when constructing a seed - * for the deterministic RNG. These bytes are discarded before passing - * the data to lz4 functions. Every fuzzer initializes the RNG exactly - * once before doing anything else, even if it is unused. - * Default: 4. - * @param LZ4_DEBUG: - * This is a parameter for the lz4 library. Defining `LZ4_DEBUG=1` - * enables assert() statements in the lz4 library. Higher levels enable - * logging, so aren't recommended. Defining `LZ4_DEBUG=1` is - * recommended. - * @param LZ4_FORCE_MEMORY_ACCESS: - * This flag controls how the zstd library accesses unaligned memory. - * It can be undefined, or 0 through 2. If it is undefined, it selects - * the method to use based on the compiler. If testing with UBSAN set - * MEM_FORCE_MEMORY_ACCESS=0 to use the standard compliant method. - * @param FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - * This is the canonical flag to enable deterministic builds for fuzzing. - * Changes to zstd for fuzzing are gated behind this define. - * It is recommended to define this when building zstd for fuzzing. - */ - -#ifndef FUZZ_H -#define FUZZ_H - -#ifndef FUZZ_RNG_SEED_SIZE -# define FUZZ_RNG_SEED_SIZE 4 -#endif - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ta6ob/lz4/ossfuzz/fuzz_data_producer.c b/ta6ob/lz4/ossfuzz/fuzz_data_producer.c deleted file mode 100644 index 670fbf5..0000000 --- a/ta6ob/lz4/ossfuzz/fuzz_data_producer.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "fuzz_data_producer.h" - -struct FUZZ_dataProducer_s{ - const uint8_t *data; - size_t size; -}; - -FUZZ_dataProducer_t* FUZZ_dataProducer_create(const uint8_t* data, size_t size) { - FUZZ_dataProducer_t* const producer = malloc(sizeof(FUZZ_dataProducer_t)); - - FUZZ_ASSERT(producer != NULL); - - producer->data = data; - producer->size = size; - return producer; -} - -void FUZZ_dataProducer_free(FUZZ_dataProducer_t *producer) { free(producer); } - -uint32_t FUZZ_dataProducer_retrieve32(FUZZ_dataProducer_t *producer) { - const uint8_t* data = producer->data; - const size_t size = producer->size; - if (size == 0) { - return 0; - } else if (size < 4) { - producer->size -= 1; - return (uint32_t)data[size - 1]; - } else { - producer->size -= 4; - return *(data + size - 4); - } -} - -uint32_t FUZZ_getRange_from_uint32(uint32_t seed, uint32_t min, uint32_t max) -{ - uint32_t range = max - min; - if (range == 0xffffffff) { - return seed; - } - return min + seed % (range + 1); -} - -uint32_t FUZZ_dataProducer_range32(FUZZ_dataProducer_t* producer, - uint32_t min, uint32_t max) -{ - size_t const seed = FUZZ_dataProducer_retrieve32(producer); - return FUZZ_getRange_from_uint32(seed, min, max); -} - -LZ4F_frameInfo_t FUZZ_dataProducer_frameInfo(FUZZ_dataProducer_t* producer) -{ - LZ4F_frameInfo_t info = LZ4F_INIT_FRAMEINFO; - info.blockSizeID = FUZZ_dataProducer_range32(producer, LZ4F_max64KB - 1, LZ4F_max4MB); - if (info.blockSizeID < LZ4F_max64KB) { - info.blockSizeID = LZ4F_default; - } - info.blockMode = FUZZ_dataProducer_range32(producer, LZ4F_blockLinked, LZ4F_blockIndependent); - info.contentChecksumFlag = FUZZ_dataProducer_range32(producer, LZ4F_noContentChecksum, - LZ4F_contentChecksumEnabled); - info.blockChecksumFlag = FUZZ_dataProducer_range32(producer, LZ4F_noBlockChecksum, - LZ4F_blockChecksumEnabled); - return info; -} - -LZ4F_preferences_t FUZZ_dataProducer_preferences(FUZZ_dataProducer_t* producer) -{ - LZ4F_preferences_t prefs = LZ4F_INIT_PREFERENCES; - prefs.frameInfo = FUZZ_dataProducer_frameInfo(producer); - prefs.compressionLevel = FUZZ_dataProducer_range32(producer, 0, LZ4HC_CLEVEL_MAX + 3) - 3; - prefs.autoFlush = FUZZ_dataProducer_range32(producer, 0, 1); - prefs.favorDecSpeed = FUZZ_dataProducer_range32(producer, 0, 1); - return prefs; -} - -size_t FUZZ_dataProducer_remainingBytes(FUZZ_dataProducer_t *producer){ - return producer->size; -} diff --git a/ta6ob/lz4/ossfuzz/fuzz_data_producer.h b/ta6ob/lz4/ossfuzz/fuzz_data_producer.h deleted file mode 100644 index b96dcba..0000000 --- a/ta6ob/lz4/ossfuzz/fuzz_data_producer.h +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include - -#include "fuzz_helpers.h" -#include "lz4frame.h" -#include "lz4hc.h" - -/* Struct used for maintaining the state of the data */ -typedef struct FUZZ_dataProducer_s FUZZ_dataProducer_t; - -/* Returns a data producer state struct. Use for producer initialization. */ -FUZZ_dataProducer_t *FUZZ_dataProducer_create(const uint8_t *data, size_t size); - -/* Frees the data producer */ -void FUZZ_dataProducer_free(FUZZ_dataProducer_t *producer); - -/* Returns 32 bits from the end of data */ -uint32_t FUZZ_dataProducer_retrieve32(FUZZ_dataProducer_t *producer); - -/* Returns value between [min, max] */ -uint32_t FUZZ_getRange_from_uint32(uint32_t seed, uint32_t min, uint32_t max); - -/* Combination of above two functions for non adaptive use cases. ie where size is not involved */ -uint32_t FUZZ_dataProducer_range32(FUZZ_dataProducer_t *producer, uint32_t min, - uint32_t max); - -/* Returns lz4 preferences */ -LZ4F_preferences_t FUZZ_dataProducer_preferences(FUZZ_dataProducer_t* producer); - -/* Returns lz4 frame info */ -LZ4F_frameInfo_t FUZZ_dataProducer_frameInfo(FUZZ_dataProducer_t* producer); - -/* Returns the size of the remaining bytes of data in the producer */ -size_t FUZZ_dataProducer_remainingBytes(FUZZ_dataProducer_t *producer); diff --git a/ta6ob/lz4/ossfuzz/fuzz_helpers.h b/ta6ob/lz4/ossfuzz/fuzz_helpers.h deleted file mode 100644 index c4a8645..0000000 --- a/ta6ob/lz4/ossfuzz/fuzz_helpers.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - */ - -/** - * Helper functions for fuzzing. - */ - -#ifndef FUZZ_HELPERS_H -#define FUZZ_HELPERS_H - -#include "fuzz.h" -#include "xxhash.h" -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define LZ4_COMMONDEFS_ONLY -#ifndef LZ4_SRC_INCLUDED -#include "lz4.c" /* LZ4_count, constants, mem */ -#endif - -#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) -#define MAX(a,b) ( (a) > (b) ? (a) : (b) ) - -#define FUZZ_QUOTE_IMPL(str) #str -#define FUZZ_QUOTE(str) FUZZ_QUOTE_IMPL(str) - -/** - * Asserts for fuzzing that are always enabled. - */ -#define FUZZ_ASSERT_MSG(cond, msg) \ - ((cond) ? (void)0 \ - : (fprintf(stderr, "%s: %u: Assertion: `%s' failed. %s\n", __FILE__, \ - __LINE__, FUZZ_QUOTE(cond), (msg)), \ - abort())) -#define FUZZ_ASSERT(cond) FUZZ_ASSERT_MSG((cond), ""); - -#if defined(__GNUC__) -#define FUZZ_STATIC static __inline __attribute__((unused)) -#elif defined(__cplusplus) || \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -#define FUZZ_STATIC static inline -#elif defined(_MSC_VER) -#define FUZZ_STATIC static __inline -#else -#define FUZZ_STATIC static -#endif - -/** - * Deterministically constructs a seed based on the fuzz input. - * Consumes up to the first FUZZ_RNG_SEED_SIZE bytes of the input. - */ -FUZZ_STATIC uint32_t FUZZ_seed(uint8_t const **src, size_t* size) { - uint8_t const *data = *src; - size_t const toHash = MIN(FUZZ_RNG_SEED_SIZE, *size); - *size -= toHash; - *src += toHash; - return XXH32(data, toHash, 0); -} - -#define FUZZ_rotl32(x, r) (((x) << (r)) | ((x) >> (32 - (r)))) - -FUZZ_STATIC uint32_t FUZZ_rand(uint32_t *state) { - static const uint32_t prime1 = 2654435761U; - static const uint32_t prime2 = 2246822519U; - uint32_t rand32 = *state; - rand32 *= prime1; - rand32 += prime2; - rand32 = FUZZ_rotl32(rand32, 13); - *state = rand32; - return rand32 >> 5; -} - -/* Returns a random numer in the range [min, max]. */ -FUZZ_STATIC uint32_t FUZZ_rand32(uint32_t *state, uint32_t min, uint32_t max) { - uint32_t random = FUZZ_rand(state); - return min + (random % (max - min + 1)); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/ta6ob/lz4/ossfuzz/lz4_helpers.c b/ta6ob/lz4/ossfuzz/lz4_helpers.c deleted file mode 100644 index 9471630..0000000 --- a/ta6ob/lz4/ossfuzz/lz4_helpers.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "fuzz_helpers.h" -#include "lz4_helpers.h" -#include "lz4hc.h" - -LZ4F_frameInfo_t FUZZ_randomFrameInfo(uint32_t* seed) -{ - LZ4F_frameInfo_t info = LZ4F_INIT_FRAMEINFO; - info.blockSizeID = FUZZ_rand32(seed, LZ4F_max64KB - 1, LZ4F_max4MB); - if (info.blockSizeID < LZ4F_max64KB) { - info.blockSizeID = LZ4F_default; - } - info.blockMode = FUZZ_rand32(seed, LZ4F_blockLinked, LZ4F_blockIndependent); - info.contentChecksumFlag = FUZZ_rand32(seed, LZ4F_noContentChecksum, - LZ4F_contentChecksumEnabled); - info.blockChecksumFlag = FUZZ_rand32(seed, LZ4F_noBlockChecksum, - LZ4F_blockChecksumEnabled); - return info; -} - -LZ4F_preferences_t FUZZ_randomPreferences(uint32_t* seed) -{ - LZ4F_preferences_t prefs = LZ4F_INIT_PREFERENCES; - prefs.frameInfo = FUZZ_randomFrameInfo(seed); - prefs.compressionLevel = FUZZ_rand32(seed, 0, LZ4HC_CLEVEL_MAX + 3) - 3; - prefs.autoFlush = FUZZ_rand32(seed, 0, 1); - prefs.favorDecSpeed = FUZZ_rand32(seed, 0, 1); - return prefs; -} - -size_t FUZZ_decompressFrame(void* dst, const size_t dstCapacity, - const void* src, const size_t srcSize) -{ - LZ4F_decompressOptions_t opts; - memset(&opts, 0, sizeof(opts)); - opts.stableDst = 1; - LZ4F_dctx* dctx; - LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION); - FUZZ_ASSERT(dctx); - - size_t dstSize = dstCapacity; - size_t srcConsumed = srcSize; - size_t const rc = - LZ4F_decompress(dctx, dst, &dstSize, src, &srcConsumed, &opts); - FUZZ_ASSERT(!LZ4F_isError(rc)); - FUZZ_ASSERT(rc == 0); - FUZZ_ASSERT(srcConsumed == srcSize); - - LZ4F_freeDecompressionContext(dctx); - - return dstSize; -} diff --git a/ta6ob/lz4/ossfuzz/lz4_helpers.h b/ta6ob/lz4/ossfuzz/lz4_helpers.h deleted file mode 100644 index c99fb01..0000000 --- a/ta6ob/lz4/ossfuzz/lz4_helpers.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef LZ4_HELPERS -#define LZ4_HELPERS - -#include "lz4frame.h" - -LZ4F_frameInfo_t FUZZ_randomFrameInfo(uint32_t* seed); - -LZ4F_preferences_t FUZZ_randomPreferences(uint32_t* seed); - -size_t FUZZ_decompressFrame(void* dst, const size_t dstCapacity, - const void* src, const size_t srcSize); - -#endif /* LZ4_HELPERS */ diff --git a/ta6ob/lz4/ossfuzz/ossfuzz.sh b/ta6ob/lz4/ossfuzz/ossfuzz.sh deleted file mode 100755 index 9782286..0000000 --- a/ta6ob/lz4/ossfuzz/ossfuzz.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -eu - -# This script is called by the oss-fuzz main project when compiling the fuzz -# targets. This script is regression tested by travisoss.sh. - -# Save off the current folder as the build root. -export BUILD_ROOT=$PWD - -echo "CC: $CC" -echo "CXX: $CXX" -echo "LIB_FUZZING_ENGINE: $LIB_FUZZING_ENGINE" -echo "CFLAGS: $CFLAGS" -echo "CXXFLAGS: $CXXFLAGS" -echo "OUT: $OUT" - -export MAKEFLAGS+="-j$(nproc)" - -pushd ossfuzz -make V=1 all -popd - -# Copy the fuzzers to the target directory. -cp -v ossfuzz/*_fuzzer $OUT/ diff --git a/ta6ob/lz4/ossfuzz/round_trip_frame_fuzzer.c b/ta6ob/lz4/ossfuzz/round_trip_frame_fuzzer.c deleted file mode 100644 index 149542d..0000000 --- a/ta6ob/lz4/ossfuzz/round_trip_frame_fuzzer.c +++ /dev/null @@ -1,43 +0,0 @@ -/** - * This fuzz target performs a lz4 round-trip test (compress & decompress), - * compares the result with the original, and calls abort() on corruption. - */ - -#include -#include -#include -#include - -#include "fuzz_helpers.h" -#include "lz4.h" -#include "lz4frame.h" -#include "lz4_helpers.h" -#include "fuzz_data_producer.h" - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - FUZZ_dataProducer_t* producer = FUZZ_dataProducer_create(data, size); - LZ4F_preferences_t const prefs = FUZZ_dataProducer_preferences(producer); - size = FUZZ_dataProducer_remainingBytes(producer); - - size_t const dstCapacity = LZ4F_compressFrameBound(LZ4_compressBound(size), &prefs); - char* const dst = (char*)malloc(dstCapacity); - char* const rt = (char*)malloc(FUZZ_dataProducer_remainingBytes(producer)); - - FUZZ_ASSERT(dst); - FUZZ_ASSERT(rt); - - /* Compression must succeed and round trip correctly. */ - size_t const dstSize = - LZ4F_compressFrame(dst, dstCapacity, data, size, &prefs); - FUZZ_ASSERT(!LZ4F_isError(dstSize)); - size_t const rtSize = FUZZ_decompressFrame(rt, size, dst, dstSize); - FUZZ_ASSERT_MSG(rtSize == size, "Incorrect regenerated size"); - FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!"); - - free(dst); - free(rt); - FUZZ_dataProducer_free(producer); - - return 0; -} diff --git a/ta6ob/lz4/ossfuzz/round_trip_fuzzer.c b/ta6ob/lz4/ossfuzz/round_trip_fuzzer.c deleted file mode 100644 index 6307058..0000000 --- a/ta6ob/lz4/ossfuzz/round_trip_fuzzer.c +++ /dev/null @@ -1,57 +0,0 @@ -/** - * This fuzz target performs a lz4 round-trip test (compress & decompress), - * compares the result with the original, and calls abort() on corruption. - */ - -#include -#include -#include -#include - -#include "fuzz_helpers.h" -#include "lz4.h" -#include "fuzz_data_producer.h" - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size); - size_t const partialCapacitySeed = FUZZ_dataProducer_retrieve32(producer); - size = FUZZ_dataProducer_remainingBytes(producer); - - size_t const partialCapacity = FUZZ_getRange_from_uint32(partialCapacitySeed, 0, size); - size_t const dstCapacity = LZ4_compressBound(size); - - char* const dst = (char*)malloc(dstCapacity); - char* const rt = (char*)malloc(size); - - FUZZ_ASSERT(dst); - FUZZ_ASSERT(rt); - - /* Compression must succeed and round trip correctly. */ - int const dstSize = LZ4_compress_default((const char*)data, dst, - size, dstCapacity); - FUZZ_ASSERT(dstSize > 0); - - int const rtSize = LZ4_decompress_safe(dst, rt, dstSize, size); - FUZZ_ASSERT_MSG(rtSize == size, "Incorrect size"); - FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!"); - - /* Partial decompression must succeed. */ - { - char* const partial = (char*)malloc(partialCapacity); - FUZZ_ASSERT(partial); - int const partialSize = LZ4_decompress_safe_partial( - dst, partial, dstSize, partialCapacity, partialCapacity); - FUZZ_ASSERT(partialSize >= 0); - FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size"); - FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!"); - free(partial); - } - - - free(dst); - free(rt); - FUZZ_dataProducer_free(producer); - - return 0; -} diff --git a/ta6ob/lz4/ossfuzz/round_trip_hc_fuzzer.c b/ta6ob/lz4/ossfuzz/round_trip_hc_fuzzer.c deleted file mode 100644 index 7d03ee2..0000000 --- a/ta6ob/lz4/ossfuzz/round_trip_hc_fuzzer.c +++ /dev/null @@ -1,44 +0,0 @@ -/** - * This fuzz target performs a lz4 round-trip test (compress & decompress), - * compares the result with the original, and calls abort() on corruption. - */ - -#include -#include -#include -#include - -#include "fuzz_helpers.h" -#include "fuzz_data_producer.h" -#include "lz4.h" -#include "lz4hc.h" - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size); - int const level = FUZZ_dataProducer_range32(producer, - LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX); - size = FUZZ_dataProducer_remainingBytes(producer); - - size_t const dstCapacity = LZ4_compressBound(size); - char* const dst = (char*)malloc(dstCapacity); - char* const rt = (char*)malloc(size); - - FUZZ_ASSERT(dst); - FUZZ_ASSERT(rt); - - /* Compression must succeed and round trip correctly. */ - int const dstSize = LZ4_compress_HC((const char*)data, dst, size, - dstCapacity, level); - FUZZ_ASSERT(dstSize > 0); - - int const rtSize = LZ4_decompress_safe(dst, rt, dstSize, size); - FUZZ_ASSERT_MSG(rtSize == size, "Incorrect size"); - FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!"); - - free(dst); - free(rt); - FUZZ_dataProducer_free(producer); - - return 0; -} diff --git a/ta6ob/lz4/ossfuzz/round_trip_stream_fuzzer.c b/ta6ob/lz4/ossfuzz/round_trip_stream_fuzzer.c deleted file mode 100644 index abfcd2d..0000000 --- a/ta6ob/lz4/ossfuzz/round_trip_stream_fuzzer.c +++ /dev/null @@ -1,302 +0,0 @@ -/** - * This fuzz target performs a lz4 streaming round-trip test - * (compress & decompress), compares the result with the original, and calls - * abort() on corruption. - */ - -#include -#include -#include -#include - -#include "fuzz_helpers.h" -#define LZ4_STATIC_LINKING_ONLY -#include "lz4.h" -#define LZ4_HC_STATIC_LINKING_ONLY -#include "lz4hc.h" - -typedef struct { - char const* buf; - size_t size; - size_t pos; -} const_cursor_t; - -typedef struct { - char* buf; - size_t size; - size_t pos; -} cursor_t; - -typedef struct { - LZ4_stream_t* cstream; - LZ4_streamHC_t* cstreamHC; - LZ4_streamDecode_t* dstream; - const_cursor_t data; - cursor_t compressed; - cursor_t roundTrip; - uint32_t seed; - int level; -} state_t; - -cursor_t cursor_create(size_t size) -{ - cursor_t cursor; - cursor.buf = (char*)malloc(size); - cursor.size = size; - cursor.pos = 0; - FUZZ_ASSERT(cursor.buf); - return cursor; -} - -typedef void (*round_trip_t)(state_t* state); - -void cursor_free(cursor_t cursor) -{ - free(cursor.buf); -} - -state_t state_create(char const* data, size_t size, uint32_t seed) -{ - state_t state; - - state.seed = seed; - - state.data.buf = (char const*)data; - state.data.size = size; - state.data.pos = 0; - - /* Extra margin because we are streaming. */ - state.compressed = cursor_create(1024 + 2 * LZ4_compressBound(size)); - state.roundTrip = cursor_create(size); - - state.cstream = LZ4_createStream(); - FUZZ_ASSERT(state.cstream); - state.cstreamHC = LZ4_createStreamHC(); - FUZZ_ASSERT(state.cstream); - state.dstream = LZ4_createStreamDecode(); - FUZZ_ASSERT(state.dstream); - - return state; -} - -void state_free(state_t state) -{ - cursor_free(state.compressed); - cursor_free(state.roundTrip); - LZ4_freeStream(state.cstream); - LZ4_freeStreamHC(state.cstreamHC); - LZ4_freeStreamDecode(state.dstream); -} - -static void state_reset(state_t* state, uint32_t seed) -{ - state->level = FUZZ_rand32(&seed, LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX); - LZ4_resetStream_fast(state->cstream); - LZ4_resetStreamHC_fast(state->cstreamHC, state->level); - LZ4_setStreamDecode(state->dstream, NULL, 0); - state->data.pos = 0; - state->compressed.pos = 0; - state->roundTrip.pos = 0; - state->seed = seed; -} - -static void state_decompress(state_t* state, char const* src, int srcSize) -{ - char* dst = state->roundTrip.buf + state->roundTrip.pos; - int const dstCapacity = state->roundTrip.size - state->roundTrip.pos; - int const dSize = LZ4_decompress_safe_continue(state->dstream, src, dst, - srcSize, dstCapacity); - FUZZ_ASSERT(dSize >= 0); - state->roundTrip.pos += dSize; -} - -static void state_checkRoundTrip(state_t const* state) -{ - char const* data = state->data.buf; - size_t const size = state->data.size; - FUZZ_ASSERT_MSG(size == state->roundTrip.pos, "Incorrect size!"); - FUZZ_ASSERT_MSG(!memcmp(data, state->roundTrip.buf, size), "Corruption!"); -} - -/** - * Picks a dictionary size and trims the dictionary off of the data. - * We copy the dictionary to the roundTrip so our validation passes. - */ -static size_t state_trimDict(state_t* state) -{ - /* 64 KB is the max dict size, allow slightly beyond that to test trim. */ - uint32_t maxDictSize = MIN(70 * 1024, state->data.size); - size_t const dictSize = FUZZ_rand32(&state->seed, 0, maxDictSize); - DEBUGLOG(2, "dictSize = %zu", dictSize); - FUZZ_ASSERT(state->data.pos == 0); - FUZZ_ASSERT(state->roundTrip.pos == 0); - memcpy(state->roundTrip.buf, state->data.buf, dictSize); - state->data.pos += dictSize; - state->roundTrip.pos += dictSize; - return dictSize; -} - -static void state_prefixRoundTrip(state_t* state) -{ - while (state->data.pos != state->data.size) { - char const* src = state->data.buf + state->data.pos; - char* dst = state->compressed.buf + state->compressed.pos; - int const srcRemaining = state->data.size - state->data.pos; - int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining); - int const dstCapacity = state->compressed.size - state->compressed.pos; - int const cSize = LZ4_compress_fast_continue(state->cstream, src, dst, - srcSize, dstCapacity, 0); - FUZZ_ASSERT(cSize > 0); - state->data.pos += srcSize; - state->compressed.pos += cSize; - state_decompress(state, dst, cSize); - } -} - -static void state_extDictRoundTrip(state_t* state) -{ - int i = 0; - cursor_t data2 = cursor_create(state->data.size); - memcpy(data2.buf, state->data.buf, state->data.size); - while (state->data.pos != state->data.size) { - char const* data = (i++ & 1) ? state->data.buf : data2.buf; - char const* src = data + state->data.pos; - char* dst = state->compressed.buf + state->compressed.pos; - int const srcRemaining = state->data.size - state->data.pos; - int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining); - int const dstCapacity = state->compressed.size - state->compressed.pos; - int const cSize = LZ4_compress_fast_continue(state->cstream, src, dst, - srcSize, dstCapacity, 0); - FUZZ_ASSERT(cSize > 0); - state->data.pos += srcSize; - state->compressed.pos += cSize; - state_decompress(state, dst, cSize); - } - cursor_free(data2); -} - -static void state_randomRoundTrip(state_t* state, round_trip_t rt0, - round_trip_t rt1) -{ - if (FUZZ_rand32(&state->seed, 0, 1)) { - rt0(state); - } else { - rt1(state); - } -} - -static void state_loadDictRoundTrip(state_t* state) -{ - char const* dict = state->data.buf; - size_t const dictSize = state_trimDict(state); - LZ4_loadDict(state->cstream, dict, dictSize); - LZ4_setStreamDecode(state->dstream, dict, dictSize); - state_randomRoundTrip(state, state_prefixRoundTrip, state_extDictRoundTrip); -} - -static void state_attachDictRoundTrip(state_t* state) -{ - char const* dict = state->data.buf; - size_t const dictSize = state_trimDict(state); - LZ4_stream_t* dictStream = LZ4_createStream(); - LZ4_loadDict(dictStream, dict, dictSize); - LZ4_attach_dictionary(state->cstream, dictStream); - LZ4_setStreamDecode(state->dstream, dict, dictSize); - state_randomRoundTrip(state, state_prefixRoundTrip, state_extDictRoundTrip); - LZ4_freeStream(dictStream); -} - -static void state_prefixHCRoundTrip(state_t* state) -{ - while (state->data.pos != state->data.size) { - char const* src = state->data.buf + state->data.pos; - char* dst = state->compressed.buf + state->compressed.pos; - int const srcRemaining = state->data.size - state->data.pos; - int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining); - int const dstCapacity = state->compressed.size - state->compressed.pos; - int const cSize = LZ4_compress_HC_continue(state->cstreamHC, src, dst, - srcSize, dstCapacity); - FUZZ_ASSERT(cSize > 0); - state->data.pos += srcSize; - state->compressed.pos += cSize; - state_decompress(state, dst, cSize); - } -} - -static void state_extDictHCRoundTrip(state_t* state) -{ - int i = 0; - cursor_t data2 = cursor_create(state->data.size); - DEBUGLOG(2, "extDictHC"); - memcpy(data2.buf, state->data.buf, state->data.size); - while (state->data.pos != state->data.size) { - char const* data = (i++ & 1) ? state->data.buf : data2.buf; - char const* src = data + state->data.pos; - char* dst = state->compressed.buf + state->compressed.pos; - int const srcRemaining = state->data.size - state->data.pos; - int const srcSize = FUZZ_rand32(&state->seed, 0, srcRemaining); - int const dstCapacity = state->compressed.size - state->compressed.pos; - int const cSize = LZ4_compress_HC_continue(state->cstreamHC, src, dst, - srcSize, dstCapacity); - FUZZ_ASSERT(cSize > 0); - DEBUGLOG(2, "srcSize = %d", srcSize); - state->data.pos += srcSize; - state->compressed.pos += cSize; - state_decompress(state, dst, cSize); - } - cursor_free(data2); -} - -static void state_loadDictHCRoundTrip(state_t* state) -{ - char const* dict = state->data.buf; - size_t const dictSize = state_trimDict(state); - LZ4_loadDictHC(state->cstreamHC, dict, dictSize); - LZ4_setStreamDecode(state->dstream, dict, dictSize); - state_randomRoundTrip(state, state_prefixHCRoundTrip, - state_extDictHCRoundTrip); -} - -static void state_attachDictHCRoundTrip(state_t* state) -{ - char const* dict = state->data.buf; - size_t const dictSize = state_trimDict(state); - LZ4_streamHC_t* dictStream = LZ4_createStreamHC(); - LZ4_setCompressionLevel(dictStream, state->level); - LZ4_loadDictHC(dictStream, dict, dictSize); - LZ4_attach_HC_dictionary(state->cstreamHC, dictStream); - LZ4_setStreamDecode(state->dstream, dict, dictSize); - state_randomRoundTrip(state, state_prefixHCRoundTrip, - state_extDictHCRoundTrip); - LZ4_freeStreamHC(dictStream); -} - -round_trip_t roundTrips[] = { - &state_prefixRoundTrip, - &state_extDictRoundTrip, - &state_loadDictRoundTrip, - &state_attachDictRoundTrip, - &state_prefixHCRoundTrip, - &state_extDictHCRoundTrip, - &state_loadDictHCRoundTrip, - &state_attachDictHCRoundTrip, -}; - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - uint32_t seed = FUZZ_seed(&data, &size); - state_t state = state_create((char const*)data, size, seed); - const int n = sizeof(roundTrips) / sizeof(round_trip_t); - int i; - - for (i = 0; i < n; ++i) { - DEBUGLOG(2, "Round trip %d", i); - state_reset(&state, seed); - roundTrips[i](&state); - state_checkRoundTrip(&state); - } - - state_free(state); - - return 0; -} diff --git a/ta6ob/lz4/ossfuzz/standaloneengine.c b/ta6ob/lz4/ossfuzz/standaloneengine.c deleted file mode 100644 index 6afeffd..0000000 --- a/ta6ob/lz4/ossfuzz/standaloneengine.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include - -#include "fuzz.h" - -/** - * Main procedure for standalone fuzzing engine. - * - * Reads filenames from the argument array. For each filename, read the file - * into memory and then call the fuzzing interface with the data. - */ -int main(int argc, char **argv) -{ - int ii; - for(ii = 1; ii < argc; ii++) - { - FILE *infile; - printf("[%s] ", argv[ii]); - - /* Try and open the file. */ - infile = fopen(argv[ii], "rb"); - if(infile) - { - uint8_t *buffer = NULL; - size_t buffer_len; - - printf("Opened.. "); - - /* Get the length of the file. */ - fseek(infile, 0L, SEEK_END); - buffer_len = ftell(infile); - - /* Reset the file indicator to the beginning of the file. */ - fseek(infile, 0L, SEEK_SET); - - /* Allocate a buffer for the file contents. */ - buffer = (uint8_t *)calloc(buffer_len, sizeof(uint8_t)); - if(buffer) - { - /* Read all the text from the file into the buffer. */ - fread(buffer, sizeof(uint8_t), buffer_len, infile); - printf("Read %zu bytes, fuzzing.. ", buffer_len); - - /* Call the fuzzer with the data. */ - LLVMFuzzerTestOneInput(buffer, buffer_len); - - printf("complete !!"); - - /* Free the buffer as it's no longer needed. */ - free(buffer); - buffer = NULL; - } - else - { - fprintf(stderr, - "[%s] Failed to allocate %zu bytes \n", - argv[ii], - buffer_len); - } - - /* Close the file as it's no longer needed. */ - fclose(infile); - infile = NULL; - } - else - { - /* Failed to open the file. Maybe wrong name or wrong permissions? */ - fprintf(stderr, "[%s] Open failed. \n", argv[ii]); - } - - printf("\n"); - } -} diff --git a/ta6ob/lz4/ossfuzz/travisoss.sh b/ta6ob/lz4/ossfuzz/travisoss.sh deleted file mode 100755 index eae9a80..0000000 --- a/ta6ob/lz4/ossfuzz/travisoss.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -set -ex - -# Clone the oss-fuzz repository -git clone https://github.com/google/oss-fuzz.git /tmp/ossfuzz - -if [[ ! -d /tmp/ossfuzz/projects/lz4 ]] -then - echo "Could not find the lz4 project in ossfuzz" - exit 1 -fi - -# Modify the oss-fuzz Dockerfile so that we're checking out the current branch on travis. -if [ "x${TRAVIS_PULL_REQUEST}" = "xfalse" ] -then - sed -i "s@https://github.com/lz4/lz4.git@-b ${TRAVIS_BRANCH} https://github.com/lz4/lz4.git@" /tmp/ossfuzz/projects/lz4/Dockerfile -else - sed -i "s@https://github.com/lz4/lz4.git@-b ${TRAVIS_PULL_REQUEST_BRANCH} https://github.com/${TRAVIS_PULL_REQUEST_SLUG}.git@" /tmp/ossfuzz/projects/lz4/Dockerfile -fi - -# Try and build the fuzzers -pushd /tmp/ossfuzz -python infra/helper.py build_image --pull lz4 -python infra/helper.py build_fuzzers lz4 -popd diff --git a/ta6ob/lz4/programs/.gitignore b/ta6ob/lz4/programs/.gitignore deleted file mode 100644 index 9ffadd9..0000000 --- a/ta6ob/lz4/programs/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# local binary (Makefile) -lz4 -unlz4 -lz4cat -lz4c -lz4c32 -lz4-wlib -datagen -frametest -frametest32 -fullbench -fullbench32 -fuzzer -fuzzer32 -*.exe - -# tests files -tmp* - -# artefacts -*.dSYM diff --git a/ta6ob/lz4/programs/COPYING b/ta6ob/lz4/programs/COPYING deleted file mode 100644 index d159169..0000000 --- a/ta6ob/lz4/programs/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/ta6ob/lz4/programs/Makefile b/ta6ob/lz4/programs/Makefile deleted file mode 100644 index c1053f6..0000000 --- a/ta6ob/lz4/programs/Makefile +++ /dev/null @@ -1,187 +0,0 @@ -# ########################################################################## -# LZ4 programs - Makefile -# Copyright (C) Yann Collet 2011-2017 -# -# This Makefile is validated for Linux, macOS, *BSD, Hurd, Solaris, MSYS2 targets -# -# GPL v2 License -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# You can contact the author at : -# - LZ4 homepage : http://www.lz4.org -# - LZ4 source repository : https://github.com/lz4/lz4 -# ########################################################################## -# lz4 : Command Line Utility, supporting gzip-like arguments -# lz4c : CLU, supporting also legacy lz4demo arguments -# lz4c32: Same as lz4c, but forced to compile in 32-bits mode -# ########################################################################## - -# Version numbers -LZ4DIR := ../lib -LIBVER_SRC := $(LZ4DIR)/lz4.h -LIBVER_MAJOR_SCRIPT:=`sed -n '/define LZ4_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)` -LIBVER_MINOR_SCRIPT:=`sed -n '/define LZ4_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)` -LIBVER_PATCH_SCRIPT:=`sed -n '/define LZ4_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < $(LIBVER_SRC)` -LIBVER_SCRIPT:= $(LIBVER_MAJOR_SCRIPT).$(LIBVER_MINOR_SCRIPT).$(LIBVER_PATCH_SCRIPT) -LIBVER_MAJOR := $(shell echo $(LIBVER_MAJOR_SCRIPT)) -LIBVER_MINOR := $(shell echo $(LIBVER_MINOR_SCRIPT)) -LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT)) -LIBVER := $(shell echo $(LIBVER_SCRIPT)) - -LIBFILES = $(wildcard $(LZ4DIR)/*.c) -SRCFILES = $(sort $(LIBFILES) $(wildcard *.c)) -OBJFILES = $(SRCFILES:.c=.o) - -CPPFLAGS += -I$(LZ4DIR) -DXXH_NAMESPACE=LZ4_ -CFLAGS ?= -O3 -DEBUGFLAGS= -Wall -Wextra -Wundef -Wcast-qual -Wcast-align -Wshadow \ - -Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes \ - -Wpointer-arith -Wstrict-aliasing=1 -CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) -FLAGS = $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) - -LZ4_VERSION=$(LIBVER) -MD2ROFF = ronn -MD2ROFF_FLAGS = --roff --warnings --manual="User Commands" --organization="lz4 $(LZ4_VERSION)" - -include ../Makefile.inc - -default: lz4-release - -all: lz4 lz4c - -all32: CFLAGS+=-m32 -all32: all - -ifeq ($(WINBASED),yes) -lz4-exe.rc: lz4-exe.rc.in - @echo creating executable resource - $(Q)sed -e 's|@PROGNAME@|lz4|' \ - -e 's|@LIBVER_MAJOR@|$(LIBVER_MAJOR)|g' \ - -e 's|@LIBVER_MINOR@|$(LIBVER_MINOR)|g' \ - -e 's|@LIBVER_PATCH@|$(LIBVER_PATCH)|g' \ - -e 's|@EXT@|$(EXT)|g' \ - $< >$@ - -lz4-exe.o: lz4-exe.rc - $(WINDRES) -i lz4-exe.rc -o lz4-exe.o - -lz4: $(OBJFILES) lz4-exe.o - $(CC) $(FLAGS) $^ -o $@$(EXT) -else -lz4: $(OBJFILES) - $(CC) $(FLAGS) $(OBJFILES) -o $@$(EXT) $(LDLIBS) -endif - -.PHONY: lz4-release -lz4-release: DEBUGFLAGS= -lz4-release: lz4 - -lz4-wlib: LIBFILES = -lz4-wlib: SRCFILES+= $(LZ4DIR)/xxhash.c # benchmark unit needs XXH64() -lz4-wlib: LDFLAGS += -L $(LZ4DIR) -lz4-wlib: LDLIBS = -llz4 -lz4-wlib: liblz4 $(OBJFILES) - @echo WARNING: $@ must link to an extended variant of the dynamic library which also exposes unstable symbols - $(CC) $(FLAGS) $(OBJFILES) -o $@$(EXT) $(LDLIBS) - -.PHONY:liblz4 -liblz4: - CPPFLAGS="-DLZ4F_PUBLISH_STATIC_FUNCTIONS -DLZ4_PUBLISH_STATIC_FUNCTIONS" $(MAKE) -C $(LZ4DIR) liblz4 - -lz4c: lz4 - $(LN_SF) lz4$(EXT) lz4c$(EXT) - -lz4c32: CFLAGS += -m32 -lz4c32 : $(SRCFILES) - $(CC) $(FLAGS) $^ -o $@$(EXT) - -lz4.1: lz4.1.md $(LIBVER_SRC) - cat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | sed -n '/^\.\\\".*/!p' > $@ - -man: lz4.1 - -clean-man: - $(RM) lz4.1 - -preview-man: clean-man man - man ./lz4.1 - -clean: -ifeq ($(WINBASED),yes) - $(Q)$(RM) *.rc -endif - @$(MAKE) -C $(LZ4DIR) $@ > $(VOID) - @$(RM) core *.o *.test tmp* \ - lz4$(EXT) lz4c$(EXT) lz4c32$(EXT) lz4-wlib$(EXT) \ - unlz4$(EXT) lz4cat$(EXT) - @echo Cleaning completed - - -#----------------------------------------------------------------------------- -# make install is validated only for Linux, OSX, BSD, Hurd and Solaris targets -#----------------------------------------------------------------------------- -ifeq ($(POSIX_ENV),Yes) - -unlz4: lz4 - $(LN_SF) lz4$(EXT) unlz4$(EXT) - -lz4cat: lz4 - $(LN_SF) lz4$(EXT) lz4cat$(EXT) - -DESTDIR ?= -# directory variables : GNU conventions prefer lowercase -# see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html -# support both lower and uppercase (BSD), use lowercase in script -PREFIX ?= /usr/local -prefix ?= $(PREFIX) -EXEC_PREFIX ?= $(prefix) -exec_prefix ?= $(EXEC_PREFIX) -BINDIR ?= $(exec_prefix)/bin -bindir ?= $(BINDIR) -DATAROOTDIR ?= $(prefix)/share -datarootdir ?= $(DATAROOTDIR) -MANDIR ?= $(datarootdir)/man -mandir ?= $(MANDIR) -MAN1DIR ?= $(mandir)/man1 -man1dir ?= $(MAN1DIR) - -install: lz4 - @echo Installing binaries - @$(INSTALL_DIR) $(DESTDIR)$(bindir)/ $(DESTDIR)$(man1dir)/ - @$(INSTALL_PROGRAM) lz4$(EXT) $(DESTDIR)$(bindir)/lz4$(EXT) - @$(LN_S) lz4$(EXT) $(DESTDIR)$(bindir)/lz4c$(EXT) - @$(LN_S) lz4$(EXT) $(DESTDIR)$(bindir)/lz4cat$(EXT) - @$(LN_S) lz4$(EXT) $(DESTDIR)$(bindir)/unlz4$(EXT) - @echo Installing man pages - @$(INSTALL_DATA) lz4.1 $(DESTDIR)$(man1dir)/lz4.1 - @$(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4c.1 - @$(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/lz4cat.1 - @$(LN_SF) lz4.1 $(DESTDIR)$(man1dir)/unlz4.1 - @echo lz4 installation completed - -uninstall: - @$(RM) $(DESTDIR)$(bindir)/lz4cat$(EXT) - @$(RM) $(DESTDIR)$(bindir)/unlz4$(EXT) - @$(RM) $(DESTDIR)$(bindir)/lz4$(EXT) - @$(RM) $(DESTDIR)$(bindir)/lz4c$(EXT) - @$(RM) $(DESTDIR)$(man1dir)/lz4.1 - @$(RM) $(DESTDIR)$(man1dir)/lz4c.1 - @$(RM) $(DESTDIR)$(man1dir)/lz4cat.1 - @$(RM) $(DESTDIR)$(man1dir)/unlz4.1 - @echo lz4 programs successfully uninstalled - -endif diff --git a/ta6ob/lz4/programs/README.md b/ta6ob/lz4/programs/README.md deleted file mode 100644 index c1995af..0000000 --- a/ta6ob/lz4/programs/README.md +++ /dev/null @@ -1,84 +0,0 @@ -Command Line Interface for LZ4 library -============================================ - -### Build -The Command Line Interface (CLI) can be generated -using the `make` command without any additional parameters. - -The `Makefile` script supports all [standard conventions](https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html), -including standard targets (`all`, `install`, `clean`, etc.) -and standard variables (`CC`, `CFLAGS`, `CPPFLAGS`, etc.). - -For advanced use cases, there are targets to different variations of the CLI: -- `lz4` : default CLI, with a command line syntax close to gzip -- `lz4c` : Same as `lz4` with additional support legacy lz4 commands (incompatible with gzip) -- `lz4c32` : Same as `lz4c`, but forced to compile in 32-bits mode - -The CLI generates and decodes [LZ4-compressed frames](../doc/lz4_Frame_format.md). - - -#### Aggregation of parameters -CLI supports aggregation of parameters i.e. `-b1`, `-e18`, and `-i1` can be joined into `-b1e18i1`. - - -#### Benchmark in Command Line Interface -CLI includes in-memory compression benchmark module for lz4. -The benchmark is conducted using a given filename. -The file is read into memory. -It makes benchmark more precise as it eliminates I/O overhead. - -The benchmark measures ratio, compressed size, compression and decompression speed. -One can select compression levels starting from `-b` and ending with `-e`. -The `-i` parameter selects a number of seconds used for each of tested levels. - - - -#### Usage of Command Line Interface -The full list of commands can be obtained with `-h` or `-H` parameter: -``` -Usage : - lz4 [arg] [input] [output] - -input : a filename - with no FILE, or when FILE is - or stdin, read standard input -Arguments : - -1 : Fast compression (default) - -9 : High compression - -d : decompression (default for .lz4 extension) - -z : force compression - -D FILE: use FILE as dictionary - -f : overwrite output without prompting - -k : preserve source files(s) (default) ---rm : remove source file(s) after successful de/compression - -h/-H : display help/long help and exit - -Advanced arguments : - -V : display Version number and exit - -v : verbose mode - -q : suppress warnings; specify twice to suppress errors too - -c : force write to standard output, even if it is the console - -t : test compressed file integrity - -m : multiple input files (implies automatic output filenames) - -r : operate recursively on directories (sets also -m) - -l : compress using Legacy format (Linux kernel compression) - -B# : cut file into blocks of size # bytes [32+] - or predefined block size [4-7] (default: 7) - -BD : Block dependency (improve compression ratio) - -BX : enable block checksum (default:disabled) ---no-frame-crc : disable stream checksum (default:enabled) ---content-size : compressed frame includes original size (default:not present) ---[no-]sparse : sparse mode (default:enabled on file, disabled on stdout) ---favor-decSpeed: compressed files decompress faster, but are less compressed ---fast[=#]: switch to ultra fast compression level (default: 1) - -Benchmark arguments : - -b# : benchmark file(s), using # compression level (default : 1) - -e# : test all compression levels from -bX to # (default : 1) - -i# : minimum evaluation time in seconds (default : 3s)``` -``` - -#### License - -All files in this directory are licensed under GPL-v2. -See [COPYING](COPYING) for details. -The text of the license is also included at the top of each source file. diff --git a/ta6ob/lz4/programs/bench.c b/ta6ob/lz4/programs/bench.c deleted file mode 100644 index 3357d14..0000000 --- a/ta6ob/lz4/programs/bench.c +++ /dev/null @@ -1,746 +0,0 @@ -/* - bench.c - Demo program to benchmark open-source compression algorithms - Copyright (C) Yann Collet 2012-2016 - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 homepage : http://www.lz4.org - - LZ4 source repository : https://github.com/lz4/lz4 -*/ - - -/*-************************************ -* Compiler options -**************************************/ -#ifdef _MSC_VER /* Visual Studio */ -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#endif - - -/* ************************************* -* Includes -***************************************/ -#include "platform.h" /* Compiler options */ -#include "util.h" /* UTIL_GetFileSize, UTIL_sleep */ -#include /* malloc, free */ -#include /* memset */ -#include /* fprintf, fopen, ftello */ -#include /* clock_t, clock, CLOCKS_PER_SEC */ -#include /* assert */ - -#include "datagen.h" /* RDG_genBuffer */ -#include "xxhash.h" -#include "bench.h" - -#define LZ4_STATIC_LINKING_ONLY -#include "lz4.h" -#define LZ4_HC_STATIC_LINKING_ONLY -#include "lz4hc.h" - - -/* ************************************* -* Compression parameters and functions -***************************************/ - -struct compressionParameters -{ - int cLevel; - const char* dictBuf; - int dictSize; - - LZ4_stream_t* LZ4_stream; - LZ4_stream_t* LZ4_dictStream; - LZ4_streamHC_t* LZ4_streamHC; - LZ4_streamHC_t* LZ4_dictStreamHC; - - void (*initFunction)( - struct compressionParameters* pThis); - void (*resetFunction)( - const struct compressionParameters* pThis); - int (*blockFunction)( - const struct compressionParameters* pThis, - const char* src, char* dst, int srcSize, int dstSize); - void (*cleanupFunction)( - const struct compressionParameters* pThis); -}; - -static void LZ4_compressInitNoStream( - struct compressionParameters* pThis) -{ - pThis->LZ4_stream = NULL; - pThis->LZ4_dictStream = NULL; - pThis->LZ4_streamHC = NULL; - pThis->LZ4_dictStreamHC = NULL; -} - -static void LZ4_compressInitStream( - struct compressionParameters* pThis) -{ - pThis->LZ4_stream = LZ4_createStream(); - pThis->LZ4_dictStream = LZ4_createStream(); - pThis->LZ4_streamHC = NULL; - pThis->LZ4_dictStreamHC = NULL; - LZ4_loadDict(pThis->LZ4_dictStream, pThis->dictBuf, pThis->dictSize); -} - -static void LZ4_compressInitStreamHC( - struct compressionParameters* pThis) -{ - pThis->LZ4_stream = NULL; - pThis->LZ4_dictStream = NULL; - pThis->LZ4_streamHC = LZ4_createStreamHC(); - pThis->LZ4_dictStreamHC = LZ4_createStreamHC(); - LZ4_loadDictHC(pThis->LZ4_dictStreamHC, pThis->dictBuf, pThis->dictSize); -} - -static void LZ4_compressResetNoStream( - const struct compressionParameters* pThis) -{ - (void)pThis; -} - -static void LZ4_compressResetStream( - const struct compressionParameters* pThis) -{ - LZ4_resetStream_fast(pThis->LZ4_stream); - LZ4_attach_dictionary(pThis->LZ4_stream, pThis->LZ4_dictStream); -} - -static void LZ4_compressResetStreamHC( - const struct compressionParameters* pThis) -{ - LZ4_resetStreamHC_fast(pThis->LZ4_streamHC, pThis->cLevel); - LZ4_attach_HC_dictionary(pThis->LZ4_streamHC, pThis->LZ4_dictStreamHC); -} - -static int LZ4_compressBlockNoStream( - const struct compressionParameters* pThis, - const char* src, char* dst, - int srcSize, int dstSize) -{ - int const acceleration = (pThis->cLevel < 0) ? -pThis->cLevel + 1 : 1; - return LZ4_compress_fast(src, dst, srcSize, dstSize, acceleration); -} - -static int LZ4_compressBlockNoStreamHC( - const struct compressionParameters* pThis, - const char* src, char* dst, - int srcSize, int dstSize) -{ - return LZ4_compress_HC(src, dst, srcSize, dstSize, pThis->cLevel); -} - -static int LZ4_compressBlockStream( - const struct compressionParameters* pThis, - const char* src, char* dst, - int srcSize, int dstSize) -{ - int const acceleration = (pThis->cLevel < 0) ? -pThis->cLevel + 1 : 1; - return LZ4_compress_fast_continue(pThis->LZ4_stream, src, dst, srcSize, dstSize, acceleration); -} - -static int LZ4_compressBlockStreamHC( - const struct compressionParameters* pThis, - const char* src, char* dst, - int srcSize, int dstSize) -{ - return LZ4_compress_HC_continue(pThis->LZ4_streamHC, src, dst, srcSize, dstSize); -} - -static void LZ4_compressCleanupNoStream( - const struct compressionParameters* pThis) -{ - (void)pThis; -} - -static void LZ4_compressCleanupStream( - const struct compressionParameters* pThis) -{ - LZ4_freeStream(pThis->LZ4_stream); - LZ4_freeStream(pThis->LZ4_dictStream); -} - -static void LZ4_compressCleanupStreamHC( - const struct compressionParameters* pThis) -{ - LZ4_freeStreamHC(pThis->LZ4_streamHC); - LZ4_freeStreamHC(pThis->LZ4_dictStreamHC); -} - -static void LZ4_buildCompressionParameters( - struct compressionParameters* pParams, - int cLevel, const char* dictBuf, int dictSize) -{ - pParams->cLevel = cLevel; - pParams->dictBuf = dictBuf; - pParams->dictSize = dictSize; - - if (dictSize) { - if (cLevel < LZ4HC_CLEVEL_MIN) { - pParams->initFunction = LZ4_compressInitStream; - pParams->resetFunction = LZ4_compressResetStream; - pParams->blockFunction = LZ4_compressBlockStream; - pParams->cleanupFunction = LZ4_compressCleanupStream; - } else { - pParams->initFunction = LZ4_compressInitStreamHC; - pParams->resetFunction = LZ4_compressResetStreamHC; - pParams->blockFunction = LZ4_compressBlockStreamHC; - pParams->cleanupFunction = LZ4_compressCleanupStreamHC; - } - } else { - pParams->initFunction = LZ4_compressInitNoStream; - pParams->resetFunction = LZ4_compressResetNoStream; - pParams->cleanupFunction = LZ4_compressCleanupNoStream; - - if (cLevel < LZ4HC_CLEVEL_MIN) { - pParams->blockFunction = LZ4_compressBlockNoStream; - } else { - pParams->blockFunction = LZ4_compressBlockNoStreamHC; - } - } -} - -#define LZ4_isError(errcode) (errcode==0) - - -/* ************************************* -* Constants -***************************************/ -#ifndef LZ4_GIT_COMMIT_STRING -# define LZ4_GIT_COMMIT_STRING "" -#else -# define LZ4_GIT_COMMIT_STRING LZ4_EXPAND_AND_QUOTE(LZ4_GIT_COMMIT) -#endif - -#define NBSECONDS 3 -#define TIMELOOP_MICROSEC 1*1000000ULL /* 1 second */ -#define TIMELOOP_NANOSEC 1*1000000000ULL /* 1 second */ -#define ACTIVEPERIOD_MICROSEC 70*1000000ULL /* 70 seconds */ -#define COOLPERIOD_SEC 10 -#define DECOMP_MULT 1 /* test decompression DECOMP_MULT times longer than compression */ - -#define KB *(1 <<10) -#define MB *(1 <<20) -#define GB *(1U<<30) - -#define LZ4_MAX_DICT_SIZE (64 KB) - -static const size_t maxMemory = (sizeof(size_t)==4) ? (2 GB - 64 MB) : (size_t)(1ULL << ((sizeof(size_t)*8)-31)); - -static U32 g_compressibilityDefault = 50; - - -/* ************************************* -* console display -***************************************/ -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } -static U32 g_displayLevel = 2; /* 0 : no display; 1: errors; 2 : + result + interaction + warnings; 3 : + progression; 4 : + information */ - -#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \ - if ((clock() - g_time > refreshRate) || (g_displayLevel>=4)) \ - { g_time = clock(); DISPLAY(__VA_ARGS__); \ - if (g_displayLevel>=4) fflush(stdout); } } -static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100; -static clock_t g_time = 0; - - -/* ************************************* -* Exceptions -***************************************/ -#ifndef DEBUG -# define DEBUG 0 -#endif -#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); -#define EXM_THROW(error, ...) \ -{ \ - DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ - DISPLAYLEVEL(1, "Error %i : ", error); \ - DISPLAYLEVEL(1, __VA_ARGS__); \ - DISPLAYLEVEL(1, "\n"); \ - exit(error); \ -} - - -/* ************************************* -* Benchmark Parameters -***************************************/ -static U32 g_nbSeconds = NBSECONDS; -static size_t g_blockSize = 0; -int g_additionalParam = 0; -int g_benchSeparately = 0; - -void BMK_setNotificationLevel(unsigned level) { g_displayLevel=level; } - -void BMK_setAdditionalParam(int additionalParam) { g_additionalParam=additionalParam; } - -void BMK_setNbSeconds(unsigned nbSeconds) -{ - g_nbSeconds = nbSeconds; - DISPLAYLEVEL(3, "- test >= %u seconds per compression / decompression -\n", g_nbSeconds); -} - -void BMK_setBlockSize(size_t blockSize) { g_blockSize = blockSize; } - -void BMK_setBenchSeparately(int separate) { g_benchSeparately = (separate!=0); } - - -/* ******************************************************** -* Bench functions -**********************************************************/ -typedef struct { - const char* srcPtr; - size_t srcSize; - char* cPtr; - size_t cRoom; - size_t cSize; - char* resPtr; - size_t resSize; -} blockParam_t; - -#define MIN(a,b) ((a)<(b) ? (a) : (b)) -#define MAX(a,b) ((a)>(b) ? (a) : (b)) - -static int BMK_benchMem(const void* srcBuffer, size_t srcSize, - const char* displayName, int cLevel, - const size_t* fileSizes, U32 nbFiles, - const char* dictBuf, int dictSize) -{ - size_t const blockSize = (g_blockSize>=32 ? g_blockSize : srcSize) + (!srcSize) /* avoid div by 0 */ ; - U32 const maxNbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize) + nbFiles; - blockParam_t* const blockTable = (blockParam_t*) malloc(maxNbBlocks * sizeof(blockParam_t)); - size_t const maxCompressedSize = LZ4_compressBound((int)srcSize) + (maxNbBlocks * 1024); /* add some room for safety */ - void* const compressedBuffer = malloc(maxCompressedSize); - void* const resultBuffer = malloc(srcSize); - U32 nbBlocks; - struct compressionParameters compP; - - /* checks */ - if (!compressedBuffer || !resultBuffer || !blockTable) - EXM_THROW(31, "allocation error : not enough memory"); - - if (strlen(displayName)>17) displayName += strlen(displayName)-17; /* can only display 17 characters */ - - /* init */ - LZ4_buildCompressionParameters(&compP, cLevel, dictBuf, dictSize); - compP.initFunction(&compP); - - /* Init blockTable data */ - { const char* srcPtr = (const char*)srcBuffer; - char* cPtr = (char*)compressedBuffer; - char* resPtr = (char*)resultBuffer; - U32 fileNb; - for (nbBlocks=0, fileNb=0; fileNb ACTIVEPERIOD_MICROSEC) { - DISPLAYLEVEL(2, "\rcooling down ... \r"); - UTIL_sleep(COOLPERIOD_SEC); - coolTime = UTIL_getTime(); - } - - /* Compression */ - DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->\r", marks[markNb], displayName, (U32)srcSize); - if (!cCompleted) memset(compressedBuffer, 0xE5, maxCompressedSize); /* warm up and erase result buffer */ - - UTIL_sleepMilli(1); /* give processor time to other processes */ - UTIL_waitForNextTick(); - - if (!cCompleted) { /* still some time to do compression tests */ - UTIL_time_t const clockStart = UTIL_getTime(); - U32 nbLoops; - for (nbLoops=0; nbLoops < nbCompressionLoops; nbLoops++) { - U32 blockNb; - compP.resetFunction(&compP); - for (blockNb=0; blockNb 0) { - if (clockSpan < fastestC * nbCompressionLoops) - fastestC = clockSpan / nbCompressionLoops; - assert(fastestC > 0); - nbCompressionLoops = (U32)(TIMELOOP_NANOSEC / fastestC) + 1; /* aim for ~1sec */ - } else { - assert(nbCompressionLoops < 40000000); /* avoid overflow */ - nbCompressionLoops *= 100; - } - totalCTime += clockSpan; - cCompleted = totalCTime>maxTime; - } } - - cSize = 0; - { U32 blockNb; for (blockNb=0; blockNb%10u (%5.3f),%6.1f MB/s\r", - marks[markNb], displayName, (U32)srcSize, (U32)cSize, ratio, - ((double)srcSize / fastestC) * 1000 ); - - (void)fastestD; (void)crcOrig; /* unused when decompression disabled */ -#if 1 - /* Decompression */ - if (!dCompleted) memset(resultBuffer, 0xD6, srcSize); /* warm result buffer */ - - UTIL_sleepMilli(5); /* give processor time to other processes */ - UTIL_waitForNextTick(); - - if (!dCompleted) { - UTIL_time_t const clockStart = UTIL_getTime(); - U32 nbLoops; - for (nbLoops=0; nbLoops < nbDecodeLoops; nbLoops++) { - U32 blockNb; - for (blockNb=0; blockNb 0) { - if (clockSpan < fastestD * nbDecodeLoops) - fastestD = clockSpan / nbDecodeLoops; - assert(fastestD > 0); - nbDecodeLoops = (U32)(TIMELOOP_NANOSEC / fastestD) + 1; /* aim for ~1sec */ - } else { - assert(nbDecodeLoops < 40000000); /* avoid overflow */ - nbDecodeLoops *= 100; - } - totalDTime += clockSpan; - dCompleted = totalDTime > (DECOMP_MULT*maxTime); - } } - - markNb = (markNb+1) % NB_MARKS; - DISPLAYLEVEL(2, "%2s-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s ,%6.1f MB/s\r", - marks[markNb], displayName, (U32)srcSize, (U32)cSize, ratio, - ((double)srcSize / fastestC) * 1000, - ((double)srcSize / fastestD) * 1000); - - /* CRC Checking */ - { U64 const crcCheck = XXH64(resultBuffer, srcSize, 0); - if (crcOrig!=crcCheck) { - size_t u; - DISPLAY("\n!!! WARNING !!! %17s : Invalid Checksum : %x != %x \n", displayName, (unsigned)crcOrig, (unsigned)crcCheck); - for (u=0; u u) break; - bacc += blockTable[segNb].srcSize; - } - pos = (U32)(u - bacc); - bNb = pos / (128 KB); - DISPLAY("(block %u, sub %u, pos %u) \n", segNb, bNb, pos); - break; - } - if (u==srcSize-1) { /* should never happen */ - DISPLAY("no difference detected\n"); - } } - break; - } } /* CRC Checking */ -#endif - } /* for (testNb = 1; testNb <= (g_nbSeconds + !g_nbSeconds); testNb++) */ - - if (g_displayLevel == 1) { - double const cSpeed = ((double)srcSize / fastestC) * 1000; - double const dSpeed = ((double)srcSize / fastestD) * 1000; - if (g_additionalParam) - DISPLAY("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s (param=%d)\n", cLevel, (int)cSize, ratio, cSpeed, dSpeed, displayName, g_additionalParam); - else - DISPLAY("-%-3i%11i (%5.3f) %6.2f MB/s %6.1f MB/s %s\n", cLevel, (int)cSize, ratio, cSpeed, dSpeed, displayName); - } - DISPLAYLEVEL(2, "%2i#\n", cLevel); - } /* Bench */ - - /* clean up */ - compP.cleanupFunction(&compP); - free(blockTable); - free(compressedBuffer); - free(resultBuffer); - return 0; -} - - -static size_t BMK_findMaxMem(U64 requiredMem) -{ - size_t step = 64 MB; - BYTE* testmem=NULL; - - requiredMem = (((requiredMem >> 26) + 1) << 26); - requiredMem += 2*step; - if (requiredMem > maxMemory) requiredMem = maxMemory; - - while (!testmem) { - if (requiredMem > step) requiredMem -= step; - else requiredMem >>= 1; - testmem = (BYTE*) malloc ((size_t)requiredMem); - } - free (testmem); - - /* keep some space available */ - if (requiredMem > step) requiredMem -= step; - else requiredMem >>= 1; - - return (size_t)requiredMem; -} - - -static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize, - const char* displayName, int cLevel, int cLevelLast, - const size_t* fileSizes, unsigned nbFiles, - const char* dictBuf, int dictSize) -{ - int l; - - const char* pch = strrchr(displayName, '\\'); /* Windows */ - if (!pch) pch = strrchr(displayName, '/'); /* Linux */ - if (pch) displayName = pch+1; - - SET_REALTIME_PRIORITY; - - if (g_displayLevel == 1 && !g_additionalParam) - DISPLAY("bench %s %s: input %u bytes, %u seconds, %u KB blocks\n", LZ4_VERSION_STRING, LZ4_GIT_COMMIT_STRING, (U32)benchedSize, g_nbSeconds, (U32)(g_blockSize>>10)); - - if (cLevelLast < cLevel) cLevelLast = cLevel; - - for (l=cLevel; l <= cLevelLast; l++) { - BMK_benchMem(srcBuffer, benchedSize, - displayName, l, - fileSizes, nbFiles, - dictBuf, dictSize); - } -} - - -/*! BMK_loadFiles() : - Loads `buffer` with content of files listed within `fileNamesTable`. - At most, fills `buffer` entirely */ -static void BMK_loadFiles(void* buffer, size_t bufferSize, - size_t* fileSizes, - const char** fileNamesTable, unsigned nbFiles) -{ - size_t pos = 0, totalSize = 0; - unsigned n; - for (n=0; n bufferSize-pos) { /* buffer too small - stop after this file */ - fileSize = bufferSize-pos; - nbFiles=n; - } - { size_t const readSize = fread(((char*)buffer)+pos, 1, (size_t)fileSize, f); - if (readSize != (size_t)fileSize) EXM_THROW(11, "could not read %s", fileNamesTable[n]); - pos += readSize; } - fileSizes[n] = (size_t)fileSize; - totalSize += (size_t)fileSize; - fclose(f); - } - - if (totalSize == 0) EXM_THROW(12, "no data to bench"); -} - -static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles, - int cLevel, int cLevelLast, - const char* dictBuf, int dictSize) -{ - void* srcBuffer; - size_t benchedSize; - size_t* fileSizes = (size_t*)malloc(nbFiles * sizeof(size_t)); - U64 const totalSizeToLoad = UTIL_getTotalFileSize(fileNamesTable, nbFiles); - char mfName[20] = {0}; - - if (!fileSizes) EXM_THROW(12, "not enough memory for fileSizes"); - - /* Memory allocation & restrictions */ - benchedSize = BMK_findMaxMem(totalSizeToLoad * 3) / 3; - if (benchedSize==0) EXM_THROW(12, "not enough memory"); - if ((U64)benchedSize > totalSizeToLoad) benchedSize = (size_t)totalSizeToLoad; - if (benchedSize > LZ4_MAX_INPUT_SIZE) { - benchedSize = LZ4_MAX_INPUT_SIZE; - DISPLAY("File(s) bigger than LZ4's max input size; testing %u MB only...\n", (U32)(benchedSize >> 20)); - } else { - if (benchedSize < totalSizeToLoad) - DISPLAY("Not enough memory; testing %u MB only...\n", (U32)(benchedSize >> 20)); - } - srcBuffer = malloc(benchedSize + !benchedSize); /* avoid alloc of zero */ - if (!srcBuffer) EXM_THROW(12, "not enough memory"); - - /* Load input buffer */ - BMK_loadFiles(srcBuffer, benchedSize, fileSizes, fileNamesTable, nbFiles); - - /* Bench */ - snprintf (mfName, sizeof(mfName), " %u files", nbFiles); - { const char* displayName = (nbFiles > 1) ? mfName : fileNamesTable[0]; - BMK_benchCLevel(srcBuffer, benchedSize, - displayName, cLevel, cLevelLast, - fileSizes, nbFiles, - dictBuf, dictSize); - } - - /* clean up */ - free(srcBuffer); - free(fileSizes); -} - - -static void BMK_syntheticTest(int cLevel, int cLevelLast, double compressibility, - const char* dictBuf, int dictSize) -{ - char name[20] = {0}; - size_t benchedSize = 10000000; - void* const srcBuffer = malloc(benchedSize); - - /* Memory allocation */ - if (!srcBuffer) EXM_THROW(21, "not enough memory"); - - /* Fill input buffer */ - RDG_genBuffer(srcBuffer, benchedSize, compressibility, 0.0, 0); - - /* Bench */ - snprintf (name, sizeof(name), "Synthetic %2u%%", (unsigned)(compressibility*100)); - BMK_benchCLevel(srcBuffer, benchedSize, name, cLevel, cLevelLast, &benchedSize, 1, dictBuf, dictSize); - - /* clean up */ - free(srcBuffer); -} - - -int BMK_benchFilesSeparately(const char** fileNamesTable, unsigned nbFiles, - int cLevel, int cLevelLast, - const char* dictBuf, int dictSize) -{ - unsigned fileNb; - if (cLevel > LZ4HC_CLEVEL_MAX) cLevel = LZ4HC_CLEVEL_MAX; - if (cLevelLast > LZ4HC_CLEVEL_MAX) cLevelLast = LZ4HC_CLEVEL_MAX; - if (cLevelLast < cLevel) cLevelLast = cLevel; - if (cLevelLast > cLevel) DISPLAYLEVEL(2, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast); - - for (fileNb=0; fileNb LZ4HC_CLEVEL_MAX) cLevel = LZ4HC_CLEVEL_MAX; - if (cLevelLast > LZ4HC_CLEVEL_MAX) cLevelLast = LZ4HC_CLEVEL_MAX; - if (cLevelLast < cLevel) cLevelLast = cLevel; - if (cLevelLast > cLevel) DISPLAYLEVEL(2, "Benchmarking levels from %d to %d\n", cLevel, cLevelLast); - - if (dictFileName) { - FILE* dictFile = NULL; - U64 dictFileSize = UTIL_getFileSize(dictFileName); - if (!dictFileSize) EXM_THROW(25, "Dictionary error : could not stat dictionary file"); - - dictFile = fopen(dictFileName, "rb"); - if (!dictFile) EXM_THROW(25, "Dictionary error : could not open dictionary file"); - - if (dictFileSize > LZ4_MAX_DICT_SIZE) { - dictSize = LZ4_MAX_DICT_SIZE; - if (UTIL_fseek(dictFile, dictFileSize - dictSize, SEEK_SET)) - EXM_THROW(25, "Dictionary error : could not seek dictionary file"); - } else { - dictSize = (int)dictFileSize; - } - - dictBuf = (char *)malloc(dictSize); - if (!dictBuf) EXM_THROW(25, "Allocation error : not enough memory"); - - if (fread(dictBuf, 1, dictSize, dictFile) != (size_t)dictSize) - EXM_THROW(25, "Dictionary error : could not read dictionary file"); - - fclose(dictFile); - } - - if (nbFiles == 0) - BMK_syntheticTest(cLevel, cLevelLast, compressibility, dictBuf, dictSize); - else { - if (g_benchSeparately) - BMK_benchFilesSeparately(fileNamesTable, nbFiles, cLevel, cLevelLast, dictBuf, dictSize); - else - BMK_benchFileTable(fileNamesTable, nbFiles, cLevel, cLevelLast, dictBuf, dictSize); - } - - free(dictBuf); - return 0; -} diff --git a/ta6ob/lz4/programs/bench.h b/ta6ob/lz4/programs/bench.h deleted file mode 100644 index 22ebf60..0000000 --- a/ta6ob/lz4/programs/bench.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - bench.h - Demo program to benchmark open-source compression algorithm - Copyright (C) Yann Collet 2012-2016 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ -#ifndef BENCH_H_125623623633 -#define BENCH_H_125623623633 - -#include - -int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles, - int cLevel, int cLevelLast, - const char* dictFileName); - -/* Set Parameters */ -void BMK_setNbSeconds(unsigned nbLoops); -void BMK_setBlockSize(size_t blockSize); -void BMK_setAdditionalParam(int additionalParam); -void BMK_setNotificationLevel(unsigned level); -void BMK_setBenchSeparately(int separate); - -#endif /* BENCH_H_125623623633 */ diff --git a/ta6ob/lz4/programs/datagen.c b/ta6ob/lz4/programs/datagen.c deleted file mode 100644 index 24a2da2..0000000 --- a/ta6ob/lz4/programs/datagen.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - datagen.c - compressible data generator test tool - Copyright (C) Yann Collet 2012-2016 - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - Public forum : https://groups.google.com/forum/#!forum/lz4c -*/ - -/************************************** -* Includes -**************************************/ -#include "platform.h" /* Compiler options, SET_BINARY_MODE */ -#include "util.h" /* U32 */ -#include /* malloc */ -#include /* FILE, fwrite */ -#include /* memcpy */ -#include - - -/************************************** -* Constants -**************************************/ -#define KB *(1 <<10) - -#define PRIME1 2654435761U -#define PRIME2 2246822519U - - -/************************************** -* Local types -**************************************/ -#define LTLOG 13 -#define LTSIZE (1<> (32 - r))) -static unsigned int RDG_rand(U32* src) -{ - U32 rand32 = *src; - rand32 *= PRIME1; - rand32 ^= PRIME2; - rand32 = RDG_rotl32(rand32, 13); - *src = rand32; - return rand32; -} - - -static void RDG_fillLiteralDistrib(litDistribTable lt, double ld) -{ - BYTE const firstChar = ld <= 0.0 ? 0 : '('; - BYTE const lastChar = ld <= 0.0 ? 255 : '}'; - BYTE character = ld <= 0.0 ? 0 : '0'; - U32 u = 0; - - while (u lastChar) character = firstChar; - } -} - - -static BYTE RDG_genChar(U32* seed, const litDistribTable lt) -{ - U32 id = RDG_rand(seed) & LTMASK; - return (lt[id]); -} - - -#define RDG_DICTSIZE (32 KB) -#define RDG_RAND15BITS ((RDG_rand(seed) >> 3) & 32767) -#define RDG_RANDLENGTH ( ((RDG_rand(seed) >> 7) & 7) ? (RDG_rand(seed) & 15) : (RDG_rand(seed) & 511) + 15) -void RDG_genBlock(void* buffer, size_t buffSize, size_t prefixSize, double matchProba, litDistribTable lt, unsigned* seedPtr) -{ - BYTE* buffPtr = (BYTE*)buffer; - const U32 matchProba32 = (U32)(32768 * matchProba); - size_t pos = prefixSize; - U32* seed = seedPtr; - - /* special case */ - while (matchProba >= 1.0) { - size_t size0 = RDG_rand(seed) & 3; - size0 = (size_t)1 << (16 + size0 * 2); - size0 += RDG_rand(seed) & (size0-1); /* because size0 is power of 2*/ - if (buffSize < pos + size0) { - memset(buffPtr+pos, 0, buffSize-pos); - return; - } - memset(buffPtr+pos, 0, size0); - pos += size0; - buffPtr[pos-1] = RDG_genChar(seed, lt); - } - - /* init */ - if (pos==0) { - buffPtr[0] = RDG_genChar(seed, lt); - pos=1; - } - - /* Generate compressible data */ - while (pos < buffSize) { - /* Select : Literal (char) or Match (within 32K) */ - if (RDG_RAND15BITS < matchProba32) { - /* Copy (within 32K) */ - size_t match; - size_t d; - int length = RDG_RANDLENGTH + 4; - U32 offset = RDG_RAND15BITS + 1; - if (offset > pos) offset = (U32)pos; - match = pos - offset; - d = pos + length; - if (d > buffSize) d = buffSize; - while (pos < d) buffPtr[pos++] = buffPtr[match++]; - } else { - /* Literal (noise) */ - size_t d; - size_t length = RDG_RANDLENGTH; - d = pos + length; - if (d > buffSize) d = buffSize; - while (pos < d) buffPtr[pos++] = RDG_genChar(seed, lt); - } - } -} - - -void RDG_genBuffer(void* buffer, size_t size, double matchProba, double litProba, unsigned seed) -{ - litDistribTable lt; - if (litProba==0.0) litProba = matchProba / 4.5; - RDG_fillLiteralDistrib(lt, litProba); - RDG_genBlock(buffer, size, 0, matchProba, lt, &seed); -} - - -#define RDG_BLOCKSIZE (128 KB) -void RDG_genOut(unsigned long long size, double matchProba, double litProba, unsigned seed) -{ - BYTE buff[RDG_DICTSIZE + RDG_BLOCKSIZE]; - U64 total = 0; - size_t genBlockSize = RDG_BLOCKSIZE; - litDistribTable lt; - - /* init */ - if (litProba==0.0) litProba = matchProba / 4.5; - RDG_fillLiteralDistrib(lt, litProba); - SET_BINARY_MODE(stdout); - - /* Generate dict */ - RDG_genBlock(buff, RDG_DICTSIZE, 0, matchProba, lt, &seed); - - /* Generate compressible data */ - while (total < size) { - RDG_genBlock(buff, RDG_DICTSIZE+RDG_BLOCKSIZE, RDG_DICTSIZE, matchProba, lt, &seed); - if (size-total < RDG_BLOCKSIZE) genBlockSize = (size_t)(size-total); - total += genBlockSize; - fwrite(buff, 1, genBlockSize, stdout); /* should check potential write error */ - /* update dict */ - memcpy(buff, buff + RDG_BLOCKSIZE, RDG_DICTSIZE); - } -} diff --git a/ta6ob/lz4/programs/datagen.h b/ta6ob/lz4/programs/datagen.h deleted file mode 100644 index 91c5b02..0000000 --- a/ta6ob/lz4/programs/datagen.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - datagen.h - compressible data generator header - Copyright (C) Yann Collet 2012-2016 - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - Public forum : https://groups.google.com/forum/#!forum/lz4c -*/ - - -#include /* size_t */ - -void RDG_genOut(unsigned long long size, double matchProba, double litProba, unsigned seed); -void RDG_genBuffer(void* buffer, size_t size, double matchProba, double litProba, unsigned seed); -/* RDG_genOut - Generate 'size' bytes of compressible data into stdout. - Compressibility can be controlled using 'matchProba'. - 'LitProba' is optional, and affect variability of bytes. If litProba==0.0, default value is used. - Generated data can be selected using 'seed'. - If (matchProba, litProba and seed) are equal, the function always generate the same content. - - RDG_genBuffer - Same as RDG_genOut, but generate data into provided buffer -*/ diff --git a/ta6ob/lz4/programs/lz4-exe.rc.in b/ta6ob/lz4/programs/lz4-exe.rc.in deleted file mode 100644 index 7b81030..0000000 --- a/ta6ob/lz4/programs/lz4-exe.rc.in +++ /dev/null @@ -1,27 +0,0 @@ -1 VERSIONINFO -FILEVERSION @LIBVER_MAJOR@,@LIBVER_MINOR@,@LIBVER_PATCH@,0 -PRODUCTVERSION @LIBVER_MAJOR@,@LIBVER_MINOR@,@LIBVER_PATCH@,0 -FILEFLAGSMASK 0 -FILEOS 0x40000 -FILETYPE 1 -{ - BLOCK "StringFileInfo" - { - BLOCK "040904B0" - { - VALUE "CompanyName", "Yann Collet" - VALUE "FileDescription", "Extremely fast compression" - VALUE "FileVersion", "@LIBVER_MAJOR@.@LIBVER_MINOR@.@LIBVER_PATCH@.0" - VALUE "InternalName", "@PROGNAME@" - VALUE "LegalCopyright", "Copyright (C) 2013-2016, Yann Collet" - VALUE "OriginalFilename", "@PROGNAME@.@EXT@" - VALUE "ProductName", "LZ4" - VALUE "ProductVersion", "@LIBVER_MAJOR@.@LIBVER_MINOR@.@LIBVER_PATCH@.0" - } - } - BLOCK "VarFileInfo" - { - VALUE "Translation", 0x0409, 1200 - } -} - diff --git a/ta6ob/lz4/programs/lz4.1 b/ta6ob/lz4/programs/lz4.1 deleted file mode 100644 index d758ed5..0000000 --- a/ta6ob/lz4/programs/lz4.1 +++ /dev/null @@ -1,241 +0,0 @@ -. -.TH "LZ4" "1" "July 2019" "lz4 1.9.2" "User Commands" -. -.SH "NAME" -\fBlz4\fR \- lz4, unlz4, lz4cat \- Compress or decompress \.lz4 files -. -.SH "SYNOPSIS" -\fBlz4\fR [\fIOPTIONS\fR] [\-|INPUT\-FILE] \fIOUTPUT\-FILE\fR -. -.P -\fBunlz4\fR is equivalent to \fBlz4 \-d\fR -. -.P -\fBlz4cat\fR is equivalent to \fBlz4 \-dcfm\fR -. -.P -When writing scripts that need to decompress files, it is recommended to always use the name \fBlz4\fR with appropriate arguments (\fBlz4 \-d\fR or \fBlz4 \-dc\fR) instead of the names \fBunlz4\fR and \fBlz4cat\fR\. -. -.SH "DESCRIPTION" -\fBlz4\fR is an extremely fast lossless compression algorithm, based on \fBbyte\-aligned LZ77\fR family of compression scheme\. \fBlz4\fR offers compression speeds of 400 MB/s per core, linearly scalable with multi\-core CPUs\. It features an extremely fast decoder, with speed in multiple GB/s per core, typically reaching RAM speed limit on multi\-core systems\. The native file format is the \fB\.lz4\fR format\. -. -.SS "Difference between lz4 and gzip" -\fBlz4\fR supports a command line syntax similar \fIbut not identical\fR to \fBgzip(1)\fR\. Differences are : -. -.IP "\(bu" 4 -\fBlz4\fR compresses a single file by default (see \fB\-m\fR for multiple files) -. -.IP "\(bu" 4 -\fBlz4 file1 file2\fR means : compress file1 \fIinto\fR file2 -. -.IP "\(bu" 4 -\fBlz4 file\.lz4\fR will default to decompression (use \fB\-z\fR to force compression) -. -.IP "\(bu" 4 -\fBlz4\fR preserves original files -. -.IP "\(bu" 4 -\fBlz4\fR shows real\-time notification statistics during compression or decompression of a single file (use \fB\-q\fR to silence them) -. -.IP "\(bu" 4 -When no destination is specified, result is sent on implicit output, which depends on \fBstdout\fR status\. When \fBstdout\fR \fIis Not the console\fR, it becomes the implicit output\. Otherwise, if \fBstdout\fR is the console, the implicit output is \fBfilename\.lz4\fR\. -. -.IP "\(bu" 4 -It is considered bad practice to rely on implicit output in scripts\. because the script\'s environment may change\. Always use explicit output in scripts\. \fB\-c\fR ensures that output will be \fBstdout\fR\. Conversely, providing a destination name, or using \fB\-m\fR ensures that the output will be either the specified name, or \fBfilename\.lz4\fR respectively\. -. -.IP "" 0 -. -.P -Default behaviors can be modified by opt\-in commands, detailed below\. -. -.IP "\(bu" 4 -\fBlz4 \-m\fR makes it possible to provide multiple input filenames, which will be compressed into files using suffix \fB\.lz4\fR\. Progress notifications become disabled by default (use \fB\-v\fR to enable them)\. This mode has a behavior which more closely mimics \fBgzip\fR command line, with the main remaining difference being that source files are preserved by default\. -. -.IP "\(bu" 4 -Similarly, \fBlz4 \-m \-d\fR can decompress multiple \fB*\.lz4\fR files\. -. -.IP "\(bu" 4 -It\'s possible to opt\-in to erase source files on successful compression or decompression, using \fB\-\-rm\fR command\. -. -.IP "\(bu" 4 -Consequently, \fBlz4 \-m \-\-rm\fR behaves the same as \fBgzip\fR\. -. -.IP "" 0 -. -.SS "Concatenation of \.lz4 files" -It is possible to concatenate \fB\.lz4\fR files as is\. \fBlz4\fR will decompress such files as if they were a single \fB\.lz4\fR file\. For example: -. -.IP "" 4 -. -.nf - -lz4 file1 > foo\.lz4 -lz4 file2 >> foo\.lz4 -. -.fi -. -.IP "" 0 -. -.P -Then \fBlz4cat foo\.lz4\fR is equivalent to \fBcat file1 file2\fR\. -. -.SH "OPTIONS" -. -.SS "Short commands concatenation" -In some cases, some options can be expressed using short command \fB\-x\fR or long command \fB\-\-long\-word\fR\. Short commands can be concatenated together\. For example, \fB\-d \-c\fR is equivalent to \fB\-dc\fR\. Long commands cannot be concatenated\. They must be clearly separated by a space\. -. -.SS "Multiple commands" -When multiple contradictory commands are issued on a same command line, only the latest one will be applied\. -. -.SS "Operation mode" -. -.TP -\fB\-z\fR \fB\-\-compress\fR -Compress\. This is the default operation mode when no operation mode option is specified, no other operation mode is implied from the command name (for example, \fBunlz4\fR implies \fB\-\-decompress\fR), nor from the input file name (for example, a file extension \fB\.lz4\fR implies \fB\-\-decompress\fR by default)\. \fB\-z\fR can also be used to force compression of an already compressed \fB\.lz4\fR file\. -. -.TP -\fB\-d\fR \fB\-\-decompress\fR \fB\-\-uncompress\fR -Decompress\. \fB\-\-decompress\fR is also the default operation when the input filename has an \fB\.lz4\fR extension\. -. -.TP -\fB\-t\fR \fB\-\-test\fR -Test the integrity of compressed \fB\.lz4\fR files\. The decompressed data is discarded\. No files are created nor removed\. -. -.TP -\fB\-b#\fR -Benchmark mode, using \fB#\fR compression level\. -. -.TP -\fB\-\-list\fR -List information about \.lz4 files\. note : current implementation is limited to single\-frame \.lz4 files\. -. -.SS "Operation modifiers" -. -.TP -\fB\-#\fR -Compression level, with # being any value from 1 to 12\. Higher values trade compression speed for compression ratio\. Values above 12 are considered the same as 12\. Recommended values are 1 for fast compression (default), and 9 for high compression\. Speed/compression trade\-off will vary depending on data to compress\. Decompression speed remains fast at all settings\. -. -.TP -\fB\-\-fast[=#]\fR -Switch to ultra\-fast compression levels\. The higher the value, the faster the compression speed, at the cost of some compression ratio\. If \fB=#\fR is not present, it defaults to \fB1\fR\. This setting overrides compression level if one was set previously\. Similarly, if a compression level is set after \fB\-\-fast\fR, it overrides it\. -. -.TP -\fB\-\-best\fR -Set highest compression level\. Same as -12\. -. -.TP -\fB\-\-favor\-decSpeed\fR -Generate compressed data optimized for decompression speed\. Compressed data will be larger as a consequence (typically by ~0\.5%), while decompression speed will be improved by 5\-20%, depending on use cases\. This option only works in combination with very high compression levels (>=10)\. -. -.TP -\fB\-D dictionaryName\fR -Compress, decompress or benchmark using dictionary \fIdictionaryName\fR\. Compression and decompression must use the same dictionary to be compatible\. Using a different dictionary during decompression will either abort due to decompression error, or generate a checksum error\. -. -.TP -\fB\-f\fR \fB\-\-[no\-]force\fR -This option has several effects: -. -.IP -If the target file already exists, overwrite it without prompting\. -. -.IP -When used with \fB\-\-decompress\fR and \fBlz4\fR cannot recognize the type of the source file, copy the source file as is to standard output\. This allows \fBlz4cat \-\-force\fR to be used like \fBcat (1)\fR for files that have not been compressed with \fBlz4\fR\. -. -.TP -\fB\-c\fR \fB\-\-stdout\fR \fB\-\-to\-stdout\fR -Force write to standard output, even if it is the console\. -. -.TP -\fB\-m\fR \fB\-\-multiple\fR -Multiple input files\. Compressed file names will be appended a \fB\.lz4\fR suffix\. This mode also reduces notification level\. Can also be used to list multiple files\. \fBlz4 \-m\fR has a behavior equivalent to \fBgzip \-k\fR (it preserves source files by default)\. -. -.TP -\fB\-r\fR -operate recursively on directories\. This mode also sets \fB\-m\fR (multiple input files)\. -. -.TP -\fB\-B#\fR -Block size [4\-7](default : 7) -. -.br -\fB\-B4\fR= 64KB ; \fB\-B5\fR= 256KB ; \fB\-B6\fR= 1MB ; \fB\-B7\fR= 4MB -. -.TP -\fB\-BI\fR -Produce independent blocks (default) -. -.TP -\fB\-BD\fR -Blocks depend on predecessors (improves compression ratio, more noticeable on small blocks) -. -.TP -\fB\-\-[no\-]frame\-crc\fR -Select frame checksum (default:enabled) -. -.TP -\fB\-\-[no\-]content\-size\fR -Header includes original size (default:not present) -. -.br -Note : this option can only be activated when the original size can be determined, hence for a file\. It won\'t work with unknown source size, such as stdin or pipe\. -. -.TP -\fB\-\-[no\-]sparse\fR -Sparse mode support (default:enabled on file, disabled on stdout) -. -.TP -\fB\-l\fR -Use Legacy format (typically for Linux Kernel compression) -. -.br -Note : \fB\-l\fR is not compatible with \fB\-m\fR (\fB\-\-multiple\fR) nor \fB\-r\fR -. -.SS "Other options" -. -.TP -\fB\-v\fR \fB\-\-verbose\fR -Verbose mode -. -.TP -\fB\-q\fR \fB\-\-quiet\fR -Suppress warnings and real\-time statistics; specify twice to suppress errors too -. -.TP -\fB\-h\fR \fB\-H\fR \fB\-\-help\fR -Display help/long help and exit -. -.TP -\fB\-V\fR \fB\-\-version\fR -Display Version number and exit -. -.TP -\fB\-k\fR \fB\-\-keep\fR -Preserve source files (default behavior) -. -.TP -\fB\-\-rm\fR -Delete source files on successful compression or decompression -. -.TP -\fB\-\-\fR -Treat all subsequent arguments as files -. -.SS "Benchmark mode" -. -.TP -\fB\-b#\fR -Benchmark file(s), using # compression level -. -.TP -\fB\-e#\fR -Benchmark multiple compression levels, from b# to e# (included) -. -.TP -\fB\-i#\fR -Minimum evaluation time in seconds [1\-9] (default : 3) -. -.SH "BUGS" -Report bugs at: https://github\.com/lz4/lz4/issues -. -.SH "AUTHOR" -Yann Collet diff --git a/ta6ob/lz4/programs/lz4.1.md b/ta6ob/lz4/programs/lz4.1.md deleted file mode 100644 index 56c0053..0000000 --- a/ta6ob/lz4/programs/lz4.1.md +++ /dev/null @@ -1,250 +0,0 @@ -lz4(1) -- lz4, unlz4, lz4cat - Compress or decompress .lz4 files -================================================================ - -SYNOPSIS --------- - -`lz4` [*OPTIONS*] [-|INPUT-FILE] - -`unlz4` is equivalent to `lz4 -d` - -`lz4cat` is equivalent to `lz4 -dcfm` - -When writing scripts that need to decompress files, -it is recommended to always use the name `lz4` with appropriate arguments -(`lz4 -d` or `lz4 -dc`) instead of the names `unlz4` and `lz4cat`. - - -DESCRIPTION ------------ - -`lz4` is an extremely fast lossless compression algorithm, -based on **byte-aligned LZ77** family of compression scheme. -`lz4` offers compression speeds of 400 MB/s per core, linearly scalable with -multi-core CPUs. -It features an extremely fast decoder, with speed in multiple GB/s per core, -typically reaching RAM speed limit on multi-core systems. -The native file format is the `.lz4` format. - -### Difference between lz4 and gzip - -`lz4` supports a command line syntax similar _but not identical_ to `gzip(1)`. -Differences are : - - * `lz4` compresses a single file by default (see `-m` for multiple files) - * `lz4 file1 file2` means : compress file1 _into_ file2 - * `lz4 file.lz4` will default to decompression (use `-z` to force compression) - * `lz4` preserves original files - * `lz4` shows real-time notification statistics - during compression or decompression of a single file - (use `-q` to silence them) - * When no destination is specified, result is sent on implicit output, - which depends on `stdout` status. - When `stdout` _is Not the console_, it becomes the implicit output. - Otherwise, if `stdout` is the console, the implicit output is `filename.lz4`. - * It is considered bad practice to rely on implicit output in scripts. - because the script's environment may change. - Always use explicit output in scripts. - `-c` ensures that output will be `stdout`. - Conversely, providing a destination name, or using `-m` - ensures that the output will be either the specified name, or `filename.lz4` respectively. - -Default behaviors can be modified by opt-in commands, detailed below. - - * `lz4 -m` makes it possible to provide multiple input filenames, - which will be compressed into files using suffix `.lz4`. - Progress notifications become disabled by default (use `-v` to enable them). - This mode has a behavior which more closely mimics `gzip` command line, - with the main remaining difference being that source files are preserved by default. - * Similarly, `lz4 -m -d` can decompress multiple `*.lz4` files. - * It's possible to opt-in to erase source files - on successful compression or decompression, using `--rm` command. - * Consequently, `lz4 -m --rm` behaves the same as `gzip`. - -### Concatenation of .lz4 files - -It is possible to concatenate `.lz4` files as is. -`lz4` will decompress such files as if they were a single `.lz4` file. -For example: - - lz4 file1 > foo.lz4 - lz4 file2 >> foo.lz4 - -Then `lz4cat foo.lz4` is equivalent to `cat file1 file2`. - -OPTIONS -------- - -### Short commands concatenation - -In some cases, some options can be expressed using short command `-x` -or long command `--long-word`. -Short commands can be concatenated together. -For example, `-d -c` is equivalent to `-dc`. -Long commands cannot be concatenated. They must be clearly separated by a space. - -### Multiple commands - -When multiple contradictory commands are issued on a same command line, -only the latest one will be applied. - -### Operation mode - -* `-z` `--compress`: - Compress. - This is the default operation mode when no operation mode option is - specified, no other operation mode is implied from the command name - (for example, `unlz4` implies `--decompress`), - nor from the input file name - (for example, a file extension `.lz4` implies `--decompress` by default). - `-z` can also be used to force compression of an already compressed - `.lz4` file. - -* `-d` `--decompress` `--uncompress`: - Decompress. - `--decompress` is also the default operation when the input filename has an - `.lz4` extension. - -* `-t` `--test`: - Test the integrity of compressed `.lz4` files. - The decompressed data is discarded. - No files are created nor removed. - -* `-b#`: - Benchmark mode, using `#` compression level. - -* `--list`: - List information about .lz4 files. - note : current implementation is limited to single-frame .lz4 files. - -### Operation modifiers - -* `-#`: - Compression level, with # being any value from 1 to 12. - Higher values trade compression speed for compression ratio. - Values above 12 are considered the same as 12. - Recommended values are 1 for fast compression (default), - and 9 for high compression. - Speed/compression trade-off will vary depending on data to compress. - Decompression speed remains fast at all settings. - -* `--fast[=#]`: - Switch to ultra-fast compression levels. - The higher the value, the faster the compression speed, at the cost of some compression ratio. - If `=#` is not present, it defaults to `1`. - This setting overrides compression level if one was set previously. - Similarly, if a compression level is set after `--fast`, it overrides it. - -* `--best`: - Set highest compression level. Same as -12. - -* `--favor-decSpeed`: - Generate compressed data optimized for decompression speed. - Compressed data will be larger as a consequence (typically by ~0.5%), - while decompression speed will be improved by 5-20%, depending on use cases. - This option only works in combination with very high compression levels (>=10). - -* `-D dictionaryName`: - Compress, decompress or benchmark using dictionary _dictionaryName_. - Compression and decompression must use the same dictionary to be compatible. - Using a different dictionary during decompression will either - abort due to decompression error, or generate a checksum error. - -* `-f` `--[no-]force`: - This option has several effects: - - If the target file already exists, overwrite it without prompting. - - When used with `--decompress` and `lz4` cannot recognize the type of - the source file, copy the source file as is to standard output. - This allows `lz4cat --force` to be used like `cat (1)` for files - that have not been compressed with `lz4`. - -* `-c` `--stdout` `--to-stdout`: - Force write to standard output, even if it is the console. - -* `-m` `--multiple`: - Multiple input files. - Compressed file names will be appended a `.lz4` suffix. - This mode also reduces notification level. - Can also be used to list multiple files. - `lz4 -m` has a behavior equivalent to `gzip -k` - (it preserves source files by default). - -* `-r` : - operate recursively on directories. - This mode also sets `-m` (multiple input files). - -* `-B#`: - Block size \[4-7\](default : 7)
- `-B4`= 64KB ; `-B5`= 256KB ; `-B6`= 1MB ; `-B7`= 4MB - -* `-BI`: - Produce independent blocks (default) - -* `-BD`: - Blocks depend on predecessors (improves compression ratio, more noticeable on small blocks) - -* `--[no-]frame-crc`: - Select frame checksum (default:enabled) - -* `--[no-]content-size`: - Header includes original size (default:not present)
- Note : this option can only be activated when the original size can be - determined, hence for a file. It won't work with unknown source size, - such as stdin or pipe. - -* `--[no-]sparse`: - Sparse mode support (default:enabled on file, disabled on stdout) - -* `-l`: - Use Legacy format (typically for Linux Kernel compression)
- Note : `-l` is not compatible with `-m` (`--multiple`) nor `-r` - -### Other options - -* `-v` `--verbose`: - Verbose mode - -* `-q` `--quiet`: - Suppress warnings and real-time statistics; - specify twice to suppress errors too - -* `-h` `-H` `--help`: - Display help/long help and exit - -* `-V` `--version`: - Display Version number and exit - -* `-k` `--keep`: - Preserve source files (default behavior) - -* `--rm` : - Delete source files on successful compression or decompression - -* `--` : - Treat all subsequent arguments as files - - -### Benchmark mode - -* `-b#`: - Benchmark file(s), using # compression level - -* `-e#`: - Benchmark multiple compression levels, from b# to e# (included) - -* `-i#`: - Minimum evaluation time in seconds \[1-9\] (default : 3) - - -BUGS ----- - -Report bugs at: https://github.com/lz4/lz4/issues - - -AUTHOR ------- - -Yann Collet diff --git a/ta6ob/lz4/programs/lz4cli.c b/ta6ob/lz4/programs/lz4cli.c deleted file mode 100644 index 523b8a8..0000000 --- a/ta6ob/lz4/programs/lz4cli.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - LZ4cli - LZ4 Command Line Interface - Copyright (C) Yann Collet 2011-2016 - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ -/* - Note : this is stand-alone program. - It is not part of LZ4 compression library, it is a user program of the LZ4 library. - The license of LZ4 library is BSD. - The license of xxHash library is BSD. - The license of this compression CLI program is GPLv2. -*/ - - -/**************************** -* Includes -*****************************/ -#include "platform.h" /* Compiler options, IS_CONSOLE */ -#include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */ -#include /* fprintf, getchar */ -#include /* exit, calloc, free */ -#include /* strcmp, strlen */ -#include "bench.h" /* BMK_benchFile, BMK_SetNbIterations, BMK_SetBlocksize, BMK_SetPause */ -#include "lz4io.h" /* LZ4IO_compressFilename, LZ4IO_decompressFilename, LZ4IO_compressMultipleFilenames */ -#include "lz4hc.h" /* LZ4HC_CLEVEL_MAX */ -#include "lz4.h" /* LZ4_VERSION_STRING */ - - -/***************************** -* Constants -******************************/ -#define COMPRESSOR_NAME "LZ4 command line interface" -#define AUTHOR "Yann Collet" -#define WELCOME_MESSAGE "*** %s %i-bits v%s, by %s ***\n", COMPRESSOR_NAME, (int)(sizeof(void*)*8), LZ4_versionString(), AUTHOR -#define LZ4_EXTENSION ".lz4" -#define LZ4CAT "lz4cat" -#define UNLZ4 "unlz4" -#define LZ4_LEGACY "lz4c" -static int g_lz4c_legacy_commands = 0; - -#define KB *(1U<<10) -#define MB *(1U<<20) -#define GB *(1U<<30) - -#define LZ4_BLOCKSIZEID_DEFAULT 7 - - -/*-************************************ -* Macros -***************************************/ -#define DISPLAYOUT(...) fprintf(stdout, __VA_ARGS__) -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); } -static unsigned displayLevel = 2; /* 0 : no display ; 1: errors only ; 2 : downgradable normal ; 3 : non-downgradable normal; 4 : + information */ - - -/*-************************************ -* Exceptions -***************************************/ -#define DEBUG 0 -#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); -#define EXM_THROW(error, ...) \ -{ \ - DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ - DISPLAYLEVEL(1, "Error %i : ", error); \ - DISPLAYLEVEL(1, __VA_ARGS__); \ - DISPLAYLEVEL(1, "\n"); \ - exit(error); \ -} - - -/*-************************************ -* Version modifiers -***************************************/ -#define DEFAULT_COMPRESSOR LZ4IO_compressFilename -#define DEFAULT_DECOMPRESSOR LZ4IO_decompressFilename -int LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output_filename, int compressionlevel, const LZ4IO_prefs_t* prefs); /* hidden function */ -int LZ4IO_compressMultipleFilenames_Legacy( - const char** inFileNamesTable, int ifntSize, - const char* suffix, - int compressionLevel, const LZ4IO_prefs_t* prefs); - -/*-*************************** -* Functions -*****************************/ -static int usage(const char* exeName) -{ - DISPLAY( "Usage : \n"); - DISPLAY( " %s [arg] [input] [output] \n", exeName); - DISPLAY( "\n"); - DISPLAY( "input : a filename \n"); - DISPLAY( " with no FILE, or when FILE is - or %s, read standard input\n", stdinmark); - DISPLAY( "Arguments : \n"); - DISPLAY( " -1 : Fast compression (default) \n"); - DISPLAY( " -9 : High compression \n"); - DISPLAY( " -d : decompression (default for %s extension)\n", LZ4_EXTENSION); - DISPLAY( " -z : force compression \n"); - DISPLAY( " -D FILE: use FILE as dictionary \n"); - DISPLAY( " -f : overwrite output without prompting \n"); - DISPLAY( " -k : preserve source files(s) (default) \n"); - DISPLAY( "--rm : remove source file(s) after successful de/compression \n"); - DISPLAY( " -h/-H : display help/long help and exit \n"); - return 0; -} - -static int usage_advanced(const char* exeName) -{ - DISPLAY(WELCOME_MESSAGE); - usage(exeName); - DISPLAY( "\n"); - DISPLAY( "Advanced arguments :\n"); - DISPLAY( " -V : display Version number and exit \n"); - DISPLAY( " -v : verbose mode \n"); - DISPLAY( " -q : suppress warnings; specify twice to suppress errors too\n"); - DISPLAY( " -c : force write to standard output, even if it is the console\n"); - DISPLAY( " -t : test compressed file integrity\n"); - DISPLAY( " -m : multiple input files (implies automatic output filenames)\n"); -#ifdef UTIL_HAS_CREATEFILELIST - DISPLAY( " -r : operate recursively on directories (sets also -m) \n"); -#endif - DISPLAY( " -l : compress using Legacy format (Linux kernel compression)\n"); - DISPLAY( " -B# : cut file into blocks of size # bytes [32+] \n"); - DISPLAY( " or predefined block size [4-7] (default: 7) \n"); - DISPLAY( " -BI : Block Independence (default) \n"); - DISPLAY( " -BD : Block dependency (improves compression ratio) \n"); - DISPLAY( " -BX : enable block checksum (default:disabled) \n"); - DISPLAY( "--no-frame-crc : disable stream checksum (default:enabled) \n"); - DISPLAY( "--content-size : compressed frame includes original size (default:not present)\n"); - DISPLAY( "--list FILE : lists information about .lz4 files (useful for files compressed with --content-size flag)\n"); - DISPLAY( "--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)\n"); - DISPLAY( "--favor-decSpeed: compressed files decompress faster, but are less compressed \n"); - DISPLAY( "--fast[=#]: switch to ultra fast compression level (default: %i)\n", 1); - DISPLAY( "--best : same as -%d\n", LZ4HC_CLEVEL_MAX); - DISPLAY( "Benchmark arguments : \n"); - DISPLAY( " -b# : benchmark file(s), using # compression level (default : 1) \n"); - DISPLAY( " -e# : test all compression levels from -bX to # (default : 1)\n"); - DISPLAY( " -i# : minimum evaluation time in seconds (default : 3s) \n"); - if (g_lz4c_legacy_commands) { - DISPLAY( "Legacy arguments : \n"); - DISPLAY( " -c0 : fast compression \n"); - DISPLAY( " -c1 : high compression \n"); - DISPLAY( " -c2,-hc: very high compression \n"); - DISPLAY( " -y : overwrite output without prompting \n"); - } - return 0; -} - -static int usage_longhelp(const char* exeName) -{ - usage_advanced(exeName); - DISPLAY( "\n"); - DISPLAY( "****************************\n"); - DISPLAY( "***** Advanced comment *****\n"); - DISPLAY( "****************************\n"); - DISPLAY( "\n"); - DISPLAY( "Which values can [output] have ? \n"); - DISPLAY( "---------------------------------\n"); - DISPLAY( "[output] : a filename \n"); - DISPLAY( " '%s', or '-' for standard output (pipe mode)\n", stdoutmark); - DISPLAY( " '%s' to discard output (test mode) \n", NULL_OUTPUT); - DISPLAY( "[output] can be left empty. In this case, it receives the following value :\n"); - DISPLAY( " - if stdout is not the console, then [output] = stdout \n"); - DISPLAY( " - if stdout is console : \n"); - DISPLAY( " + for compression, output to filename%s \n", LZ4_EXTENSION); - DISPLAY( " + for decompression, output to filename without '%s'\n", LZ4_EXTENSION); - DISPLAY( " > if input filename has no '%s' extension : error \n", LZ4_EXTENSION); - DISPLAY( "\n"); - DISPLAY( "Compression levels : \n"); - DISPLAY( "---------------------\n"); - DISPLAY( "-0 ... -2 => Fast compression, all identicals\n"); - DISPLAY( "-3 ... -%d => High compression; higher number == more compression but slower\n", LZ4HC_CLEVEL_MAX); - DISPLAY( "\n"); - DISPLAY( "stdin, stdout and the console : \n"); - DISPLAY( "--------------------------------\n"); - DISPLAY( "To protect the console from binary flooding (bad argument mistake)\n"); - DISPLAY( "%s will refuse to read from console, or write to console \n", exeName); - DISPLAY( "except if '-c' command is specified, to force output to console \n"); - DISPLAY( "\n"); - DISPLAY( "Simple example :\n"); - DISPLAY( "----------------\n"); - DISPLAY( "1 : compress 'filename' fast, using default output name 'filename.lz4'\n"); - DISPLAY( " %s filename\n", exeName); - DISPLAY( "\n"); - DISPLAY( "Short arguments can be aggregated. For example :\n"); - DISPLAY( "----------------------------------\n"); - DISPLAY( "2 : compress 'filename' in high compression mode, overwrite output if exists\n"); - DISPLAY( " %s -9 -f filename \n", exeName); - DISPLAY( " is equivalent to :\n"); - DISPLAY( " %s -9f filename \n", exeName); - DISPLAY( "\n"); - DISPLAY( "%s can be used in 'pure pipe mode'. For example :\n", exeName); - DISPLAY( "-------------------------------------\n"); - DISPLAY( "3 : compress data stream from 'generator', send result to 'consumer'\n"); - DISPLAY( " generator | %s | consumer \n", exeName); - if (g_lz4c_legacy_commands) { - DISPLAY( "\n"); - DISPLAY( "***** Warning ***** \n"); - DISPLAY( "Legacy arguments take precedence. Therefore : \n"); - DISPLAY( "--------------------------------- \n"); - DISPLAY( " %s -hc filename \n", exeName); - DISPLAY( "means 'compress filename in high compression mode' \n"); - DISPLAY( "It is not equivalent to : \n"); - DISPLAY( " %s -h -c filename \n", exeName); - DISPLAY( "which displays help text and exits \n"); - } - return 0; -} - -static int badusage(const char* exeName) -{ - DISPLAYLEVEL(1, "Incorrect parameters\n"); - if (displayLevel >= 1) usage(exeName); - exit(1); -} - - -static void waitEnter(void) -{ - DISPLAY("Press enter to continue...\n"); - (void)getchar(); -} - -static const char* lastNameFromPath(const char* path) -{ - const char* name = path; - if (strrchr(name, '/')) name = strrchr(name, '/') + 1; - if (strrchr(name, '\\')) name = strrchr(name, '\\') + 1; /* windows */ - return name; -} - -/*! exeNameMatch() : - @return : a non-zero value if exeName matches test, excluding the extension - */ -static int exeNameMatch(const char* exeName, const char* test) -{ - return !strncmp(exeName, test, strlen(test)) && - (exeName[strlen(test)] == '\0' || exeName[strlen(test)] == '.'); -} - -/*! readU32FromChar() : - * @return : unsigned integer value read from input in `char` format - * allows and interprets K, KB, KiB, M, MB and MiB suffix. - * Will also modify `*stringPtr`, advancing it to position where it stopped reading. - * Note : function result can overflow if digit string > MAX_UINT */ -static unsigned readU32FromChar(const char** stringPtr) -{ - unsigned result = 0; - while ((**stringPtr >='0') && (**stringPtr <='9')) { - result *= 10; - result += (unsigned)(**stringPtr - '0'); - (*stringPtr)++ ; - } - if ((**stringPtr=='K') || (**stringPtr=='M')) { - result <<= 10; - if (**stringPtr=='M') result <<= 10; - (*stringPtr)++ ; - if (**stringPtr=='i') (*stringPtr)++; - if (**stringPtr=='B') (*stringPtr)++; - } - return result; -} - -/** longCommandWArg() : - * check if *stringPtr is the same as longCommand. - * If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand. - * @return 0 and doesn't modify *stringPtr otherwise. - */ -static int longCommandWArg(const char** stringPtr, const char* longCommand) -{ - size_t const comSize = strlen(longCommand); - int const result = !strncmp(*stringPtr, longCommand, comSize); - if (result) *stringPtr += comSize; - return result; -} - -typedef enum { om_auto, om_compress, om_decompress, om_test, om_bench, om_list } operationMode_e; - -/** determineOpMode() : - * auto-determine operation mode, based on input filename extension - * @return `om_decompress` if input filename has .lz4 extension and `om_compress` otherwise. - */ -static operationMode_e determineOpMode(const char* inputFilename) -{ - size_t const inSize = strlen(inputFilename); - size_t const extSize = strlen(LZ4_EXTENSION); - size_t const extStart= (inSize > extSize) ? inSize-extSize : 0; - if (!strcmp(inputFilename+extStart, LZ4_EXTENSION)) return om_decompress; - else return om_compress; -} - -int main(int argc, const char** argv) -{ - int i, - cLevel=1, - cLevelLast=-10000, - legacy_format=0, - forceStdout=0, - main_pause=0, - multiple_inputs=0, - all_arguments_are_files=0, - operationResult=0; - operationMode_e mode = om_auto; - const char* input_filename = NULL; - const char* output_filename= NULL; - const char* dictionary_filename = NULL; - char* dynNameSpace = NULL; - const char** inFileNames = (const char**)calloc((size_t)argc, sizeof(char*)); - unsigned ifnIdx=0; - LZ4IO_prefs_t* const prefs = LZ4IO_defaultPreferences(); - const char nullOutput[] = NULL_OUTPUT; - const char extension[] = LZ4_EXTENSION; - size_t blockSize = LZ4IO_setBlockSizeID(prefs, LZ4_BLOCKSIZEID_DEFAULT); - const char* const exeName = lastNameFromPath(argv[0]); -#ifdef UTIL_HAS_CREATEFILELIST - const char** extendedFileList = NULL; - char* fileNamesBuf = NULL; - unsigned fileNamesNb, recursive=0; -#endif - - /* Init */ - if (inFileNames==NULL) { - DISPLAY("Allocation error : not enough memory \n"); - return 1; - } - inFileNames[0] = stdinmark; - LZ4IO_setOverwrite(prefs, 0); - - /* predefined behaviors, based on binary/link name */ - if (exeNameMatch(exeName, LZ4CAT)) { - mode = om_decompress; - LZ4IO_setOverwrite(prefs, 1); - LZ4IO_setPassThrough(prefs, 1); - LZ4IO_setRemoveSrcFile(prefs, 0); - forceStdout=1; - output_filename=stdoutmark; - displayLevel=1; - multiple_inputs=1; - } - if (exeNameMatch(exeName, UNLZ4)) { mode = om_decompress; } - if (exeNameMatch(exeName, LZ4_LEGACY)) { g_lz4c_legacy_commands=1; } - - /* command switches */ - for(i=1; i='0') && (*argument<='9')) { - cLevel = (int)readU32FromChar(&argument); - argument--; - continue; - } - - - switch(argument[0]) - { - /* Display help */ - case 'V': DISPLAYOUT(WELCOME_MESSAGE); goto _cleanup; /* Version */ - case 'h': usage_advanced(exeName); goto _cleanup; - case 'H': usage_longhelp(exeName); goto _cleanup; - - case 'e': - argument++; - cLevelLast = (int)readU32FromChar(&argument); - argument--; - break; - - /* Compression (default) */ - case 'z': mode = om_compress; break; - - case 'D': - if (argument[1] == '\0') { - /* path is next arg */ - if (i + 1 == argc) { - /* there is no next arg */ - badusage(exeName); - } - dictionary_filename = argv[++i]; - } else { - /* path follows immediately */ - dictionary_filename = argument + 1; - } - /* skip to end of argument so that we jump to parsing next argument */ - argument += strlen(argument) - 1; - break; - - /* Use Legacy format (ex : Linux kernel compression) */ - case 'l': legacy_format = 1; blockSize = 8 MB; break; - - /* Decoding */ - case 'd': mode = om_decompress; break; - - /* Force stdout, even if stdout==console */ - case 'c': - forceStdout=1; - output_filename=stdoutmark; - LZ4IO_setPassThrough(prefs, 1); - break; - - /* Test integrity */ - case 't': mode = om_test; break; - - /* Overwrite */ - case 'f': LZ4IO_setOverwrite(prefs, 1); break; - - /* Verbose mode */ - case 'v': displayLevel++; break; - - /* Quiet mode */ - case 'q': if (displayLevel) displayLevel--; break; - - /* keep source file (default anyway, so useless) (for xz/lzma compatibility) */ - case 'k': LZ4IO_setRemoveSrcFile(prefs, 0); break; - - /* Modify Block Properties */ - case 'B': - while (argument[1]!=0) { - int exitBlockProperties=0; - switch(argument[1]) - { - case 'D': LZ4IO_setBlockMode(prefs, LZ4IO_blockLinked); argument++; break; - case 'I': LZ4IO_setBlockMode(prefs, LZ4IO_blockIndependent); argument++; break; - case 'X': LZ4IO_setBlockChecksumMode(prefs, 1); argument ++; break; /* disabled by default */ - default : - if (argument[1] < '0' || argument[1] > '9') { - exitBlockProperties=1; - break; - } else { - unsigned B; - argument++; - B = readU32FromChar(&argument); - argument--; - if (B < 4) badusage(exeName); - if (B <= 7) { - blockSize = LZ4IO_setBlockSizeID(prefs, B); - BMK_setBlockSize(blockSize); - DISPLAYLEVEL(2, "using blocks of size %u KB \n", (U32)(blockSize>>10)); - } else { - if (B < 32) badusage(exeName); - blockSize = LZ4IO_setBlockSize(prefs, B); - BMK_setBlockSize(blockSize); - if (blockSize >= 1024) { - DISPLAYLEVEL(2, "using blocks of size %u KB \n", (U32)(blockSize>>10)); - } else { - DISPLAYLEVEL(2, "using blocks of size %u bytes \n", (U32)(blockSize)); - } - } - break; - } - } - if (exitBlockProperties) break; - } - break; - - /* Benchmark */ - case 'b': mode = om_bench; multiple_inputs=1; - break; - - /* hidden command : benchmark files, but do not fuse result */ - case 'S': BMK_setBenchSeparately(1); - break; - -#ifdef UTIL_HAS_CREATEFILELIST - /* recursive */ - case 'r': recursive=1; -#endif - /* fall-through */ - /* Treat non-option args as input files. See https://code.google.com/p/lz4/issues/detail?id=151 */ - case 'm': multiple_inputs=1; - break; - - /* Modify Nb Seconds (benchmark only) */ - case 'i': - { unsigned iters; - argument++; - iters = readU32FromChar(&argument); - argument--; - BMK_setNotificationLevel(displayLevel); - BMK_setNbSeconds(iters); /* notification if displayLevel >= 3 */ - } - break; - - /* Pause at the end (hidden option) */ - case 'p': main_pause=1; break; - - /* Unrecognised command */ - default : badusage(exeName); - } - } - continue; - } - - /* Store in *inFileNames[] if -m is used. */ - if (multiple_inputs) { inFileNames[ifnIdx++]=argument; continue; } - - /* Store first non-option arg in input_filename to preserve original cli logic. */ - if (!input_filename) { input_filename=argument; continue; } - - /* Second non-option arg in output_filename to preserve original cli logic. */ - if (!output_filename) { - output_filename=argument; - if (!strcmp (output_filename, nullOutput)) output_filename = nulmark; - continue; - } - - /* 3rd non-option arg should not exist */ - DISPLAYLEVEL(1, "Warning : %s won't be used ! Do you want multiple input files (-m) ? \n", argument); - } - - DISPLAYLEVEL(3, WELCOME_MESSAGE); -#ifdef _POSIX_C_SOURCE - DISPLAYLEVEL(4, "_POSIX_C_SOURCE defined: %ldL\n", (long) _POSIX_C_SOURCE); -#endif -#ifdef _POSIX_VERSION - DISPLAYLEVEL(4, "_POSIX_VERSION defined: %ldL\n", (long) _POSIX_VERSION); -#endif -#ifdef PLATFORM_POSIX_VERSION - DISPLAYLEVEL(4, "PLATFORM_POSIX_VERSION defined: %ldL\n", (long) PLATFORM_POSIX_VERSION); -#endif -#ifdef _FILE_OFFSET_BITS - DISPLAYLEVEL(4, "_FILE_OFFSET_BITS defined: %ldL\n", (long) _FILE_OFFSET_BITS); -#endif - if ((mode == om_compress) || (mode == om_bench)) - DISPLAYLEVEL(4, "Blocks size : %u KB\n", (U32)(blockSize>>10)); - - if (multiple_inputs) { - input_filename = inFileNames[0]; -#ifdef UTIL_HAS_CREATEFILELIST - if (recursive) { /* at this stage, filenameTable is a list of paths, which can contain both files and directories */ - extendedFileList = UTIL_createFileList(inFileNames, ifnIdx, &fileNamesBuf, &fileNamesNb); - if (extendedFileList) { - unsigned u; - for (u=0; u try to select one automatically (when possible) */ - while ((!output_filename) && (multiple_inputs==0)) { - if (!IS_CONSOLE(stdout) && mode != om_list) { - /* Default to stdout whenever stdout is not the console. - * Note : this policy may change in the future, therefore don't rely on it ! - * To ensure `stdout` is explicitly selected, use `-c` command flag. - * Conversely, to ensure output will not become `stdout`, use `-m` command flag */ - DISPLAYLEVEL(1, "Warning : using stdout as default output. Do not rely on this behavior: use explicit `-c` instead ! \n"); - output_filename=stdoutmark; - break; - } - if (mode == om_auto) { /* auto-determine compression or decompression, based on file extension */ - mode = determineOpMode(input_filename); - } - if (mode == om_compress) { /* compression to file */ - size_t const l = strlen(input_filename); - dynNameSpace = (char*)calloc(1,l+5); - if (dynNameSpace==NULL) { perror(exeName); exit(1); } - strcpy(dynNameSpace, input_filename); - strcat(dynNameSpace, LZ4_EXTENSION); - output_filename = dynNameSpace; - DISPLAYLEVEL(2, "Compressed filename will be : %s \n", output_filename); - break; - } - if (mode == om_decompress) {/* decompression to file (automatic name will work only if input filename has correct format extension) */ - size_t outl; - size_t const inl = strlen(input_filename); - dynNameSpace = (char*)calloc(1,inl+1); - if (dynNameSpace==NULL) { perror(exeName); exit(1); } - strcpy(dynNameSpace, input_filename); - outl = inl; - if (inl>4) - while ((outl >= inl-4) && (input_filename[outl] == extension[outl-inl+4])) dynNameSpace[outl--]=0; - if (outl != inl-5) { DISPLAYLEVEL(1, "Cannot determine an output filename\n"); badusage(exeName); } - output_filename = dynNameSpace; - DISPLAYLEVEL(2, "Decoding file %s \n", output_filename); - } - break; - } - - if (mode == om_list){ - /* Exit if trying to read from stdin as this isn't supported in this mode */ - if(!strcmp(input_filename, stdinmark)){ - DISPLAYLEVEL(1, "refusing to read from standard input in --list mode\n"); - exit(1); - } - if(!multiple_inputs){ - inFileNames[ifnIdx++] = input_filename; - } - } - else{ - if (multiple_inputs==0) assert(output_filename); - } - /* when multiple_inputs==1, output_filename may simply be useless, - * however, output_filename must be !NULL for next strcmp() tests */ - if (!output_filename) output_filename = "*\\dummy^!//"; - - /* Check if output is defined as console; trigger an error in this case */ - if (!strcmp(output_filename,stdoutmark) && IS_CONSOLE(stdout) && !forceStdout) { - DISPLAYLEVEL(1, "refusing to write to console without -c \n"); - exit(1); - } - /* Downgrade notification level in stdout and multiple file mode */ - if (!strcmp(output_filename,stdoutmark) && (displayLevel==2)) displayLevel=1; - if ((multiple_inputs) && (displayLevel==2)) displayLevel=1; - - /* Auto-determine compression or decompression, based on file extension */ - if (mode == om_auto) { - mode = determineOpMode(input_filename); - } - - /* IO Stream/File */ - LZ4IO_setNotificationLevel((int)displayLevel); - if (ifnIdx == 0) multiple_inputs = 0; - if (mode == om_decompress) { - if (multiple_inputs) { - const char* const dec_extension = !strcmp(output_filename,stdoutmark) ? stdoutmark : LZ4_EXTENSION; - assert(ifnIdx <= INT_MAX); - operationResult = LZ4IO_decompressMultipleFilenames(inFileNames, (int)ifnIdx, dec_extension, prefs); - } else { - operationResult = DEFAULT_DECOMPRESSOR(input_filename, output_filename, prefs); - } - } else if (mode == om_list){ - operationResult = LZ4IO_displayCompressedFilesInfo(inFileNames, ifnIdx); - } else { /* compression is default action */ - if (legacy_format) { - DISPLAYLEVEL(3, "! Generating LZ4 Legacy format (deprecated) ! \n"); - if(multiple_inputs){ - const char* const leg_extension = !strcmp(output_filename,stdoutmark) ? stdoutmark : LZ4_EXTENSION; - LZ4IO_compressMultipleFilenames_Legacy(inFileNames, (int)ifnIdx, leg_extension, cLevel, prefs); - } else { - LZ4IO_compressFilename_Legacy(input_filename, output_filename, cLevel, prefs); - } - } else { - if (multiple_inputs) { - const char* const comp_extension = !strcmp(output_filename,stdoutmark) ? stdoutmark : LZ4_EXTENSION; - assert(ifnIdx <= INT_MAX); - operationResult = LZ4IO_compressMultipleFilenames(inFileNames, (int)ifnIdx, comp_extension, cLevel, prefs); - } else { - operationResult = DEFAULT_COMPRESSOR(input_filename, output_filename, cLevel, prefs); - } } } - -_cleanup: - if (main_pause) waitEnter(); - free(dynNameSpace); -#ifdef UTIL_HAS_CREATEFILELIST - if (extendedFileList) { - UTIL_freeFileList(extendedFileList, fileNamesBuf); - inFileNames = NULL; - } -#endif - LZ4IO_freePreferences(prefs); - free((void*)inFileNames); - return operationResult; -} diff --git a/ta6ob/lz4/programs/lz4io.c b/ta6ob/lz4/programs/lz4io.c deleted file mode 100644 index a274798..0000000 --- a/ta6ob/lz4/programs/lz4io.c +++ /dev/null @@ -1,1677 +0,0 @@ -/* - LZ4io.c - LZ4 File/Stream Interface - Copyright (C) Yann Collet 2011-2017 - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ -/* - Note : this is stand-alone program. - It is not part of LZ4 compression library, it is a user code of the LZ4 library. - - The license of LZ4 library is BSD. - - The license of xxHash library is BSD. - - The license of this source file is GPLv2. -*/ - - -/*-************************************ -* Compiler options -**************************************/ -#ifdef _MSC_VER /* Visual Studio */ -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#endif -#if defined(__MINGW32__) && !defined(_POSIX_SOURCE) -# define _POSIX_SOURCE 1 /* disable %llu warnings with MinGW on Windows */ -#endif - - -/***************************** -* Includes -*****************************/ -#include "platform.h" /* Large File Support, SET_BINARY_MODE, SET_SPARSE_FILE_MODE, PLATFORM_POSIX_VERSION, __64BIT__ */ -#include "util.h" /* UTIL_getFileStat, UTIL_setFileStat */ -#include /* fprintf, fopen, fread, stdin, stdout, fflush, getchar */ -#include /* malloc, free */ -#include /* strerror, strcmp, strlen */ -#include /* clock */ -#include /* stat64 */ -#include /* stat64 */ -#include "lz4.h" /* still required for legacy format */ -#include "lz4hc.h" /* still required for legacy format */ -#define LZ4F_STATIC_LINKING_ONLY -#include "lz4frame.h" -#include "lz4io.h" - - -/***************************** -* Constants -*****************************/ -#define KB *(1 <<10) -#define MB *(1 <<20) -#define GB *(1U<<30) - -#define _1BIT 0x01 -#define _2BITS 0x03 -#define _3BITS 0x07 -#define _4BITS 0x0F -#define _8BITS 0xFF - -#define MAGICNUMBER_SIZE 4 -#define LZ4IO_MAGICNUMBER 0x184D2204 -#define LZ4IO_SKIPPABLE0 0x184D2A50 -#define LZ4IO_SKIPPABLEMASK 0xFFFFFFF0 -#define LEGACY_MAGICNUMBER 0x184C2102 - -#define CACHELINE 64 -#define LEGACY_BLOCKSIZE (8 MB) -#define MIN_STREAM_BUFSIZE (192 KB) -#define LZ4IO_BLOCKSIZEID_DEFAULT 7 -#define LZ4_MAX_DICT_SIZE (64 KB) - - -/************************************** -* Macros -**************************************/ -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYOUT(...) fprintf(stdout, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } -static int g_displayLevel = 0; /* 0 : no display ; 1: errors ; 2 : + result + interaction + warnings ; 3 : + progression; 4 : + information */ - -#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \ - if ( ((clock() - g_time) > refreshRate) \ - || (g_displayLevel>=4) ) { \ - g_time = clock(); \ - DISPLAY(__VA_ARGS__); \ - if (g_displayLevel>=4) fflush(stderr); \ - } } -static const clock_t refreshRate = CLOCKS_PER_SEC / 6; -static clock_t g_time = 0; -#define LZ4IO_STATIC_ASSERT(c) { enum { LZ4IO_static_assert = 1/(int)(!!(c)) }; } /* use after variable declarations */ - - -/************************************** -* Local Parameters -**************************************/ - -struct LZ4IO_prefs_s { - int passThrough; - int overwrite; - int testMode; - int blockSizeId; - size_t blockSize; - int blockChecksum; - int streamChecksum; - int blockIndependence; - int sparseFileSupport; - int contentSizeFlag; - int useDictionary; - unsigned favorDecSpeed; - const char* dictionaryFilename; - int removeSrcFile; -}; - -/************************************** -* Exceptions -***************************************/ -#ifndef DEBUG -# define DEBUG 0 -#endif -#define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); -#define EXM_THROW(error, ...) \ -{ \ - DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ - DISPLAYLEVEL(1, "Error %i : ", error); \ - DISPLAYLEVEL(1, __VA_ARGS__); \ - DISPLAYLEVEL(1, " \n"); \ - exit(error); \ -} - - -/************************************** -* Version modifiers -**************************************/ -#define EXTENDED_ARGUMENTS -#define EXTENDED_HELP -#define EXTENDED_FORMAT -#define DEFAULT_DECOMPRESSOR LZ4IO_decompressLZ4F - - -/* ************************************************** */ -/* ****************** Parameters ******************** */ -/* ************************************************** */ - -LZ4IO_prefs_t* LZ4IO_defaultPreferences(void) -{ - LZ4IO_prefs_t* const ret = (LZ4IO_prefs_t*)malloc(sizeof(*ret)); - if (!ret) EXM_THROW(21, "Allocation error : not enough memory"); - ret->passThrough = 0; - ret->overwrite = 1; - ret->testMode = 0; - ret->blockSizeId = LZ4IO_BLOCKSIZEID_DEFAULT; - ret->blockSize = 0; - ret->blockChecksum = 0; - ret->streamChecksum = 1; - ret->blockIndependence = 1; - ret->sparseFileSupport = 1; - ret->contentSizeFlag = 0; - ret->useDictionary = 0; - ret->favorDecSpeed = 0; - ret->dictionaryFilename = NULL; - ret->removeSrcFile = 0; - return ret; -} - -void LZ4IO_freePreferences(LZ4IO_prefs_t* prefs) -{ - free(prefs); -} - - -int LZ4IO_setDictionaryFilename(LZ4IO_prefs_t* const prefs, const char* dictionaryFilename) -{ - prefs->dictionaryFilename = dictionaryFilename; - prefs->useDictionary = dictionaryFilename != NULL; - return prefs->useDictionary; -} - -/* Default setting : passThrough = 0; return : passThrough mode (0/1) */ -int LZ4IO_setPassThrough(LZ4IO_prefs_t* const prefs, int yes) -{ - prefs->passThrough = (yes!=0); - return prefs->passThrough; -} - - -/* Default setting : overwrite = 1; return : overwrite mode (0/1) */ -int LZ4IO_setOverwrite(LZ4IO_prefs_t* const prefs, int yes) -{ - prefs->overwrite = (yes!=0); - return prefs->overwrite; -} - -/* Default setting : testMode = 0; return : testMode (0/1) */ -int LZ4IO_setTestMode(LZ4IO_prefs_t* const prefs, int yes) -{ - prefs->testMode = (yes!=0); - return prefs->testMode; -} - -/* blockSizeID : valid values : 4-5-6-7 */ -size_t LZ4IO_setBlockSizeID(LZ4IO_prefs_t* const prefs, unsigned bsid) -{ - static const size_t blockSizeTable[] = { 64 KB, 256 KB, 1 MB, 4 MB }; - static const unsigned minBlockSizeID = 4; - static const unsigned maxBlockSizeID = 7; - if ((bsid < minBlockSizeID) || (bsid > maxBlockSizeID)) return 0; - prefs->blockSizeId = (int)bsid; - prefs->blockSize = blockSizeTable[(unsigned)prefs->blockSizeId-minBlockSizeID]; - return prefs->blockSize; -} - -size_t LZ4IO_setBlockSize(LZ4IO_prefs_t* const prefs, size_t blockSize) -{ - static const size_t minBlockSize = 32; - static const size_t maxBlockSize = 4 MB; - unsigned bsid = 0; - if (blockSize < minBlockSize) blockSize = minBlockSize; - if (blockSize > maxBlockSize) blockSize = maxBlockSize; - prefs->blockSize = blockSize; - blockSize--; - /* find which of { 64k, 256k, 1MB, 4MB } is closest to blockSize */ - while (blockSize >>= 2) - bsid++; - if (bsid < 7) bsid = 7; - prefs->blockSizeId = (int)(bsid-3); - return prefs->blockSize; -} - -/* Default setting : 1 == independent blocks */ -int LZ4IO_setBlockMode(LZ4IO_prefs_t* const prefs, LZ4IO_blockMode_t blockMode) -{ - prefs->blockIndependence = (blockMode == LZ4IO_blockIndependent); - return prefs->blockIndependence; -} - -/* Default setting : 0 == no block checksum */ -int LZ4IO_setBlockChecksumMode(LZ4IO_prefs_t* const prefs, int enable) -{ - prefs->blockChecksum = (enable != 0); - return prefs->blockChecksum; -} - -/* Default setting : 1 == checksum enabled */ -int LZ4IO_setStreamChecksumMode(LZ4IO_prefs_t* const prefs, int enable) -{ - prefs->streamChecksum = (enable != 0); - return prefs->streamChecksum; -} - -/* Default setting : 0 (no notification) */ -int LZ4IO_setNotificationLevel(int level) -{ - g_displayLevel = level; - return g_displayLevel; -} - -/* Default setting : 1 (auto: enabled on file, disabled on stdout) */ -int LZ4IO_setSparseFile(LZ4IO_prefs_t* const prefs, int enable) -{ - prefs->sparseFileSupport = 2*(enable!=0); /* 2==force enable */ - return prefs->sparseFileSupport; -} - -/* Default setting : 0 (disabled) */ -int LZ4IO_setContentSize(LZ4IO_prefs_t* const prefs, int enable) -{ - prefs->contentSizeFlag = (enable!=0); - return prefs->contentSizeFlag; -} - -/* Default setting : 0 (disabled) */ -void LZ4IO_favorDecSpeed(LZ4IO_prefs_t* const prefs, int favor) -{ - prefs->favorDecSpeed = (favor!=0); -} - -void LZ4IO_setRemoveSrcFile(LZ4IO_prefs_t* const prefs, unsigned flag) -{ - prefs->removeSrcFile = (flag>0); -} - - - -/* ************************************************************************ ** -** ********************** LZ4 File / Pipe compression ********************* ** -** ************************************************************************ */ - -static int LZ4IO_isSkippableMagicNumber(unsigned int magic) { - return (magic & LZ4IO_SKIPPABLEMASK) == LZ4IO_SKIPPABLE0; -} - - -/** LZ4IO_openSrcFile() : - * condition : `srcFileName` must be non-NULL. - * @result : FILE* to `dstFileName`, or NULL if it fails */ -static FILE* LZ4IO_openSrcFile(const char* srcFileName) -{ - FILE* f; - - if (!strcmp (srcFileName, stdinmark)) { - DISPLAYLEVEL(4,"Using stdin for input\n"); - f = stdin; - SET_BINARY_MODE(stdin); - } else { - f = fopen(srcFileName, "rb"); - if ( f==NULL ) DISPLAYLEVEL(1, "%s: %s \n", srcFileName, strerror(errno)); - } - - return f; -} - -/** FIO_openDstFile() : - * prefs is writable, because sparseFileSupport might be updated. - * condition : `dstFileName` must be non-NULL. - * @result : FILE* to `dstFileName`, or NULL if it fails */ -static FILE* LZ4IO_openDstFile(const char* dstFileName, const LZ4IO_prefs_t* const prefs) -{ - FILE* f; - assert(dstFileName != NULL); - - if (!strcmp (dstFileName, stdoutmark)) { - DISPLAYLEVEL(4, "Using stdout for output \n"); - f = stdout; - SET_BINARY_MODE(stdout); - if (prefs->sparseFileSupport==1) { - DISPLAYLEVEL(4, "Sparse File Support automatically disabled on stdout ;" - " to force-enable it, add --sparse command \n"); - } - } else { - if (!prefs->overwrite && strcmp (dstFileName, nulmark)) { /* Check if destination file already exists */ - FILE* const testf = fopen( dstFileName, "rb" ); - if (testf != NULL) { /* dest exists, prompt for overwrite authorization */ - fclose(testf); - if (g_displayLevel <= 1) { /* No interaction possible */ - DISPLAY("%s already exists; not overwritten \n", dstFileName); - return NULL; - } - DISPLAY("%s already exists; do you wish to overwrite (y/N) ? ", dstFileName); - { int ch = getchar(); - if ((ch!='Y') && (ch!='y')) { - DISPLAY(" not overwritten \n"); - return NULL; - } - while ((ch!=EOF) && (ch!='\n')) ch = getchar(); /* flush rest of input line */ - } } } - f = fopen( dstFileName, "wb" ); - if (f==NULL) DISPLAYLEVEL(1, "%s: %s\n", dstFileName, strerror(errno)); - } - - /* sparse file */ - { int const sparseMode = (prefs->sparseFileSupport - (f==stdout)) > 0; - if (f && sparseMode) { SET_SPARSE_FILE_MODE(f); } - } - - return f; -} - - - -/*************************************** -* Legacy Compression -***************************************/ - -/* unoptimized version; solves endianess & alignment issues */ -static void LZ4IO_writeLE32 (void* p, unsigned value32) -{ - unsigned char* const dstPtr = (unsigned char*)p; - dstPtr[0] = (unsigned char)value32; - dstPtr[1] = (unsigned char)(value32 >> 8); - dstPtr[2] = (unsigned char)(value32 >> 16); - dstPtr[3] = (unsigned char)(value32 >> 24); -} - -static int LZ4IO_LZ4_compress(const char* src, char* dst, int srcSize, int dstSize, int cLevel) -{ - (void)cLevel; - return LZ4_compress_fast(src, dst, srcSize, dstSize, 1); -} - -/* LZ4IO_compressFilename_Legacy : - * This function is intentionally "hidden" (not published in .h) - * It generates compressed streams using the old 'legacy' format */ -int LZ4IO_compressFilename_Legacy(const char* input_filename, const char* output_filename, - int compressionlevel, const LZ4IO_prefs_t* prefs) -{ - typedef int (*compress_f)(const char* src, char* dst, int srcSize, int dstSize, int cLevel); - compress_f const compressionFunction = (compressionlevel < 3) ? LZ4IO_LZ4_compress : LZ4_compress_HC; - unsigned long long filesize = 0; - unsigned long long compressedfilesize = MAGICNUMBER_SIZE; - char* in_buff; - char* out_buff; - const int outBuffSize = LZ4_compressBound(LEGACY_BLOCKSIZE); - FILE* const finput = LZ4IO_openSrcFile(input_filename); - FILE* foutput; - clock_t clockEnd; - - /* Init */ - clock_t const clockStart = clock(); - if (finput == NULL) - EXM_THROW(20, "%s : open file error ", input_filename); - - foutput = LZ4IO_openDstFile(output_filename, prefs); - if (foutput == NULL) { - fclose(finput); - EXM_THROW(20, "%s : open file error ", input_filename); - } - - /* Allocate Memory */ - in_buff = (char*)malloc(LEGACY_BLOCKSIZE); - out_buff = (char*)malloc((size_t)outBuffSize + 4); - if (!in_buff || !out_buff) - EXM_THROW(21, "Allocation error : not enough memory"); - - /* Write Archive Header */ - LZ4IO_writeLE32(out_buff, LEGACY_MAGICNUMBER); - if (fwrite(out_buff, 1, MAGICNUMBER_SIZE, foutput) != MAGICNUMBER_SIZE) - EXM_THROW(22, "Write error : cannot write header"); - - /* Main Loop */ - while (1) { - int outSize; - /* Read Block */ - size_t const inSize = fread(in_buff, (size_t)1, (size_t)LEGACY_BLOCKSIZE, finput); - if (inSize == 0) break; - assert(inSize <= LEGACY_BLOCKSIZE); - filesize += inSize; - - /* Compress Block */ - outSize = compressionFunction(in_buff, out_buff+4, (int)inSize, outBuffSize, compressionlevel); - assert(outSize >= 0); - compressedfilesize += (unsigned long long)outSize+4; - DISPLAYUPDATE(2, "\rRead : %i MB ==> %.2f%% ", - (int)(filesize>>20), (double)compressedfilesize/filesize*100); - - /* Write Block */ - assert(outSize > 0); - assert(outSize < outBuffSize); - LZ4IO_writeLE32(out_buff, (unsigned)outSize); - if (fwrite(out_buff, 1, (size_t)outSize+4, foutput) != (size_t)(outSize+4)) { - EXM_THROW(24, "Write error : cannot write compressed block"); - } } - if (ferror(finput)) EXM_THROW(25, "Error while reading %s ", input_filename); - - /* Status */ - clockEnd = clock(); - if (clockEnd==clockStart) clockEnd+=1; /* avoid division by zero (speed) */ - filesize += !filesize; /* avoid division by zero (ratio) */ - DISPLAYLEVEL(2, "\r%79s\r", ""); /* blank line */ - DISPLAYLEVEL(2,"Compressed %llu bytes into %llu bytes ==> %.2f%%\n", - filesize, compressedfilesize, (double)compressedfilesize / filesize * 100); - { double const seconds = (double)(clockEnd - clockStart) / CLOCKS_PER_SEC; - DISPLAYLEVEL(4,"Done in %.2f s ==> %.2f MB/s\n", seconds, - (double)filesize / seconds / 1024 / 1024); - } - - /* Close & Free */ - free(in_buff); - free(out_buff); - fclose(finput); - if (strcmp(output_filename,stdoutmark)) fclose(foutput); /* do not close stdout */ - - return 0; -} - -#define FNSPACE 30 -/* LZ4IO_compressMultipleFilenames_Legacy : - * This function is intentionally "hidden" (not published in .h) - * It generates multiple compressed streams using the old 'legacy' format */ -int LZ4IO_compressMultipleFilenames_Legacy( - const char** inFileNamesTable, int ifntSize, - const char* suffix, - int compressionLevel, const LZ4IO_prefs_t* prefs) -{ - int i; - int missed_files = 0; - char* dstFileName = (char*)malloc(FNSPACE); - size_t ofnSize = FNSPACE; - const size_t suffixSize = strlen(suffix); - - if (dstFileName == NULL) return ifntSize; /* not enough memory */ - - /* loop on each file */ - for (i=0; i0); - - if (dictLen > LZ4_MAX_DICT_SIZE) { - dictLen = LZ4_MAX_DICT_SIZE; - } - - *dictSize = dictLen; - - dictStart = (circularBufSize + dictEnd - dictLen) % circularBufSize; - - if (dictStart == 0) { - /* We're in the simple case where the dict starts at the beginning of our circular buffer. */ - dictBuf = circularBuf; - circularBuf = NULL; - } else { - /* Otherwise, we will alloc a new buffer and copy our dict into that. */ - dictBuf = (char *)malloc(dictLen ? dictLen : 1); - if (!dictBuf) EXM_THROW(25, "Allocation error : not enough memory"); - - memcpy(dictBuf, circularBuf + dictStart, circularBufSize - dictStart); - memcpy(dictBuf + circularBufSize - dictStart, circularBuf, dictLen - (circularBufSize - dictStart)); - } - - fclose(dictFile); - free(circularBuf); - - return dictBuf; -} - -static LZ4F_CDict* LZ4IO_createCDict(const LZ4IO_prefs_t* const prefs) -{ - size_t dictionarySize; - void* dictionaryBuffer; - LZ4F_CDict* cdict; - if (!prefs->useDictionary) return NULL; - dictionaryBuffer = LZ4IO_createDict(&dictionarySize, prefs->dictionaryFilename); - if (!dictionaryBuffer) EXM_THROW(25, "Dictionary error : could not create dictionary"); - cdict = LZ4F_createCDict(dictionaryBuffer, dictionarySize); - free(dictionaryBuffer); - return cdict; -} - -static cRess_t LZ4IO_createCResources(const LZ4IO_prefs_t* const prefs) -{ - const size_t blockSize = prefs->blockSize; - cRess_t ress; - - LZ4F_errorCode_t const errorCode = LZ4F_createCompressionContext(&(ress.ctx), LZ4F_VERSION); - if (LZ4F_isError(errorCode)) EXM_THROW(30, "Allocation error : can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); - - /* Allocate Memory */ - ress.srcBuffer = malloc(blockSize); - ress.srcBufferSize = blockSize; - ress.dstBufferSize = LZ4F_compressFrameBound(blockSize, NULL); /* cover worst case */ - ress.dstBuffer = malloc(ress.dstBufferSize); - if (!ress.srcBuffer || !ress.dstBuffer) EXM_THROW(31, "Allocation error : not enough memory"); - - ress.cdict = LZ4IO_createCDict(prefs); - - return ress; -} - -static void LZ4IO_freeCResources(cRess_t ress) -{ - free(ress.srcBuffer); - free(ress.dstBuffer); - - LZ4F_freeCDict(ress.cdict); - ress.cdict = NULL; - - { LZ4F_errorCode_t const errorCode = LZ4F_freeCompressionContext(ress.ctx); - if (LZ4F_isError(errorCode)) EXM_THROW(38, "Error : can't free LZ4F context resource : %s", LZ4F_getErrorName(errorCode)); } -} - -/* - * LZ4IO_compressFilename_extRess() - * result : 0 : compression completed correctly - * 1 : missing or pb opening srcFileName - */ -static int -LZ4IO_compressFilename_extRess(cRess_t ress, - const char* srcFileName, const char* dstFileName, - int compressionLevel, const LZ4IO_prefs_t* const io_prefs) -{ - unsigned long long filesize = 0; - unsigned long long compressedfilesize = 0; - FILE* dstFile; - void* const srcBuffer = ress.srcBuffer; - void* const dstBuffer = ress.dstBuffer; - const size_t dstBufferSize = ress.dstBufferSize; - const size_t blockSize = io_prefs->blockSize; - size_t readSize; - LZ4F_compressionContext_t ctx = ress.ctx; /* just a pointer */ - LZ4F_preferences_t prefs; - - /* Init */ - FILE* const srcFile = LZ4IO_openSrcFile(srcFileName); - if (srcFile == NULL) return 1; - dstFile = LZ4IO_openDstFile(dstFileName, io_prefs); - if (dstFile == NULL) { fclose(srcFile); return 1; } - memset(&prefs, 0, sizeof(prefs)); - - /* Set compression parameters */ - prefs.autoFlush = 1; - prefs.compressionLevel = compressionLevel; - prefs.frameInfo.blockMode = (LZ4F_blockMode_t)io_prefs->blockIndependence; - prefs.frameInfo.blockSizeID = (LZ4F_blockSizeID_t)io_prefs->blockSizeId; - prefs.frameInfo.blockChecksumFlag = (LZ4F_blockChecksum_t)io_prefs->blockChecksum; - prefs.frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)io_prefs->streamChecksum; - prefs.favorDecSpeed = io_prefs->favorDecSpeed; - if (io_prefs->contentSizeFlag) { - U64 const fileSize = UTIL_getOpenFileSize(srcFile); - prefs.frameInfo.contentSize = fileSize; /* == 0 if input == stdin */ - if (fileSize==0) - DISPLAYLEVEL(3, "Warning : cannot determine input content size \n"); - } - - /* read first block */ - readSize = fread(srcBuffer, (size_t)1, blockSize, srcFile); - if (ferror(srcFile)) EXM_THROW(30, "Error reading %s ", srcFileName); - filesize += readSize; - - /* single-block file */ - if (readSize < blockSize) { - /* Compress in single pass */ - size_t const cSize = LZ4F_compressFrame_usingCDict(ctx, dstBuffer, dstBufferSize, srcBuffer, readSize, ress.cdict, &prefs); - if (LZ4F_isError(cSize)) - EXM_THROW(31, "Compression failed : %s", LZ4F_getErrorName(cSize)); - compressedfilesize = cSize; - DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%% ", - (unsigned)(filesize>>20), (double)compressedfilesize/(filesize+!filesize)*100); /* avoid division by zero */ - - /* Write Block */ - if (fwrite(dstBuffer, 1, cSize, dstFile) != cSize) { - EXM_THROW(32, "Write error : failed writing single-block compressed frame"); - } } - - else - - /* multiple-blocks file */ - { - /* Write Frame Header */ - size_t const headerSize = LZ4F_compressBegin_usingCDict(ctx, dstBuffer, dstBufferSize, ress.cdict, &prefs); - if (LZ4F_isError(headerSize)) EXM_THROW(33, "File header generation failed : %s", LZ4F_getErrorName(headerSize)); - if (fwrite(dstBuffer, 1, headerSize, dstFile) != headerSize) - EXM_THROW(34, "Write error : cannot write header"); - compressedfilesize += headerSize; - - /* Main Loop - one block at a time */ - while (readSize>0) { - size_t const outSize = LZ4F_compressUpdate(ctx, dstBuffer, dstBufferSize, srcBuffer, readSize, NULL); - if (LZ4F_isError(outSize)) - EXM_THROW(35, "Compression failed : %s", LZ4F_getErrorName(outSize)); - compressedfilesize += outSize; - DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%% ", - (unsigned)(filesize>>20), (double)compressedfilesize/filesize*100); - - /* Write Block */ - if (fwrite(dstBuffer, 1, outSize, dstFile) != outSize) - EXM_THROW(36, "Write error : cannot write compressed block"); - - /* Read next block */ - readSize = fread(srcBuffer, (size_t)1, (size_t)blockSize, srcFile); - filesize += readSize; - } - if (ferror(srcFile)) EXM_THROW(37, "Error reading %s ", srcFileName); - - /* End of Frame mark */ - { size_t const endSize = LZ4F_compressEnd(ctx, dstBuffer, dstBufferSize, NULL); - if (LZ4F_isError(endSize)) - EXM_THROW(38, "End of frame error : %s", LZ4F_getErrorName(endSize)); - if (fwrite(dstBuffer, 1, endSize, dstFile) != endSize) - EXM_THROW(39, "Write error : cannot write end of frame"); - compressedfilesize += endSize; - } } - - /* Release file handlers */ - fclose (srcFile); - if (strcmp(dstFileName,stdoutmark)) fclose (dstFile); /* do not close stdout */ - - /* Copy owner, file permissions and modification time */ - { stat_t statbuf; - if (strcmp (srcFileName, stdinmark) - && strcmp (dstFileName, stdoutmark) - && strcmp (dstFileName, nulmark) - && UTIL_getFileStat(srcFileName, &statbuf)) { - UTIL_setFileStat(dstFileName, &statbuf); - } } - - if (io_prefs->removeSrcFile) { /* remove source file : --rm */ - if (remove(srcFileName)) - EXM_THROW(40, "Remove error : %s: %s", srcFileName, strerror(errno)); - } - - /* Final Status */ - DISPLAYLEVEL(2, "\r%79s\r", ""); - DISPLAYLEVEL(2, "Compressed %llu bytes into %llu bytes ==> %.2f%%\n", - filesize, compressedfilesize, - (double)compressedfilesize / (filesize + !filesize /* avoid division by zero */ ) * 100); - - return 0; -} - - -int LZ4IO_compressFilename(const char* srcFileName, const char* dstFileName, int compressionLevel, const LZ4IO_prefs_t* prefs) -{ - UTIL_time_t const timeStart = UTIL_getTime(); - clock_t const cpuStart = clock(); - cRess_t const ress = LZ4IO_createCResources(prefs); - - int const result = LZ4IO_compressFilename_extRess(ress, srcFileName, dstFileName, compressionLevel, prefs); - - /* Free resources */ - LZ4IO_freeCResources(ress); - - /* Final Status */ - { clock_t const cpuEnd = clock(); - double const cpuLoad_s = (double)(cpuEnd - cpuStart) / CLOCKS_PER_SEC; - U64 const timeLength_ns = UTIL_clockSpanNano(timeStart); - double const timeLength_s = (double)timeLength_ns / 1000000000; - DISPLAYLEVEL(4, "Completed in %.2f sec (cpu load : %.0f%%)\n", - timeLength_s, (cpuLoad_s / timeLength_s) * 100); - } - - return result; -} - - -int LZ4IO_compressMultipleFilenames( - const char** inFileNamesTable, int ifntSize, - const char* suffix, - int compressionLevel, - const LZ4IO_prefs_t* prefs) -{ - int i; - int missed_files = 0; - char* dstFileName = (char*)malloc(FNSPACE); - size_t ofnSize = FNSPACE; - const size_t suffixSize = strlen(suffix); - cRess_t ress; - - if (dstFileName == NULL) return ifntSize; /* not enough memory */ - ress = LZ4IO_createCResources(prefs); - - /* loop on each file */ - for (i=0; i= 4 */ -static unsigned LZ4IO_readLE32 (const void* s) -{ - const unsigned char* const srcPtr = (const unsigned char*)s; - unsigned value32 = srcPtr[0]; - value32 += (unsigned)srcPtr[1] << 8; - value32 += (unsigned)srcPtr[2] << 16; - value32 += (unsigned)srcPtr[3] << 24; - return value32; -} - - -static unsigned -LZ4IO_fwriteSparse(FILE* file, - const void* buffer, size_t bufferSize, - int sparseFileSupport, - unsigned storedSkips) -{ - const size_t sizeT = sizeof(size_t); - const size_t maskT = sizeT -1 ; - const size_t* const bufferT = (const size_t*)buffer; /* Buffer is supposed malloc'ed, hence aligned on size_t */ - const size_t* ptrT = bufferT; - size_t bufferSizeT = bufferSize / sizeT; - const size_t* const bufferTEnd = bufferT + bufferSizeT; - const size_t segmentSizeT = (32 KB) / sizeT; - int const sparseMode = (sparseFileSupport - (file==stdout)) > 0; - - if (!sparseMode) { /* normal write */ - size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file); - if (sizeCheck != bufferSize) EXM_THROW(70, "Write error : cannot write decoded block"); - return 0; - } - - /* avoid int overflow */ - if (storedSkips > 1 GB) { - int const seekResult = UTIL_fseek(file, 1 GB, SEEK_CUR); - if (seekResult != 0) EXM_THROW(71, "1 GB skip error (sparse file support)"); - storedSkips -= 1 GB; - } - - while (ptrT < bufferTEnd) { - size_t seg0SizeT = segmentSizeT; - size_t nb0T; - - /* count leading zeros */ - if (seg0SizeT > bufferSizeT) seg0SizeT = bufferSizeT; - bufferSizeT -= seg0SizeT; - for (nb0T=0; (nb0T < seg0SizeT) && (ptrT[nb0T] == 0); nb0T++) ; - storedSkips += (unsigned)(nb0T * sizeT); - - if (nb0T != seg0SizeT) { /* not all 0s */ - errno = 0; - { int const seekResult = UTIL_fseek(file, storedSkips, SEEK_CUR); - if (seekResult) EXM_THROW(72, "Sparse skip error(%d): %s ; try --no-sparse", (int)errno, strerror(errno)); - } - storedSkips = 0; - seg0SizeT -= nb0T; - ptrT += nb0T; - { size_t const sizeCheck = fwrite(ptrT, sizeT, seg0SizeT, file); - if (sizeCheck != seg0SizeT) EXM_THROW(73, "Write error : cannot write decoded block"); - } } - ptrT += seg0SizeT; - } - - if (bufferSize & maskT) { /* size not multiple of sizeT : implies end of block */ - const char* const restStart = (const char*)bufferTEnd; - const char* restPtr = restStart; - size_t const restSize = bufferSize & maskT; - const char* const restEnd = restStart + restSize; - for (; (restPtr < restEnd) && (*restPtr == 0); restPtr++) ; - storedSkips += (unsigned) (restPtr - restStart); - if (restPtr != restEnd) { - int const seekResult = UTIL_fseek(file, storedSkips, SEEK_CUR); - if (seekResult) EXM_THROW(74, "Sparse skip error ; try --no-sparse"); - storedSkips = 0; - { size_t const sizeCheck = fwrite(restPtr, 1, (size_t)(restEnd - restPtr), file); - if (sizeCheck != (size_t)(restEnd - restPtr)) EXM_THROW(75, "Write error : cannot write decoded end of block"); - } } - } - - return storedSkips; -} - -static void LZ4IO_fwriteSparseEnd(FILE* file, unsigned storedSkips) -{ - if (storedSkips>0) { /* implies sparseFileSupport>0 */ - const char lastZeroByte[1] = { 0 }; - if (UTIL_fseek(file, storedSkips-1, SEEK_CUR) != 0) - EXM_THROW(69, "Final skip error (sparse file)\n"); - if (fwrite(lastZeroByte, 1, 1, file) != 1) - EXM_THROW(69, "Write error : cannot write last zero\n"); - } -} - - -static unsigned g_magicRead = 0; /* out-parameter of LZ4IO_decodeLegacyStream() */ -static unsigned long long LZ4IO_decodeLegacyStream(FILE* finput, FILE* foutput, const LZ4IO_prefs_t* prefs) -{ - unsigned long long streamSize = 0; - unsigned storedSkips = 0; - - /* Allocate Memory */ - char* const in_buff = (char*)malloc((size_t)LZ4_compressBound(LEGACY_BLOCKSIZE)); - char* const out_buff = (char*)malloc(LEGACY_BLOCKSIZE); - if (!in_buff || !out_buff) EXM_THROW(51, "Allocation error : not enough memory"); - - /* Main Loop */ - while (1) { - unsigned int blockSize; - - /* Block Size */ - { size_t const sizeCheck = fread(in_buff, 1, 4, finput); - if (sizeCheck == 0) break; /* Nothing to read : file read is completed */ - if (sizeCheck != 4) EXM_THROW(52, "Read error : cannot access block size "); } - blockSize = LZ4IO_readLE32(in_buff); /* Convert to Little Endian */ - if (blockSize > LZ4_COMPRESSBOUND(LEGACY_BLOCKSIZE)) { - /* Cannot read next block : maybe new stream ? */ - g_magicRead = blockSize; - break; - } - - /* Read Block */ - { size_t const sizeCheck = fread(in_buff, 1, blockSize, finput); - if (sizeCheck!=blockSize) EXM_THROW(52, "Read error : cannot access compressed block !"); } - - /* Decode Block */ - { int const decodeSize = LZ4_decompress_safe(in_buff, out_buff, (int)blockSize, LEGACY_BLOCKSIZE); - if (decodeSize < 0) EXM_THROW(53, "Decoding Failed ! Corrupted input detected !"); - streamSize += (unsigned long long)decodeSize; - /* Write Block */ - storedSkips = LZ4IO_fwriteSparse(foutput, out_buff, (size_t)decodeSize, prefs->sparseFileSupport, storedSkips); /* success or die */ - } } - if (ferror(finput)) EXM_THROW(54, "Read error : ferror"); - - LZ4IO_fwriteSparseEnd(foutput, storedSkips); - - /* Free */ - free(in_buff); - free(out_buff); - - return streamSize; -} - - - -typedef struct { - void* srcBuffer; - size_t srcBufferSize; - void* dstBuffer; - size_t dstBufferSize; - FILE* dstFile; - LZ4F_decompressionContext_t dCtx; - void* dictBuffer; - size_t dictBufferSize; -} dRess_t; - -static void LZ4IO_loadDDict(dRess_t* ress, const LZ4IO_prefs_t* const prefs) -{ - if (!prefs->useDictionary) { - ress->dictBuffer = NULL; - ress->dictBufferSize = 0; - return; - } - - ress->dictBuffer = LZ4IO_createDict(&ress->dictBufferSize, prefs->dictionaryFilename); - if (!ress->dictBuffer) EXM_THROW(25, "Dictionary error : could not create dictionary"); -} - -static const size_t LZ4IO_dBufferSize = 64 KB; -static dRess_t LZ4IO_createDResources(const LZ4IO_prefs_t* const prefs) -{ - dRess_t ress; - - /* init */ - LZ4F_errorCode_t const errorCode = LZ4F_createDecompressionContext(&ress.dCtx, LZ4F_VERSION); - if (LZ4F_isError(errorCode)) EXM_THROW(60, "Can't create LZ4F context : %s", LZ4F_getErrorName(errorCode)); - - /* Allocate Memory */ - ress.srcBufferSize = LZ4IO_dBufferSize; - ress.srcBuffer = malloc(ress.srcBufferSize); - ress.dstBufferSize = LZ4IO_dBufferSize; - ress.dstBuffer = malloc(ress.dstBufferSize); - if (!ress.srcBuffer || !ress.dstBuffer) EXM_THROW(61, "Allocation error : not enough memory"); - - LZ4IO_loadDDict(&ress, prefs); - - ress.dstFile = NULL; - return ress; -} - -static void LZ4IO_freeDResources(dRess_t ress) -{ - LZ4F_errorCode_t errorCode = LZ4F_freeDecompressionContext(ress.dCtx); - if (LZ4F_isError(errorCode)) EXM_THROW(69, "Error : can't free LZ4F context resource : %s", LZ4F_getErrorName(errorCode)); - free(ress.srcBuffer); - free(ress.dstBuffer); - free(ress.dictBuffer); -} - - -static unsigned long long -LZ4IO_decompressLZ4F(dRess_t ress, - FILE* const srcFile, FILE* const dstFile, - const LZ4IO_prefs_t* const prefs) -{ - unsigned long long filesize = 0; - LZ4F_errorCode_t nextToLoad; - unsigned storedSkips = 0; - - /* Init feed with magic number (already consumed from FILE* sFile) */ - { size_t inSize = MAGICNUMBER_SIZE; - size_t outSize= 0; - LZ4IO_writeLE32(ress.srcBuffer, LZ4IO_MAGICNUMBER); - nextToLoad = LZ4F_decompress_usingDict(ress.dCtx, ress.dstBuffer, &outSize, ress.srcBuffer, &inSize, ress.dictBuffer, ress.dictBufferSize, NULL); - if (LZ4F_isError(nextToLoad)) EXM_THROW(62, "Header error : %s", LZ4F_getErrorName(nextToLoad)); - } - - /* Main Loop */ - for (;nextToLoad;) { - size_t readSize; - size_t pos = 0; - size_t decodedBytes = ress.dstBufferSize; - - /* Read input */ - if (nextToLoad > ress.srcBufferSize) nextToLoad = ress.srcBufferSize; - readSize = fread(ress.srcBuffer, 1, nextToLoad, srcFile); - if (!readSize) break; /* reached end of file or stream */ - - while ((pos < readSize) || (decodedBytes == ress.dstBufferSize)) { /* still to read, or still to flush */ - /* Decode Input (at least partially) */ - size_t remaining = readSize - pos; - decodedBytes = ress.dstBufferSize; - nextToLoad = LZ4F_decompress_usingDict(ress.dCtx, ress.dstBuffer, &decodedBytes, (char*)(ress.srcBuffer)+pos, &remaining, ress.dictBuffer, ress.dictBufferSize, NULL); - if (LZ4F_isError(nextToLoad)) EXM_THROW(66, "Decompression error : %s", LZ4F_getErrorName(nextToLoad)); - pos += remaining; - - /* Write Block */ - if (decodedBytes) { - if (!prefs->testMode) - storedSkips = LZ4IO_fwriteSparse(dstFile, ress.dstBuffer, decodedBytes, prefs->sparseFileSupport, storedSkips); - filesize += decodedBytes; - DISPLAYUPDATE(2, "\rDecompressed : %u MB ", (unsigned)(filesize>>20)); - } - - if (!nextToLoad) break; - } - } - /* can be out because readSize == 0, which could be an fread() error */ - if (ferror(srcFile)) EXM_THROW(67, "Read error"); - - if (!prefs->testMode) LZ4IO_fwriteSparseEnd(dstFile, storedSkips); - if (nextToLoad!=0) EXM_THROW(68, "Unfinished stream"); - - return filesize; -} - - -/* LZ4IO_passThrough: - * just output the same content as input, no decoding. - * This is a capability of zcat, and by extension lz4cat - * MNstore : contain the first MAGICNUMBER_SIZE bytes already read from finput - */ -#define PTSIZE (64 KB) -#define PTSIZET (PTSIZE / sizeof(size_t)) -static unsigned long long -LZ4IO_passThrough(FILE* finput, FILE* foutput, - unsigned char MNstore[MAGICNUMBER_SIZE], - int sparseFileSupport) -{ - size_t buffer[PTSIZET]; - size_t readBytes = 1; - unsigned long long total = MAGICNUMBER_SIZE; - unsigned storedSkips = 0; - - if (fwrite(MNstore, 1, MAGICNUMBER_SIZE, foutput) != MAGICNUMBER_SIZE) { - EXM_THROW(50, "Pass-through write error"); - } - while (readBytes) { - readBytes = fread(buffer, 1, sizeof(buffer), finput); - total += readBytes; - storedSkips = LZ4IO_fwriteSparse(foutput, buffer, readBytes, sparseFileSupport, storedSkips); - } - if (ferror(finput)) EXM_THROW(51, "Read Error"); - - LZ4IO_fwriteSparseEnd(foutput, storedSkips); - return total; -} - - -/** Safely handle cases when (unsigned)offset > LONG_MAX */ -static int fseek_u32(FILE *fp, unsigned offset, int where) -{ - const unsigned stepMax = 1U << 30; - int errorNb = 0; - - if (where != SEEK_CUR) return -1; /* Only allows SEEK_CUR */ - while (offset > 0) { - unsigned s = offset; - if (s > stepMax) s = stepMax; - errorNb = UTIL_fseek(fp, (long) s, SEEK_CUR); - if (errorNb != 0) break; - offset -= s; - } - return errorNb; -} - -#define ENDOFSTREAM ((unsigned long long)-1) -static unsigned long long -selectDecoder(dRess_t ress, - FILE* finput, FILE* foutput, - const LZ4IO_prefs_t* const prefs) -{ - unsigned char MNstore[MAGICNUMBER_SIZE]; - unsigned magicNumber; - static unsigned nbFrames = 0; - - /* init */ - nbFrames++; - - /* Check Archive Header */ - if (g_magicRead) { /* magic number already read from finput (see legacy frame)*/ - magicNumber = g_magicRead; - g_magicRead = 0; - } else { - size_t const nbReadBytes = fread(MNstore, 1, MAGICNUMBER_SIZE, finput); - if (nbReadBytes==0) { nbFrames = 0; return ENDOFSTREAM; } /* EOF */ - if (nbReadBytes != MAGICNUMBER_SIZE) - EXM_THROW(40, "Unrecognized header : Magic Number unreadable"); - magicNumber = LZ4IO_readLE32(MNstore); /* Little Endian format */ - } - if (LZ4IO_isSkippableMagicNumber(magicNumber)) - magicNumber = LZ4IO_SKIPPABLE0; /* fold skippable magic numbers */ - - switch(magicNumber) - { - case LZ4IO_MAGICNUMBER: - return LZ4IO_decompressLZ4F(ress, finput, foutput, prefs); - case LEGACY_MAGICNUMBER: - DISPLAYLEVEL(4, "Detected : Legacy format \n"); - return LZ4IO_decodeLegacyStream(finput, foutput, prefs); - case LZ4IO_SKIPPABLE0: - DISPLAYLEVEL(4, "Skipping detected skippable area \n"); - { size_t const nbReadBytes = fread(MNstore, 1, 4, finput); - if (nbReadBytes != 4) - EXM_THROW(42, "Stream error : skippable size unreadable"); - } - { unsigned const size = LZ4IO_readLE32(MNstore); - int const errorNb = fseek_u32(finput, size, SEEK_CUR); - if (errorNb != 0) - EXM_THROW(43, "Stream error : cannot skip skippable area"); - } - return 0; - EXTENDED_FORMAT; /* macro extension for custom formats */ - default: - if (nbFrames == 1) { /* just started */ - /* Wrong magic number at the beginning of 1st stream */ - if (!prefs->testMode && prefs->overwrite && prefs->passThrough) { - nbFrames = 0; - return LZ4IO_passThrough(finput, foutput, MNstore, prefs->sparseFileSupport); - } - EXM_THROW(44,"Unrecognized header : file cannot be decoded"); - } - { long int const position = ftell(finput); /* only works for files < 2 GB */ - DISPLAYLEVEL(2, "Stream followed by undecodable data "); - if (position != -1L) - DISPLAYLEVEL(2, "at position %i ", (int)position); - DISPLAYLEVEL(2, "\n"); - } - return ENDOFSTREAM; - } -} - - -static int -LZ4IO_decompressSrcFile(dRess_t ress, - const char* input_filename, const char* output_filename, - const LZ4IO_prefs_t* const prefs) -{ - FILE* const foutput = ress.dstFile; - unsigned long long filesize = 0; - - /* Init */ - FILE* const finput = LZ4IO_openSrcFile(input_filename); - if (finput==NULL) return 1; - assert(foutput != NULL); - - /* Loop over multiple streams */ - for ( ; ; ) { /* endless loop, see break condition */ - unsigned long long const decodedSize = - selectDecoder(ress, finput, foutput, prefs); - if (decodedSize == ENDOFSTREAM) break; - filesize += decodedSize; - } - - /* Close input */ - fclose(finput); - if (prefs->removeSrcFile) { /* --rm */ - if (remove(input_filename)) - EXM_THROW(45, "Remove error : %s: %s", input_filename, strerror(errno)); - } - - /* Final Status */ - DISPLAYLEVEL(2, "\r%79s\r", ""); - DISPLAYLEVEL(2, "%-20.20s : decoded %llu bytes \n", input_filename, filesize); - (void)output_filename; - - return 0; -} - - -static int -LZ4IO_decompressDstFile(dRess_t ress, - const char* input_filename, const char* output_filename, - const LZ4IO_prefs_t* const prefs) -{ - stat_t statbuf; - int stat_result = 0; - FILE* const foutput = LZ4IO_openDstFile(output_filename, prefs); - if (foutput==NULL) return 1; /* failure */ - - if ( strcmp(input_filename, stdinmark) - && UTIL_getFileStat(input_filename, &statbuf)) - stat_result = 1; - - ress.dstFile = foutput; - LZ4IO_decompressSrcFile(ress, input_filename, output_filename, prefs); - - fclose(foutput); - - /* Copy owner, file permissions and modification time */ - if ( stat_result != 0 - && strcmp (output_filename, stdoutmark) - && strcmp (output_filename, nulmark)) { - UTIL_setFileStat(output_filename, &statbuf); - /* should return value be read ? or is silent fail good enough ? */ - } - - return 0; -} - - -int LZ4IO_decompressFilename(const char* input_filename, const char* output_filename, const LZ4IO_prefs_t* prefs) -{ - dRess_t const ress = LZ4IO_createDResources(prefs); - clock_t const start = clock(); - - int const missingFiles = LZ4IO_decompressDstFile(ress, input_filename, output_filename, prefs); - - clock_t const end = clock(); - double const seconds = (double)(end - start) / CLOCKS_PER_SEC; - DISPLAYLEVEL(4, "Done in %.2f sec \n", seconds); - - LZ4IO_freeDResources(ress); - return missingFiles; -} - - -int LZ4IO_decompressMultipleFilenames( - const char** inFileNamesTable, int ifntSize, - const char* suffix, - const LZ4IO_prefs_t* prefs) -{ - int i; - int skippedFiles = 0; - int missingFiles = 0; - char* outFileName = (char*)malloc(FNSPACE); - size_t ofnSize = FNSPACE; - size_t const suffixSize = strlen(suffix); - dRess_t ress = LZ4IO_createDResources(prefs); - - if (outFileName==NULL) EXM_THROW(70, "Memory allocation error"); - ress.dstFile = LZ4IO_openDstFile(stdoutmark, prefs); - - for (i=0; i= 4); assert(sizeID <= 7); - buffer[1] = (char)(sizeID + '0'); - buffer[2] = (blockMode == LZ4F_blockIndependent) ? 'I' : 'D'; - buffer[3] = 0; - return buffer; -} - -/* buffer : must be valid memory area of at least 10 bytes */ -static const char* LZ4IO_toHuman(long double size, char *buf) -{ - const char units[] = {"\0KMGTPEZY"}; - size_t i = 0; - for (; size >= 1024; i++) size /= 1024; - sprintf(buf, "%.2Lf%c", size, units[i]); - return buf; -} - -/* Get filename without path prefix */ -static const char* LZ4IO_baseName(const char* input_filename) -{ - const char* b = strrchr(input_filename, '/'); - if (!b) b = strrchr(input_filename, '\\'); - if (!b) return input_filename; - return b + 1; -} - -/* Report frame/s information (--list) in verbose mode (-v). - * Will populate file info with fileName and frameSummary where applicable. - * - TODO : - * + report nb of blocks, hence max. possible decompressed size (when not reported in header) - */ -static LZ4IO_infoResult -LZ4IO_getCompressedFileInfo(LZ4IO_cFileInfo_t* cfinfo, const char* input_filename) -{ - LZ4IO_infoResult result = LZ4IO_format_not_known; /* default result (error) */ - unsigned char buffer[LZ4F_HEADER_SIZE_MAX]; - FILE* const finput = LZ4IO_openSrcFile(input_filename); - - if (finput == NULL) return LZ4IO_not_a_file; - cfinfo->fileSize = UTIL_getOpenFileSize(finput); - - while (!feof(finput)) { - LZ4IO_frameInfo_t frameInfo = LZ4IO_INIT_FRAMEINFO; - unsigned magicNumber; - /* Get MagicNumber */ - { size_t const nbReadBytes = fread(buffer, 1, MAGICNUMBER_SIZE, finput); - if (nbReadBytes == 0) { break; } /* EOF */ - result = LZ4IO_format_not_known; /* default result (error) */ - if (nbReadBytes != MAGICNUMBER_SIZE) { - EXM_THROW(40, "Unrecognized header : Magic Number unreadable"); - } } - magicNumber = LZ4IO_readLE32(buffer); /* Little Endian format */ - if (LZ4IO_isSkippableMagicNumber(magicNumber)) - magicNumber = LZ4IO_SKIPPABLE0; /* fold skippable magic numbers */ - - switch (magicNumber) { - case LZ4IO_MAGICNUMBER: - if (cfinfo->frameSummary.frameType != lz4Frame) cfinfo->eqFrameTypes = 0; - /* Get frame info */ - { const size_t readBytes = fread(buffer + MAGICNUMBER_SIZE, 1, LZ4F_HEADER_SIZE_MIN - MAGICNUMBER_SIZE, finput); - if (!readBytes || ferror(finput)) EXM_THROW(71, "Error reading %s", input_filename); - } - { size_t hSize = LZ4F_headerSize(&buffer, LZ4F_HEADER_SIZE_MIN); - if (LZ4F_isError(hSize)) break; - if (hSize > (LZ4F_HEADER_SIZE_MIN + MAGICNUMBER_SIZE)) { - /* We've already read LZ4F_HEADER_SIZE_MIN so read any extra until hSize*/ - const size_t readBytes = fread(buffer + LZ4F_HEADER_SIZE_MIN, 1, hSize - LZ4F_HEADER_SIZE_MIN, finput); - if (!readBytes || ferror(finput)) EXM_THROW(72, "Error reading %s", input_filename); - } - /* Create decompression context */ - { LZ4F_dctx* dctx; - if ( LZ4F_isError(LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION)) ) break; - { unsigned const frameInfoError = LZ4F_isError(LZ4F_getFrameInfo(dctx, &frameInfo.lz4FrameInfo, buffer, &hSize)); - LZ4F_freeDecompressionContext(dctx); - if (frameInfoError) break; - if ((cfinfo->frameSummary.lz4FrameInfo.blockSizeID != frameInfo.lz4FrameInfo.blockSizeID || - cfinfo->frameSummary.lz4FrameInfo.blockMode != frameInfo.lz4FrameInfo.blockMode) - && cfinfo->frameCount != 0) - cfinfo->eqBlockTypes = 0; - { const unsigned long long totalBlocksSize = LZ4IO_skipBlocksData(finput, - frameInfo.lz4FrameInfo.blockChecksumFlag, - frameInfo.lz4FrameInfo.contentChecksumFlag); - if (totalBlocksSize) { - char bTypeBuffer[5]; - LZ4IO_blockTypeID(frameInfo.lz4FrameInfo.blockSizeID, frameInfo.lz4FrameInfo.blockMode, bTypeBuffer); - DISPLAYLEVEL(3, " %6llu %14s %5s %8s", - cfinfo->frameCount + 1, - LZ4IO_frameTypeNames[frameInfo.frameType], - bTypeBuffer, - frameInfo.lz4FrameInfo.contentChecksumFlag ? "XXH32" : "-"); - if (frameInfo.lz4FrameInfo.contentSize) { - { double const ratio = (double)(totalBlocksSize + hSize) / frameInfo.lz4FrameInfo.contentSize * 100; - DISPLAYLEVEL(3, " %20llu %20llu %9.2f%%\n", - totalBlocksSize + hSize, - frameInfo.lz4FrameInfo.contentSize, - ratio); - } - /* Now we've consumed frameInfo we can use it to store the total contentSize */ - frameInfo.lz4FrameInfo.contentSize += cfinfo->frameSummary.lz4FrameInfo.contentSize; - } - else { - DISPLAYLEVEL(3, " %20llu %20s %9s \n", totalBlocksSize + hSize, "-", "-"); - cfinfo->allContentSize = 0; - } - result = LZ4IO_LZ4F_OK; - } } } } } - break; - case LEGACY_MAGICNUMBER: - frameInfo.frameType = legacyFrame; - if (cfinfo->frameSummary.frameType != legacyFrame && cfinfo->frameCount != 0) cfinfo->eqFrameTypes = 0; - cfinfo->eqBlockTypes = 0; - cfinfo->allContentSize = 0; - { const unsigned long long totalBlocksSize = LZ4IO_skipLegacyBlocksData(finput); - if (totalBlocksSize) { - DISPLAYLEVEL(3, " %6llu %14s %5s %8s %20llu %20s %9s\n", - cfinfo->frameCount + 1, - LZ4IO_frameTypeNames[frameInfo.frameType], - "-", "-", - totalBlocksSize + 4, - "-", "-"); - result = LZ4IO_LZ4F_OK; - } } - break; - case LZ4IO_SKIPPABLE0: - frameInfo.frameType = skippableFrame; - if (cfinfo->frameSummary.frameType != skippableFrame && cfinfo->frameCount != 0) cfinfo->eqFrameTypes = 0; - cfinfo->eqBlockTypes = 0; - cfinfo->allContentSize = 0; - { size_t const nbReadBytes = fread(buffer, 1, 4, finput); - if (nbReadBytes != 4) - EXM_THROW(42, "Stream error : skippable size unreadable"); - } - { unsigned const size = LZ4IO_readLE32(buffer); - int const errorNb = fseek_u32(finput, size, SEEK_CUR); - if (errorNb != 0) - EXM_THROW(43, "Stream error : cannot skip skippable area"); - DISPLAYLEVEL(3, " %6llu %14s %5s %8s %20u %20s %9s\n", - cfinfo->frameCount + 1, - "SkippableFrame", - "-", "-", size + 8, "-", "-"); - - result = LZ4IO_LZ4F_OK; - } - break; - default: - { long int const position = ftell(finput); /* only works for files < 2 GB */ - DISPLAYLEVEL(3, "Stream followed by undecodable data "); - if (position != -1L) - DISPLAYLEVEL(3, "at position %i ", (int)position); - DISPLAYLEVEL(3, "\n"); - } - break; - } - if (result != LZ4IO_LZ4F_OK) break; - cfinfo->frameSummary = frameInfo; - cfinfo->frameCount++; - } /* while (!feof(finput)) */ - fclose(finput); - return result; -} - - -int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, size_t ifnIdx) -{ - int result = 0; - size_t idx = 0; - if (g_displayLevel < 3) { - DISPLAYOUT("%10s %14s %5s %11s %13s %9s %s\n", - "Frames", "Type", "Block", "Compressed", "Uncompressed", "Ratio", "Filename"); - } - for (; idx < ifnIdx; idx++) { - /* Get file info */ - LZ4IO_cFileInfo_t cfinfo = LZ4IO_INIT_CFILEINFO; - cfinfo.fileName = LZ4IO_baseName(inFileNames[idx]); - if (!UTIL_isRegFile(inFileNames[idx])) { - DISPLAYLEVEL(1, "lz4: %s is not a regular file \n", inFileNames[idx]); - return 0; - } - DISPLAYLEVEL(3, "%s(%llu/%llu)\n", cfinfo.fileName, (unsigned long long)idx + 1, (unsigned long long)ifnIdx); - DISPLAYLEVEL(3, " %6s %14s %5s %8s %20s %20s %9s\n", - "Frame", "Type", "Block", "Checksum", "Compressed", "Uncompressed", "Ratio") - { LZ4IO_infoResult const op_result = LZ4IO_getCompressedFileInfo(&cfinfo, inFileNames[idx]); - if (op_result != LZ4IO_LZ4F_OK) { - assert(op_result == LZ4IO_format_not_known); - DISPLAYLEVEL(1, "lz4: %s: File format not recognized \n", inFileNames[idx]); - return 0; - } } - DISPLAYLEVEL(3, "\n"); - if (g_displayLevel < 3) { - /* Display Summary */ - { char buffers[3][10]; - DISPLAYOUT("%10llu %14s %5s %11s %13s ", - cfinfo.frameCount, - cfinfo.eqFrameTypes ? LZ4IO_frameTypeNames[cfinfo.frameSummary.frameType] : "-" , - cfinfo.eqBlockTypes ? LZ4IO_blockTypeID(cfinfo.frameSummary.lz4FrameInfo.blockSizeID, - cfinfo.frameSummary.lz4FrameInfo.blockMode, buffers[0]) : "-", - LZ4IO_toHuman((long double)cfinfo.fileSize, buffers[1]), - cfinfo.allContentSize ? LZ4IO_toHuman((long double)cfinfo.frameSummary.lz4FrameInfo.contentSize, buffers[2]) : "-"); - if (cfinfo.allContentSize) { - double const ratio = (double)cfinfo.fileSize / cfinfo.frameSummary.lz4FrameInfo.contentSize * 100; - DISPLAYOUT("%9.2f%% %s \n", ratio, cfinfo.fileName); - } else { - DISPLAYOUT("%9s %s\n", - "-", - cfinfo.fileName); - } } } /* if (g_displayLevel < 3) */ - } /* for (; idx < ifnIdx; idx++) */ - - return result; -} diff --git a/ta6ob/lz4/programs/lz4io.h b/ta6ob/lz4/programs/lz4io.h deleted file mode 100644 index d6d7eee..0000000 --- a/ta6ob/lz4/programs/lz4io.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - LZ4io.h - LZ4 File/Stream Interface - Copyright (C) Yann Collet 2011-2016 - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ -/* - Note : this is stand-alone program. - It is not part of LZ4 compression library, it is a user code of the LZ4 library. - - The license of LZ4 library is BSD. - - The license of xxHash library is BSD. - - The license of this source file is GPLv2. -*/ - -#ifndef LZ4IO_H_237902873 -#define LZ4IO_H_237902873 - -/*--- Dependency ---*/ -#include /* size_t */ - - -/* ************************************************** */ -/* Special input/output values */ -/* ************************************************** */ -#define stdinmark "stdin" -#define stdoutmark "stdout" -#define NULL_OUTPUT "null" -#ifdef _WIN32 -#define nulmark "nul" -#else -#define nulmark "/dev/null" -#endif - -/* ************************************************** */ -/* ****************** Type Definitions ************** */ -/* ************************************************** */ - -typedef struct LZ4IO_prefs_s LZ4IO_prefs_t; - -LZ4IO_prefs_t* LZ4IO_defaultPreferences(void); -void LZ4IO_freePreferences(LZ4IO_prefs_t* prefs); - -/* Size in bytes of a legacy block header in little-endian format */ -#define LZIO_LEGACY_BLOCK_HEADER_SIZE 4 - -/* ************************************************** */ -/* ****************** Functions ********************* */ -/* ************************************************** */ - -/* if output_filename == stdoutmark, writes to stdout */ -int LZ4IO_compressFilename(const char* input_filename, const char* output_filename, int compressionlevel, const LZ4IO_prefs_t* prefs); -int LZ4IO_decompressFilename(const char* input_filename, const char* output_filename, const LZ4IO_prefs_t* prefs); - -/* if suffix == stdoutmark, writes to stdout */ -int LZ4IO_compressMultipleFilenames(const char** inFileNamesTable, int ifntSize, const char* suffix, int compressionlevel, const LZ4IO_prefs_t* prefs); -int LZ4IO_decompressMultipleFilenames(const char** inFileNamesTable, int ifntSize, const char* suffix, const LZ4IO_prefs_t* prefs); - - -/* ************************************************** */ -/* ****************** Parameters ******************** */ -/* ************************************************** */ - -int LZ4IO_setDictionaryFilename(LZ4IO_prefs_t* const prefs, const char* dictionaryFilename); - -/* Default setting : passThrough = 0; - return : passThrough mode (0/1) */ -int LZ4IO_setPassThrough(LZ4IO_prefs_t* const prefs, int yes); - -/* Default setting : overwrite = 1; - return : overwrite mode (0/1) */ -int LZ4IO_setOverwrite(LZ4IO_prefs_t* const prefs, int yes); - -/* Default setting : testMode = 0; - return : testMode (0/1) */ -int LZ4IO_setTestMode(LZ4IO_prefs_t* const prefs, int yes); - -/* blockSizeID : valid values : 4-5-6-7 - return : 0 if error, blockSize if OK */ -size_t LZ4IO_setBlockSizeID(LZ4IO_prefs_t* const prefs, unsigned blockSizeID); - -/* blockSize : valid values : 32 -> 4MB - return : 0 if error, actual blocksize if OK */ -size_t LZ4IO_setBlockSize(LZ4IO_prefs_t* const prefs, size_t blockSize); - -/* Default setting : independent blocks */ -typedef enum { LZ4IO_blockLinked=0, LZ4IO_blockIndependent} LZ4IO_blockMode_t; -int LZ4IO_setBlockMode(LZ4IO_prefs_t* const prefs, LZ4IO_blockMode_t blockMode); - -/* Default setting : no block checksum */ -int LZ4IO_setBlockChecksumMode(LZ4IO_prefs_t* const prefs, int xxhash); - -/* Default setting : stream checksum enabled */ -int LZ4IO_setStreamChecksumMode(LZ4IO_prefs_t* const prefs, int xxhash); - -/* Default setting : 0 (no notification) */ -int LZ4IO_setNotificationLevel(int level); - -/* Default setting : 0 (disabled) */ -int LZ4IO_setSparseFile(LZ4IO_prefs_t* const prefs, int enable); - -/* Default setting : 0 == no content size present in frame header */ -int LZ4IO_setContentSize(LZ4IO_prefs_t* const prefs, int enable); - -/* Default setting : 0 == src file preserved */ -void LZ4IO_setRemoveSrcFile(LZ4IO_prefs_t* const prefs, unsigned flag); - -/* Default setting : 0 == favor compression ratio - * Note : 1 only works for high compression levels (10+) */ -void LZ4IO_favorDecSpeed(LZ4IO_prefs_t* const prefs, int favor); - - -/* implement --list - * @return 0 on success, 1 on error */ -int LZ4IO_displayCompressedFilesInfo(const char** inFileNames, size_t ifnIdx); - - -#endif /* LZ4IO_H_237902873 */ diff --git a/ta6ob/lz4/programs/platform.h b/ta6ob/lz4/programs/platform.h deleted file mode 100644 index ab8300d..0000000 --- a/ta6ob/lz4/programs/platform.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - platform.h - compiler and OS detection - Copyright (C) 2016-present, Przemyslaw Skibinski, Yann Collet - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef PLATFORM_H_MODULE -#define PLATFORM_H_MODULE - -#if defined (__cplusplus) -extern "C" { -#endif - - - -/* ************************************** -* Compiler Options -****************************************/ -#if defined(_MSC_VER) -# define _CRT_SECURE_NO_WARNINGS /* Disable Visual Studio warning messages for fopen, strncpy, strerror */ -# if (_MSC_VER <= 1800) /* (1800 = Visual Studio 2013) */ -# define _CRT_SECURE_NO_DEPRECATE /* VS2005 - must be declared before and */ -# define snprintf sprintf_s /* snprintf unsupported by Visual <= 2013 */ -# endif -#endif - - -/* ************************************** -* Detect 64-bit OS -* http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros -****************************************/ -#if defined __ia64 || defined _M_IA64 /* Intel Itanium */ \ - || defined __powerpc64__ || defined __ppc64__ || defined __PPC64__ /* POWER 64-bit */ \ - || (defined __sparc && (defined __sparcv9 || defined __sparc_v9__ || defined __arch64__)) || defined __sparc64__ /* SPARC 64-bit */ \ - || defined __x86_64__s || defined _M_X64 /* x86 64-bit */ \ - || defined __arm64__ || defined __aarch64__ || defined __ARM64_ARCH_8__ /* ARM 64-bit */ \ - || (defined __mips && (__mips == 64 || __mips == 4 || __mips == 3)) /* MIPS 64-bit */ \ - || defined _LP64 || defined __LP64__ /* NetBSD, OpenBSD */ || defined __64BIT__ /* AIX */ || defined _ADDR64 /* Cray */ \ - || (defined __SIZEOF_POINTER__ && __SIZEOF_POINTER__ == 8) /* gcc */ -# if !defined(__64BIT__) -# define __64BIT__ 1 -# endif -#endif - - -/* ********************************************************* -* Turn on Large Files support (>4GB) for 32-bit Linux/Unix -***********************************************************/ -#if !defined(__64BIT__) || defined(__MINGW32__) /* No point defining Large file for 64 bit but MinGW-w64 requires it */ -# if !defined(_FILE_OFFSET_BITS) -# define _FILE_OFFSET_BITS 64 /* turn off_t into a 64-bit type for ftello, fseeko */ -# endif -# if !defined(_LARGEFILE_SOURCE) /* obsolete macro, replaced with _FILE_OFFSET_BITS */ -# define _LARGEFILE_SOURCE 1 /* Large File Support extension (LFS) - fseeko, ftello */ -# endif -# if defined(_AIX) || defined(__hpux) -# define _LARGE_FILES /* Large file support on 32-bits AIX and HP-UX */ -# endif -#endif - - -/* ************************************************************ -* Detect POSIX version -* PLATFORM_POSIX_VERSION = -1 for non-Unix e.g. Windows -* PLATFORM_POSIX_VERSION = 0 for Unix-like non-POSIX -* PLATFORM_POSIX_VERSION >= 1 is equal to found _POSIX_VERSION -************************************************************** */ -#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) /* UNIX-like OS */ \ - || defined(__midipix__) || defined(__VMS)) -# if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1–2001 (SUSv3) conformant */ \ - || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__MidnightBSD__) /* BSD distros */ \ - || defined(__HAIKU__) -# define PLATFORM_POSIX_VERSION 200112L -# else -# if defined(__linux__) || defined(__linux) -# ifndef _POSIX_C_SOURCE -# define _POSIX_C_SOURCE 200809L /* use feature test macro */ -# endif -# endif -# include /* declares _POSIX_VERSION */ -# if defined(_POSIX_VERSION) /* POSIX compliant */ -# define PLATFORM_POSIX_VERSION _POSIX_VERSION -# else -# define PLATFORM_POSIX_VERSION 0 -# endif -# endif -#endif -#if !defined(PLATFORM_POSIX_VERSION) -# define PLATFORM_POSIX_VERSION -1 -#endif - - -/*-********************************************* -* Detect if isatty() and fileno() are available -*********************************************** */ -#if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 1)) || (PLATFORM_POSIX_VERSION >= 200112L) || defined(__DJGPP__) -# include /* isatty */ -# define IS_CONSOLE(stdStream) isatty(fileno(stdStream)) -#elif defined(MSDOS) || defined(OS2) || defined(__CYGWIN__) -# include /* _isatty */ -# define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream)) -#elif defined(WIN32) || defined(_WIN32) -# include /* _isatty */ -# include /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */ -# include /* FILE */ -static __inline int IS_CONSOLE(FILE* stdStream) -{ - DWORD dummy; - return _isatty(_fileno(stdStream)) && GetConsoleMode((HANDLE)_get_osfhandle(_fileno(stdStream)), &dummy); -} -#else -# define IS_CONSOLE(stdStream) 0 -#endif - - -/****************************** -* OS-specific Includes -***************************** */ -#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) -# include /* _O_BINARY */ -# include /* _setmode, _fileno, _get_osfhandle */ -# if !defined(__DJGPP__) -# include /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */ -# include /* FSCTL_SET_SPARSE */ -# define SET_BINARY_MODE(file) { int unused=_setmode(_fileno(file), _O_BINARY); (void)unused; } -# define SET_SPARSE_FILE_MODE(file) { DWORD dw; DeviceIoControl((HANDLE) _get_osfhandle(_fileno(file)), FSCTL_SET_SPARSE, 0, 0, 0, 0, &dw, 0); } -# else -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -# define SET_SPARSE_FILE_MODE(file) -# endif -#else -# define SET_BINARY_MODE(file) -# define SET_SPARSE_FILE_MODE(file) -#endif - - - -#if defined (__cplusplus) -} -#endif - -#endif /* PLATFORM_H_MODULE */ diff --git a/ta6ob/lz4/programs/util.h b/ta6ob/lz4/programs/util.h deleted file mode 100644 index 733c1ca..0000000 --- a/ta6ob/lz4/programs/util.h +++ /dev/null @@ -1,650 +0,0 @@ -/* - util.h - utility functions - Copyright (C) 2016-present, Przemyslaw Skibinski, Yann Collet - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef UTIL_H_MODULE -#define UTIL_H_MODULE - -#if defined (__cplusplus) -extern "C" { -#endif - - - -/*-**************************************** -* Dependencies -******************************************/ -#include "platform.h" /* PLATFORM_POSIX_VERSION */ -#include /* size_t, ptrdiff_t */ -#include /* malloc */ -#include /* strlen, strncpy */ -#include /* fprintf, fileno */ -#include -#include /* stat, utime */ -#include /* stat */ -#if defined(_WIN32) -# include /* utime */ -# include /* _chmod */ -#else -# include /* chown, stat */ -# if PLATFORM_POSIX_VERSION < 200809L -# include /* utime */ -# else -# include /* AT_FDCWD */ -# include /* for utimensat */ -# endif -#endif -#include /* time */ -#include /* INT_MAX */ -#include - - - -/*-************************************************************** -* Basic Types -*****************************************************************/ -#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint8_t BYTE; - typedef uint16_t U16; - typedef int16_t S16; - typedef uint32_t U32; - typedef int32_t S32; - typedef uint64_t U64; - typedef int64_t S64; -#else - typedef unsigned char BYTE; - typedef unsigned short U16; - typedef signed short S16; - typedef unsigned int U32; - typedef signed int S32; - typedef unsigned long long U64; - typedef signed long long S64; -#endif - - -/* ************************************************************ -* Avoid fseek()'s 2GiB barrier with MSVC, MacOS, *BSD, MinGW -***************************************************************/ -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -# define UTIL_fseek _fseeki64 -#elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */ -# define UTIL_fseek fseeko -#elif defined(__MINGW32__) && defined(__MSVCRT__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) -# define UTIL_fseek fseeko64 -#else -# define UTIL_fseek fseek -#endif - - -/*-**************************************** -* Sleep functions: Windows - Posix - others -******************************************/ -#if defined(_WIN32) -# include -# define SET_REALTIME_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS) -# define UTIL_sleep(s) Sleep(1000*s) -# define UTIL_sleepMilli(milli) Sleep(milli) -#elif PLATFORM_POSIX_VERSION >= 0 /* Unix-like operating system */ -# include -# include /* setpriority */ -# include /* clock_t, nanosleep, clock, CLOCKS_PER_SEC */ -# if defined(PRIO_PROCESS) -# define SET_REALTIME_PRIORITY setpriority(PRIO_PROCESS, 0, -20) -# else -# define SET_REALTIME_PRIORITY /* disabled */ -# endif -# define UTIL_sleep(s) sleep(s) -# if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 199309L)) || (PLATFORM_POSIX_VERSION >= 200112L) /* nanosleep requires POSIX.1-2001 */ -# define UTIL_sleepMilli(milli) { struct timespec t; t.tv_sec=0; t.tv_nsec=milli*1000000ULL; nanosleep(&t, NULL); } -# else -# define UTIL_sleepMilli(milli) /* disabled */ -# endif -#else -# define SET_REALTIME_PRIORITY /* disabled */ -# define UTIL_sleep(s) /* disabled */ -# define UTIL_sleepMilli(milli) /* disabled */ -#endif - - -/*-**************************************** -* stat() functions -******************************************/ -#if defined(_MSC_VER) -# define UTIL_TYPE_stat __stat64 -# define UTIL_stat _stat64 -# define UTIL_fstat _fstat64 -# define UTIL_STAT_MODE_ISREG(st_mode) ((st_mode) & S_IFREG) -#elif defined(__MINGW32__) && defined (__MSVCRT__) -# define UTIL_TYPE_stat _stati64 -# define UTIL_stat _stati64 -# define UTIL_fstat _fstati64 -# define UTIL_STAT_MODE_ISREG(st_mode) ((st_mode) & S_IFREG) -#else -# define UTIL_TYPE_stat stat -# define UTIL_stat stat -# define UTIL_fstat fstat -# define UTIL_STAT_MODE_ISREG(st_mode) (S_ISREG(st_mode)) -#endif - - -/*-**************************************** -* fileno() function -******************************************/ -#if defined(_MSC_VER) -# define UTIL_fileno _fileno -#else -# define UTIL_fileno fileno -#endif - -/* ************************************* -* Constants -***************************************/ -#define LIST_SIZE_INCREASE (8*1024) - - -/*-**************************************** -* Compiler specifics -******************************************/ -#if defined(__INTEL_COMPILER) -# pragma warning(disable : 177) /* disable: message #177: function was declared but never referenced, useful with UTIL_STATIC */ -#endif -#if defined(__GNUC__) -# define UTIL_STATIC static __attribute__((unused)) -#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -# define UTIL_STATIC static inline -#elif defined(_MSC_VER) -# define UTIL_STATIC static __inline -#else -# define UTIL_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ -#endif - - -/*-**************************************** -* Time functions -******************************************/ -#if defined(_WIN32) /* Windows */ - - typedef LARGE_INTEGER UTIL_time_t; - UTIL_STATIC UTIL_time_t UTIL_getTime(void) { UTIL_time_t x; QueryPerformanceCounter(&x); return x; } - UTIL_STATIC U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) - { - static LARGE_INTEGER ticksPerSecond; - static int init = 0; - if (!init) { - if (!QueryPerformanceFrequency(&ticksPerSecond)) - fprintf(stderr, "ERROR: QueryPerformanceFrequency() failure\n"); - init = 1; - } - return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart; - } - UTIL_STATIC U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) - { - static LARGE_INTEGER ticksPerSecond; - static int init = 0; - if (!init) { - if (!QueryPerformanceFrequency(&ticksPerSecond)) - fprintf(stderr, "ERROR: QueryPerformanceFrequency() failure\n"); - init = 1; - } - return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart; - } - -#elif defined(__APPLE__) && defined(__MACH__) - - #include - typedef U64 UTIL_time_t; - UTIL_STATIC UTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); } - UTIL_STATIC U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) - { - static mach_timebase_info_data_t rate; - static int init = 0; - if (!init) { - mach_timebase_info(&rate); - init = 1; - } - return (((clockEnd - clockStart) * (U64)rate.numer) / ((U64)rate.denom)) / 1000ULL; - } - UTIL_STATIC U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) - { - static mach_timebase_info_data_t rate; - static int init = 0; - if (!init) { - mach_timebase_info(&rate); - init = 1; - } - return ((clockEnd - clockStart) * (U64)rate.numer) / ((U64)rate.denom); - } - -#elif (PLATFORM_POSIX_VERSION >= 200112L) && (defined __UCLIBC__ || (defined(__GLIBC__) && ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) || __GLIBC__ > 2) ) ) - - #include - typedef struct timespec UTIL_time_t; - UTIL_STATIC UTIL_time_t UTIL_getTime(void) - { - UTIL_time_t now; - if (clock_gettime(CLOCK_MONOTONIC, &now)) - fprintf(stderr, "ERROR: Failed to get time\n"); /* we could also exit() */ - return now; - } - UTIL_STATIC UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end) - { - UTIL_time_t diff; - if (end.tv_nsec < begin.tv_nsec) { - diff.tv_sec = (end.tv_sec - 1) - begin.tv_sec; - diff.tv_nsec = (end.tv_nsec + 1000000000ULL) - begin.tv_nsec; - } else { - diff.tv_sec = end.tv_sec - begin.tv_sec; - diff.tv_nsec = end.tv_nsec - begin.tv_nsec; - } - return diff; - } - UTIL_STATIC U64 UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end) - { - UTIL_time_t const diff = UTIL_getSpanTime(begin, end); - U64 micro = 0; - micro += 1000000ULL * diff.tv_sec; - micro += diff.tv_nsec / 1000ULL; - return micro; - } - UTIL_STATIC U64 UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end) - { - UTIL_time_t const diff = UTIL_getSpanTime(begin, end); - U64 nano = 0; - nano += 1000000000ULL * diff.tv_sec; - nano += diff.tv_nsec; - return nano; - } - -#else /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */ - - typedef clock_t UTIL_time_t; - UTIL_STATIC UTIL_time_t UTIL_getTime(void) { return clock(); } - UTIL_STATIC U64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; } - UTIL_STATIC U64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; } -#endif - - -/* returns time span in microseconds */ -UTIL_STATIC U64 UTIL_clockSpanMicro(UTIL_time_t clockStart) -{ - UTIL_time_t const clockEnd = UTIL_getTime(); - return UTIL_getSpanTimeMicro(clockStart, clockEnd); -} - -/* returns time span in nanoseconds */ -UTIL_STATIC U64 UTIL_clockSpanNano(UTIL_time_t clockStart) -{ - UTIL_time_t const clockEnd = UTIL_getTime(); - return UTIL_getSpanTimeNano(clockStart, clockEnd); -} - -UTIL_STATIC void UTIL_waitForNextTick(void) -{ - UTIL_time_t const clockStart = UTIL_getTime(); - UTIL_time_t clockEnd; - do { - clockEnd = UTIL_getTime(); - } while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0); -} - - - -/*-**************************************** -* File functions -******************************************/ -#if defined(_MSC_VER) - #define chmod _chmod - typedef struct __stat64 stat_t; -#else - typedef struct stat stat_t; -#endif - - -UTIL_STATIC int UTIL_isRegFile(const char* infilename); - - -UTIL_STATIC int UTIL_setFileStat(const char *filename, stat_t *statbuf) -{ - int res = 0; - - if (!UTIL_isRegFile(filename)) - return -1; - - { -#if defined(_WIN32) || (PLATFORM_POSIX_VERSION < 200809L) - struct utimbuf timebuf; - timebuf.actime = time(NULL); - timebuf.modtime = statbuf->st_mtime; - res += utime(filename, &timebuf); /* set access and modification times */ -#else - struct timespec timebuf[2] = {}; - timebuf[0].tv_nsec = UTIME_NOW; - timebuf[1].tv_sec = statbuf->st_mtime; - res += utimensat(AT_FDCWD, filename, timebuf, 0); /* set access and modification times */ -#endif - } - -#if !defined(_WIN32) - res += chown(filename, statbuf->st_uid, statbuf->st_gid); /* Copy ownership */ -#endif - - res += chmod(filename, statbuf->st_mode & 07777); /* Copy file permissions */ - - errno = 0; - return -res; /* number of errors is returned */ -} - - -UTIL_STATIC int UTIL_getFileStat(const char* infilename, stat_t *statbuf) -{ - int r; -#if defined(_MSC_VER) - r = _stat64(infilename, statbuf); - if (r || !(statbuf->st_mode & S_IFREG)) return 0; /* No good... */ -#else - r = stat(infilename, statbuf); - if (r || !S_ISREG(statbuf->st_mode)) return 0; /* No good... */ -#endif - return 1; -} - - -UTIL_STATIC int UTIL_isRegFile(const char* infilename) -{ - stat_t statbuf; - return UTIL_getFileStat(infilename, &statbuf); /* Only need to know whether it is a regular file */ -} - - -UTIL_STATIC U32 UTIL_isDirectory(const char* infilename) -{ - int r; - stat_t statbuf; -#if defined(_MSC_VER) - r = _stat64(infilename, &statbuf); - if (!r && (statbuf.st_mode & _S_IFDIR)) return 1; -#else - r = stat(infilename, &statbuf); - if (!r && S_ISDIR(statbuf.st_mode)) return 1; -#endif - return 0; -} - - -UTIL_STATIC U64 UTIL_getOpenFileSize(FILE* file) -{ - int r; - int fd; - struct UTIL_TYPE_stat statbuf; - - fd = UTIL_fileno(file); - if (fd < 0) { - perror("fileno"); - exit(1); - } - r = UTIL_fstat(fd, &statbuf); - if (r || !UTIL_STAT_MODE_ISREG(statbuf.st_mode)) return 0; /* No good... */ - return (U64)statbuf.st_size; -} - - -UTIL_STATIC U64 UTIL_getFileSize(const char* infilename) -{ - int r; - struct UTIL_TYPE_stat statbuf; - - r = UTIL_stat(infilename, &statbuf); - if (r || !UTIL_STAT_MODE_ISREG(statbuf.st_mode)) return 0; /* No good... */ - return (U64)statbuf.st_size; -} - - -UTIL_STATIC U64 UTIL_getTotalFileSize(const char** fileNamesTable, unsigned nbFiles) -{ - U64 total = 0; - unsigned n; - for (n=0; n= *bufEnd) { - ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE; - *bufStart = (char*)UTIL_realloc(*bufStart, newListSize); - *bufEnd = *bufStart + newListSize; - if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; } - } - if (*bufStart + *pos + pathLength < *bufEnd) { - strncpy(*bufStart + *pos, path, *bufEnd - (*bufStart + *pos)); - *pos += pathLength + 1; - nbFiles++; - } - } - free(path); - } while (FindNextFileA(hFile, &cFile)); - - FindClose(hFile); - assert(nbFiles < INT_MAX); - return (int)nbFiles; -} - -#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */ -# define UTIL_HAS_CREATEFILELIST -# include /* opendir, readdir */ -# include /* strerror, memcpy */ - -UTIL_STATIC int UTIL_prepareFileList(const char* dirName, char** bufStart, size_t* pos, char** bufEnd) -{ - DIR* dir; - struct dirent * entry; - int dirLength, nbFiles = 0; - - if (!(dir = opendir(dirName))) { - fprintf(stderr, "Cannot open directory '%s': %s\n", dirName, strerror(errno)); - return 0; - } - - dirLength = (int)strlen(dirName); - errno = 0; - while ((entry = readdir(dir)) != NULL) { - char* path; - int fnameLength, pathLength; - if (strcmp (entry->d_name, "..") == 0 || - strcmp (entry->d_name, ".") == 0) continue; - fnameLength = (int)strlen(entry->d_name); - path = (char*) malloc(dirLength + fnameLength + 2); - if (!path) { closedir(dir); return 0; } - memcpy(path, dirName, dirLength); - path[dirLength] = '/'; - memcpy(path+dirLength+1, entry->d_name, fnameLength); - pathLength = dirLength+1+fnameLength; - path[pathLength] = 0; - - if (UTIL_isDirectory(path)) { - nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd); /* Recursively call "UTIL_prepareFileList" with the new path. */ - if (*bufStart == NULL) { free(path); closedir(dir); return 0; } - } else { - if (*bufStart + *pos + pathLength >= *bufEnd) { - ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE; - *bufStart = (char*)UTIL_realloc(*bufStart, newListSize); - *bufEnd = *bufStart + newListSize; - if (*bufStart == NULL) { free(path); closedir(dir); return 0; } - } - if (*bufStart + *pos + pathLength < *bufEnd) { - strncpy(*bufStart + *pos, path, *bufEnd - (*bufStart + *pos)); - *pos += pathLength + 1; - nbFiles++; - } - } - free(path); - errno = 0; /* clear errno after UTIL_isDirectory, UTIL_prepareFileList */ - } - - if (errno != 0) { - fprintf(stderr, "readdir(%s) error: %s\n", dirName, strerror(errno)); - free(*bufStart); - *bufStart = NULL; - } - closedir(dir); - return nbFiles; -} - -#else - -UTIL_STATIC int UTIL_prepareFileList(const char* dirName, char** bufStart, size_t* pos, char** bufEnd) -{ - (void)bufStart; (void)bufEnd; (void)pos; - fprintf(stderr, "Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE)\n", dirName); - return 0; -} - -#endif /* #ifdef _WIN32 */ - -/* - * UTIL_createFileList - takes a list of files and directories (params: inputNames, inputNamesNb), scans directories, - * and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb). - * After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer) - * In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called. - */ -UTIL_STATIC const char** -UTIL_createFileList(const char** inputNames, unsigned inputNamesNb, - char** allocatedBuffer, unsigned* allocatedNamesNb) -{ - size_t pos; - unsigned i, nbFiles; - char* buf = (char*)malloc(LIST_SIZE_INCREASE); - size_t bufSize = LIST_SIZE_INCREASE; - const char** fileTable; - - if (!buf) return NULL; - - for (i=0, pos=0, nbFiles=0; i= bufSize) { - while (pos + len >= bufSize) bufSize += LIST_SIZE_INCREASE; - buf = (char*)UTIL_realloc(buf, bufSize); - if (!buf) return NULL; - } - assert(pos + len < bufSize); - memcpy(buf + pos, inputNames[i], len); - pos += len; - nbFiles++; - } else { - char* bufend = buf + bufSize; - nbFiles += (unsigned)UTIL_prepareFileList(inputNames[i], &buf, &pos, &bufend); - if (buf == NULL) return NULL; - assert(bufend > buf); - bufSize = (size_t)(bufend - buf); - } } - - if (nbFiles == 0) { free(buf); return NULL; } - - fileTable = (const char**)malloc(((size_t)nbFiles+1) * sizeof(const char*)); - if (!fileTable) { free(buf); return NULL; } - - for (i=0, pos=0; i bufSize) { - free(buf); - free((void*)fileTable); - return NULL; - } /* can this happen ? */ - - *allocatedBuffer = buf; - *allocatedNamesNb = nbFiles; - - return fileTable; -} - - -UTIL_STATIC void -UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer) -{ - if (allocatedBuffer) free(allocatedBuffer); - if (filenameTable) free((void*)filenameTable); -} - - -#if defined (__cplusplus) -} -#endif - -#endif /* UTIL_H_MODULE */ diff --git a/ta6ob/lz4/tests/.gitignore b/ta6ob/lz4/tests/.gitignore deleted file mode 100644 index 99351af..0000000 --- a/ta6ob/lz4/tests/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ - -# build artefacts -datagen -frametest -frametest32 -fullbench -fullbench32 -fuzzer -fuzzer32 -fasttest -roundTripTest -checkTag -checkFrame -decompress-partial - -# test artefacts -tmp* -versionsTest -lz4_all.c - -# local tests -afl diff --git a/ta6ob/lz4/tests/COPYING b/ta6ob/lz4/tests/COPYING deleted file mode 100644 index d159169..0000000 --- a/ta6ob/lz4/tests/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/ta6ob/lz4/tests/Makefile b/ta6ob/lz4/tests/Makefile deleted file mode 100644 index 6eee132..0000000 --- a/ta6ob/lz4/tests/Makefile +++ /dev/null @@ -1,544 +0,0 @@ -# ########################################################################## -# LZ4 programs - Makefile -# Copyright (C) Yann Collet 2011-present -# -# GPL v2 License -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# You can contact the author at : -# - LZ4 homepage : http://www.lz4.org -# - LZ4 source repository : https://github.com/lz4/lz4 -# ########################################################################## -# fuzzer : Test tool, to check lz4 integrity on target platform -# frametest : Test tool, to check lz4frame integrity on target platform -# fullbench : Precisely measure speed for each LZ4 function variant -# datagen : generates synthetic data samples for tests & benchmarks -# ########################################################################## - -LZ4DIR := ../lib -PRGDIR := ../programs -TESTDIR := versionsTest -PYTHON ?= python3 - -DEBUGLEVEL?= 1 -DEBUGFLAGS = -g -DLZ4_DEBUG=$(DEBUGLEVEL) -CFLAGS ?= -O3 # can select custom optimization flags. Example : CFLAGS=-O2 make -CFLAGS += -Wall -Wextra -Wundef -Wcast-qual -Wcast-align -Wshadow \ - -Wswitch-enum -Wdeclaration-after-statement -Wstrict-prototypes \ - -Wpointer-arith -Wstrict-aliasing=1 -CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) -CPPFLAGS+= -I$(LZ4DIR) -I$(PRGDIR) -DXXH_NAMESPACE=LZ4_ -FLAGS = $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) - -include ../Makefile.inc - -LZ4 := $(PRGDIR)/lz4$(EXT) - - -# Default test parameters -TEST_FILES := COPYING -FUZZER_TIME := -T90s -NB_LOOPS ?= -i1 - -.PHONY: default -default: all - -all: fullbench fuzzer frametest roundTripTest datagen checkFrame decompress-partial - -all32: CFLAGS+=-m32 -all32: all - -lz4: - $(MAKE) -C $(PRGDIR) $@ CFLAGS="$(CFLAGS)" - -lib liblz4.pc: - $(MAKE) -C $(LZ4DIR) $@ CFLAGS="$(CFLAGS)" - -lz4c unlz4 lz4cat: lz4 - $(LN_SF) $(LZ4) $(PRGDIR)/$@ - -lz4c32: # create a 32-bits version for 32/64 interop tests - $(MAKE) -C $(PRGDIR) $@ CFLAGS="-m32 $(CFLAGS)" - -%.o : $(LZ4DIR)/%.c $(LZ4DIR)/%.h - $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ - -fullbench : DEBUGLEVEL=0 -fullbench : lz4.o lz4hc.o lz4frame.o xxhash.o fullbench.c - $(CC) $(FLAGS) $^ -o $@$(EXT) - -$(LZ4DIR)/liblz4.a: - $(MAKE) -C $(LZ4DIR) liblz4.a - -fullbench-lib: fullbench.c $(LZ4DIR)/liblz4.a - $(CC) $(FLAGS) $^ -o $@$(EXT) - -fullbench-dll: fullbench.c $(LZ4DIR)/xxhash.c - $(MAKE) -C $(LZ4DIR) liblz4 - $(CC) $(FLAGS) $^ -o $@$(EXT) -DLZ4_DLL_IMPORT=1 $(LZ4DIR)/dll/$(LIBLZ4).dll - -# test LZ4_USER_MEMORY_FUNCTIONS -fullbench-wmalloc: CPPFLAGS += -DLZ4_USER_MEMORY_FUNCTIONS -fullbench-wmalloc: fullbench - -fuzzer : lz4.o lz4hc.o xxhash.o fuzzer.c - $(CC) $(FLAGS) $^ -o $@$(EXT) - -frametest: lz4frame.o lz4.o lz4hc.o xxhash.o frametest.c - $(CC) $(FLAGS) $^ -o $@$(EXT) - -roundTripTest : lz4.o lz4hc.o xxhash.o roundTripTest.c - $(CC) $(FLAGS) $^ -o $@$(EXT) - -datagen : $(PRGDIR)/datagen.c datagencli.c - $(CC) $(FLAGS) -I$(PRGDIR) $^ -o $@$(EXT) - -checkFrame : lz4frame.o lz4.o lz4hc.o xxhash.o checkFrame.c - $(CC) $(FLAGS) $^ -o $@$(EXT) - -decompress-partial: lz4.o decompress-partial.c - $(CC) $(FLAGS) $^ -o $@$(EXT) - -.PHONY: clean -clean: - @$(MAKE) -C $(LZ4DIR) $@ > $(VOID) - @$(MAKE) -C $(PRGDIR) $@ > $(VOID) - @$(RM) -rf core *.o *.test tmp* \ - fullbench-dll$(EXT) fullbench-lib$(EXT) \ - fullbench$(EXT) fullbench32$(EXT) \ - fuzzer$(EXT) fuzzer32$(EXT) \ - frametest$(EXT) frametest32$(EXT) \ - fasttest$(EXT) roundTripTest$(EXT) \ - datagen$(EXT) checkTag$(EXT) \ - frameTest$(EXT) decompress-partial$(EXT) \ - lz4_all.c - @$(RM) -rf $(TESTDIR) - @echo Cleaning completed - -.PHONY: versionsTest -versionsTest: - $(PYTHON) test-lz4-versions.py - -.PHONY: listTest -listTest: lz4 - QEMU_SYS=$(QEMU_SYS) $(PYTHON) test-lz4-list.py - -checkTag: checkTag.c $(LZ4DIR)/lz4.h - $(CC) $(FLAGS) $< -o $@$(EXT) - -#----------------------------------------------------------------------------- -# validated only for Linux, OSX, BSD, Hurd and Solaris targets -#----------------------------------------------------------------------------- -ifeq ($(POSIX_ENV),Yes) - -MD5:=md5sum -ifneq (,$(filter $(shell uname), Darwin )) -MD5:=md5 -r -endif - -# note : we should probably settle on a single compare utility -CMP:=cmp -DIFF:=diff -ifneq (,$(filter $(shell uname),SunOS)) -DIFF:=gdiff -endif - -CAT:=cat -DD:=dd -DATAGEN:=./datagen - -.PHONY: list -list: - @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs - -.PHONY: check -check: test-lz4-essentials - -.PHONY: test -test: test-lz4 test-lz4c test-frametest test-fullbench test-fuzzer test-install test-amalgamation listTest test-decompress-partial - -.PHONY: test32 -test32: CFLAGS+=-m32 -test32: test - -test-amalgamation: lz4_all.o - -lz4_all.c: $(LZ4DIR)/lz4.c $(LZ4DIR)/lz4hc.c $(LZ4DIR)/lz4frame.c - $(CAT) $^ > $@ - -test-install: lz4 lib liblz4.pc - lz4_root=.. ./test_install.sh - -test-lz4-sparse: lz4 datagen - @echo "\n ---- test sparse file support ----" - $(DATAGEN) -g5M -P100 > tmplsdg5M - $(LZ4) -B4D tmplsdg5M -c | $(LZ4) -dv --sparse > tmplscB4 - $(DIFF) -s tmplsdg5M tmplscB4 - $(LZ4) -B5D tmplsdg5M -c | $(LZ4) -dv --sparse > tmplscB5 - $(DIFF) -s tmplsdg5M tmplscB5 - $(LZ4) -B6D tmplsdg5M -c | $(LZ4) -dv --sparse > tmplscB6 - $(DIFF) -s tmplsdg5M tmplscB6 - $(LZ4) -B7D tmplsdg5M -c | $(LZ4) -dv --sparse > tmplscB7 - $(DIFF) -s tmplsdg5M tmplscB7 - $(LZ4) tmplsdg5M -c | $(LZ4) -dv --no-sparse > tmplsnosparse - $(DIFF) -s tmplsdg5M tmplsnosparse - ls -ls tmpls* - $(DATAGEN) -s1 -g1200007 -P100 | $(LZ4) | $(LZ4) -dv --sparse > tmplsodd # Odd size file (to generate non-full last block) - $(DATAGEN) -s1 -g1200007 -P100 | $(DIFF) -s - tmplsodd - ls -ls tmplsodd - @$(RM) tmpls* - @echo "\n Compatibility with Console :" - echo "Hello World 1 !" | $(LZ4) | $(LZ4) -d -c - echo "Hello World 2 !" | $(LZ4) | $(LZ4) -d | $(CAT) - echo "Hello World 3 !" | $(LZ4) --no-frame-crc | $(LZ4) -d -c - @echo "\n Compatibility with Append :" - $(DATAGEN) -P100 -g1M > tmplsdg1M - $(CAT) tmplsdg1M tmplsdg1M > tmpls2M - $(LZ4) -B5 -v tmplsdg1M tmplsc - $(LZ4) -d -v tmplsc tmplsr - $(LZ4) -d -v tmplsc -c >> tmplsr - ls -ls tmp* - $(DIFF) tmpls2M tmplsr - @$(RM) tmpls* - -test-lz4-contentSize: lz4 datagen - @echo "\n ---- test original size support ----" - $(DATAGEN) -g15M > tmplc1 - $(LZ4) -v tmplc1 -c | $(LZ4) -t - $(LZ4) -v --content-size tmplc1 -c | $(LZ4) -d > tmplc2 - $(DIFF) tmplc1 tmplc2 - $(LZ4) -f tmplc1 -c > tmplc1.lz4 - $(LZ4) --content-size tmplc1 -c > tmplc2.lz4 - ! $(DIFF) tmplc1.lz4 tmplc2.lz4 # must differ, due to content size - $(LZ4) --content-size < tmplc1 > tmplc3.lz4 - $(DIFF) tmplc2.lz4 tmplc3.lz4 # both must contain content size - $(CAT) tmplc1 | $(LZ4) > tmplc4.lz4 - $(DIFF) tmplc1.lz4 tmplc4.lz4 # both don't have content size - $(CAT) tmplc1 | $(LZ4) --content-size > tmplc5.lz4 # can't determine content size - $(DIFF) tmplc1.lz4 tmplc5.lz4 # both don't have content size - @$(RM) tmplc* - -test-lz4-frame-concatenation: lz4 datagen - @echo "\n ---- test frame concatenation ----" - @echo -n > tmp-lfc-empty - @echo hi > tmp-lfc-nonempty - $(CAT) tmp-lfc-nonempty tmp-lfc-empty tmp-lfc-nonempty > tmp-lfc-src - $(LZ4) -zq tmp-lfc-empty -c > tmp-lfc-empty.lz4 - $(LZ4) -zq tmp-lfc-nonempty -c > tmp-lfc-nonempty.lz4 - $(CAT) tmp-lfc-nonempty.lz4 tmp-lfc-empty.lz4 tmp-lfc-nonempty.lz4 > tmp-lfc-concat.lz4 - $(LZ4) -d tmp-lfc-concat.lz4 -c > tmp-lfc-result - $(CMP) tmp-lfc-src tmp-lfc-result - @$(RM) tmp-lfc-* - @echo frame concatenation test completed - -test-lz4-multiple: lz4 datagen - @echo "\n ---- test multiple files ----" - @$(DATAGEN) -s1 > tmp-tlm1 2> $(VOID) - @$(DATAGEN) -s2 -g100K > tmp-tlm2 2> $(VOID) - @$(DATAGEN) -s3 -g200K > tmp-tlm3 2> $(VOID) - # compress multiple files : one .lz4 per source file - $(LZ4) -f -m tmp-tlm* - test -f tmp-tlm1.lz4 - test -f tmp-tlm2.lz4 - test -f tmp-tlm3.lz4 - # decompress multiple files : one output file per .lz4 - mv tmp-tlm1 tmp-tlm1-orig - mv tmp-tlm2 tmp-tlm2-orig - mv tmp-tlm3 tmp-tlm3-orig - $(LZ4) -d -f -m tmp-tlm*.lz4 - $(CMP) tmp-tlm1 tmp-tlm1-orig # must be identical - $(CMP) tmp-tlm2 tmp-tlm2-orig - $(CMP) tmp-tlm3 tmp-tlm3-orig - # compress multiple files into stdout - $(CAT) tmp-tlm1.lz4 tmp-tlm2.lz4 tmp-tlm3.lz4 > tmp-tlm-concat1 - $(RM) *.lz4 - $(LZ4) -m tmp-tlm1 tmp-tlm2 tmp-tlm3 -c > tmp-tlm-concat2 - test ! -f tmp-tlm1.lz4 # must not create .lz4 artefact - $(CMP) tmp-tlm-concat1 tmp-tlm-concat2 # must be equivalent - # decompress multiple files into stdout - $(RM) tmp-tlm-concat1 tmp-tlm-concat2 - $(LZ4) -f -m tmp-tlm1 tmp-tlm2 tmp-tlm3 # generate .lz4 to decompress - $(CAT) tmp-tlm1 tmp-tlm2 tmp-tlm3 > tmp-tlm-concat1 # create concatenated reference - $(RM) tmp-tlm1 tmp-tlm2 tmp-tlm3 - $(LZ4) -d -m tmp-tlm1.lz4 tmp-tlm2.lz4 tmp-tlm3.lz4 -c > tmp-tlm-concat2 - test ! -f tmp-tlm1 # must not create file artefact - $(CMP) tmp-tlm-concat1 tmp-tlm-concat2 # must be equivalent - # compress multiple files, one of which is absent (must fail) - ! $(LZ4) -f -m tmp-tlm-concat1 notHere tmp-tlm-concat2 # must fail : notHere not present - @$(RM) tmp-tlm* - -test-lz4-multiple-legacy: lz4 datagen - @echo "\n ---- test multiple files (Legacy format) ----" - @$(DATAGEN) -s1 > tmp-tlm1 2> $(VOID) - @$(DATAGEN) -s2 -g100K > tmp-tlm2 2> $(VOID) - @$(DATAGEN) -s3 -g200K > tmp-tlm3 2> $(VOID) - # compress multiple files using legacy format: one .lz4 per source file - $(LZ4) -f -l -m tmp-tlm* - test -f tmp-tlm1.lz4 - test -f tmp-tlm2.lz4 - test -f tmp-tlm3.lz4 - # decompress multiple files compressed using legacy format: one output file per .lz4 - mv tmp-tlm1 tmp-tlm1-orig - mv tmp-tlm2 tmp-tlm2-orig - mv tmp-tlm3 tmp-tlm3-orig - $(LZ4) -d -f -m tmp-tlm*.lz4 - $(LZ4) -l -d -f -m tmp-tlm*.lz4 # -l mustn't impact -d option - $(CMP) tmp-tlm1 tmp-tlm1-orig # must be identical - $(CMP) tmp-tlm2 tmp-tlm2-orig - $(CMP) tmp-tlm3 tmp-tlm3-orig - # compress multiple files into stdout using legacy format - $(CAT) tmp-tlm1.lz4 tmp-tlm2.lz4 tmp-tlm3.lz4 > tmp-tlm-concat1 - $(RM) *.lz4 - $(LZ4) -l -m tmp-tlm1 tmp-tlm2 tmp-tlm3 -c > tmp-tlm-concat2 - test ! -f tmp-tlm1.lz4 # must not create .lz4 artefact - $(CMP) tmp-tlm-concat1 tmp-tlm-concat2 # must be equivalent - # # # decompress multiple files into stdout using legacy format - $(RM) tmp-tlm-concat1 tmp-tlm-concat2 - $(LZ4) -l -f -m tmp-tlm1 tmp-tlm2 tmp-tlm3 # generate .lz4 to decompress - $(CAT) tmp-tlm1 tmp-tlm2 tmp-tlm3 > tmp-tlm-concat1 # create concatenated reference - $(RM) tmp-tlm1 tmp-tlm2 tmp-tlm3 - $(LZ4) -d -m tmp-tlm1.lz4 tmp-tlm2.lz4 tmp-tlm3.lz4 -c > tmp-tlm-concat2 - $(LZ4) -d -l -m tmp-tlm1.lz4 tmp-tlm2.lz4 tmp-tlm3.lz4 -c > tmp-tlm-concat2 # -l mustn't impact option -d - test ! -f tmp-tlm1 # must not create file artefact - $(CMP) tmp-tlm-concat1 tmp-tlm-concat2 # must be equivalent - # # # compress multiple files, one of which is absent (must fail) - ! $(LZ4) -f -l -m tmp-tlm-concat1 notHere-legacy tmp-tlm-concat2 # must fail : notHere-legacy not present - @$(RM) tmp-tlm* - -test-lz4-basic: lz4 datagen unlz4 lz4cat - @echo "\n ---- test lz4 basic compression/decompression ----" - $(DATAGEN) -g0 | $(LZ4) -v | $(LZ4) -t - $(DATAGEN) -g16KB | $(LZ4) -9 | $(LZ4) -t - $(DATAGEN) -g20KB > tmp-tlb-dg20k - $(LZ4) < tmp-tlb-dg20k | $(LZ4) -d > tmp-tlb-dec - $(DIFF) -q tmp-tlb-dg20k tmp-tlb-dec - $(LZ4) --no-frame-crc < tmp-tlb-dg20k | $(LZ4) -d > tmp-tlb-dec - $(DIFF) -q tmp-tlb-dg20k tmp-tlb-dec - $(DATAGEN) | $(LZ4) -BI | $(LZ4) -t - $(DATAGEN) -g6M -P99 | $(LZ4) -9BD | $(LZ4) -t - $(DATAGEN) -g17M | $(LZ4) -9v | $(LZ4) -qt - $(DATAGEN) -g33M | $(LZ4) --no-frame-crc | $(LZ4) -t - $(DATAGEN) -g256MB | $(LZ4) -vqB4D | $(LZ4) -t - @echo "hello world" > tmp-tlb-hw - $(LZ4) --rm -f tmp-tlb-hw tmp-tlb-hw.lz4 - test ! -f tmp-tlb-hw # must fail (--rm) - test -f tmp-tlb-hw.lz4 - $(PRGDIR)/lz4cat tmp-tlb-hw.lz4 # must display hello world - test -f tmp-tlb-hw.lz4 - $(PRGDIR)/unlz4 --rm tmp-tlb-hw.lz4 tmp-tlb-hw - test -f tmp-tlb-hw - test ! -f tmp-tlb-hw.lz4 # must fail (--rm) - test ! -f tmp-tlb-hw.lz4.lz4 # must fail (unlz4) - $(PRGDIR)/lz4cat tmp-tlb-hw # pass-through mode - test -f tmp-tlb-hw - test ! -f tmp-tlb-hw.lz4 # must fail (lz4cat) - $(LZ4) tmp-tlb-hw tmp-tlb-hw.lz4 # creates tmp-tlb-hw.lz4 - $(PRGDIR)/lz4cat < tmp-tlb-hw.lz4 > tmp-tlb3 # checks lz4cat works with stdin (#285) - $(DIFF) -q tmp-tlb-hw tmp-tlb3 - $(PRGDIR)/lz4cat < tmp-tlb-hw > tmp-tlb2 # checks lz4cat works in pass-through mode - $(DIFF) -q tmp-tlb-hw tmp-tlb2 - cp tmp-tlb-hw ./-d - $(LZ4) --rm -- -d -d.lz4 # compresses ./d into ./-d.lz4 - test -f ./-d.lz4 - test ! -f ./-d - mv ./-d.lz4 ./-z - $(LZ4) -d --rm -- -z tmp-tlb4 # uncompresses ./-z into tmp-tlb4 - test ! -f ./-z - $(DIFF) -q tmp-tlb-hw tmp-tlb4 - $(LZ4) -f tmp-tlb-hw - $(LZ4) --list tmp-tlb-hw.lz4 # test --list on valid single-frame file - $(CAT) tmp-tlb-hw >> tmp-tlb-hw.lz4 - $(LZ4) -f tmp-tlb-hw.lz4 # uncompress valid frame followed by invalid data - $(LZ4) -BX tmp-tlb-hw -c -q | $(LZ4) -tv # test block checksum - # $(DATAGEN) -g20KB generates the same file every single time - # cannot save output of $(DATAGEN) -g20KB as input file to lz4 because the following shell commands are run before $(DATAGEN) -g20KB - test "$(shell $(DATAGEN) -g20KB | $(LZ4) -c --fast | wc -c)" -lt "$(shell $(DATAGEN) -g20KB | $(LZ4) -c --fast=9 | wc -c)" # -1 vs -9 - test "$(shell $(DATAGEN) -g20KB | $(LZ4) -c -1 | wc -c)" -lt "$(shell $(DATAGEN) -g20KB| $(LZ4) -c --fast=1 | wc -c)" # 1 vs -1 - test "$(shell $(DATAGEN) -g20KB | $(LZ4) -c --fast=1 | wc -c)" -eq "$(shell $(DATAGEN) -g20KB| $(LZ4) -c --fast| wc -c)" # checks default fast compression is -1 - ! $(LZ4) -c --fast=0 tmp-tlb-dg20K # lz4 should fail when fast=0 - ! $(LZ4) -c --fast=-1 tmp-tlb-dg20K # lz4 should fail when fast=-1 - # High --fast values can result in out-of-bound dereferences #876 - $(DATAGEN) -g1M | $(LZ4) -c --fast=999999999 > /dev/null - # Test for #596 - @echo "TEST" > tmp-tlb-test - $(LZ4) -m tmp-tlb-test - $(LZ4) tmp-tlb-test.lz4 tmp-tlb-test2 - $(DIFF) -q tmp-tlb-test tmp-tlb-test2 - @$(RM) tmp-tlb* - - - -test-lz4-dict: lz4 datagen - @echo "\n ---- test lz4 compression/decompression with dictionary ----" - $(DATAGEN) -g16KB > tmp-dict - $(DATAGEN) -g32KB > tmp-dict-sample-32k - < tmp-dict-sample-32k $(LZ4) -D tmp-dict | $(LZ4) -dD tmp-dict | diff - tmp-dict-sample-32k - $(DATAGEN) -g128MB > tmp-dict-sample-128m - < tmp-dict-sample-128m $(LZ4) -D tmp-dict | $(LZ4) -dD tmp-dict | diff - tmp-dict-sample-128m - touch tmp-dict-sample-0 - < tmp-dict-sample-0 $(LZ4) -D tmp-dict | $(LZ4) -dD tmp-dict | diff - tmp-dict-sample-0 - - < tmp-dict-sample-32k $(LZ4) -D tmp-dict-sample-0 | $(LZ4) -dD tmp-dict-sample-0 | diff - tmp-dict-sample-32k - < tmp-dict-sample-0 $(LZ4) -D tmp-dict-sample-0 | $(LZ4) -dD tmp-dict-sample-0 | diff - tmp-dict-sample-0 - - @echo "\n ---- test lz4 dictionary loading ----" - $(DATAGEN) -g128KB > tmp-dict-data-128KB - set -e; \ - for l in 0 1 4 128 32767 32768 32769 65535 65536 65537 98303 98304 98305 131071 131072 131073; do \ - $(DATAGEN) -g$$l > tmp-dict-$$l; \ - $(DD) if=tmp-dict-$$l of=tmp-dict-$$l-tail bs=1 count=65536 skip=$$((l > 65536 ? l - 65536 : 0)); \ - < tmp-dict-$$l $(LZ4) -D stdin tmp-dict-data-128KB -c | $(LZ4) -dD tmp-dict-$$l-tail | $(DIFF) - tmp-dict-data-128KB; \ - < tmp-dict-$$l-tail $(LZ4) -D stdin tmp-dict-data-128KB -c | $(LZ4) -dD tmp-dict-$$l | $(DIFF) - tmp-dict-data-128KB; \ - done - - @$(RM) tmp-dict* - -test-lz4-hugefile: lz4 datagen - @echo "\n ---- test huge files compression/decompression ----" - ./datagen -g6GB | $(LZ4) -vB5D | $(LZ4) -qt - ./datagen -g4500MB | $(LZ4) -v3BD | $(LZ4) -qt - # test large file size [2-4] GB - @$(DATAGEN) -g3G -P100 | $(LZ4) -vv | $(LZ4) --decompress --force --sparse - tmphf1 - @ls -ls tmphf1 - @$(DATAGEN) -g3G -P100 | $(LZ4) --quiet --content-size | $(LZ4) --verbose --decompress --force --sparse - tmphf2 - @ls -ls tmphf2 - $(DIFF) -s tmphf1 tmphf2 - @$(RM) tmphf* - -test-lz4-testmode: lz4 datagen - @echo "\n ---- bench mode ----" - $(LZ4) -bi0 - @echo "\n ---- test mode ----" - ! $(DATAGEN) | $(LZ4) -t - ! $(DATAGEN) | $(LZ4) -tf - @echo "\n ---- pass-through mode ----" - @echo "Why hello there " > tmp-tlt2.lz4 - ! $(LZ4) -f tmp-tlt2.lz4 > $(VOID) - ! $(DATAGEN) | $(LZ4) -dc > $(VOID) - ! $(DATAGEN) | $(LZ4) -df > $(VOID) - $(DATAGEN) | $(LZ4) -dcf > $(VOID) - @echo "Hello World !" > tmp-tlt1 - $(LZ4) -dcf tmp-tlt1 - @echo "from underground..." > tmp-tlt2 - $(LZ4) -dcfm tmp-tlt1 tmp-tlt2 - @echo "\n ---- non-existing source ----" - ! $(LZ4) file-does-not-exist - ! $(LZ4) -f file-does-not-exist - ! $(LZ4) -t file-does-not-exist - ! $(LZ4) -fm file1-dne file2-dne - @$(RM) tmp-tlt tmp-tlt1 tmp-tlt2 tmp-tlt2.lz4 - -test-lz4-opt-parser: lz4 datagen - @echo "\n ---- test opt-parser ----" - $(DATAGEN) -g16KB | $(LZ4) -12 | $(LZ4) -t - $(DATAGEN) -P10 | $(LZ4) -12B4 | $(LZ4) -t - $(DATAGEN) -g256K | $(LZ4) -12B4D | $(LZ4) -t - $(DATAGEN) -g512K -P25 | $(LZ4) -12BD | $(LZ4) -t - $(DATAGEN) -g1M | $(LZ4) -12B5 | $(LZ4) -t - $(DATAGEN) -g2M -P99 | $(LZ4) -11B4D | $(LZ4) -t - $(DATAGEN) -g4M | $(LZ4) -11vq | $(LZ4) -qt - $(DATAGEN) -g8M | $(LZ4) -11B4 | $(LZ4) -t - $(DATAGEN) -g16M -P90 | $(LZ4) -11B5 | $(LZ4) -t - $(DATAGEN) -g32M -P10 | $(LZ4) -11B5D | $(LZ4) -t - -test-lz4-essentials : lz4 datagen test-lz4-basic test-lz4-multiple test-lz4-multiple-legacy \ - test-lz4-frame-concatenation test-lz4-testmode \ - test-lz4-contentSize test-lz4-dict - @$(RM) tmp* - -test-lz4: lz4 datagen test-lz4-essentials test-lz4-opt-parser \ - test-lz4-sparse test-lz4-hugefile test-lz4-dict - @$(RM) tmp* - -test-lz4c: lz4c datagen - @echo "\n ---- test lz4c variant ----" - $(DATAGEN) -g256MB | $(LZ4)c -l -v | $(LZ4)c -t - -test-lz4c32: CFLAGS+=-m32 -test-lz4c32: test-lz4 - -test-interop-32-64: lz4 lz4c32 datagen - @echo "\n ---- test interoperability 32-bits -vs- 64 bits ----" - $(DATAGEN) -g16KB | $(LZ4)c32 -9 | $(LZ4) -t - $(DATAGEN) -P10 | $(LZ4) -9B4 | $(LZ4)c32 -t - $(DATAGEN) | $(LZ4)c32 | $(LZ4) -t - $(DATAGEN) -g1M | $(LZ4) -3B5 | $(LZ4)c32 -t - $(DATAGEN) -g256MB | $(LZ4)c32 -vqB4D | $(LZ4) -qt - $(DATAGEN) -g1G -P90 | $(LZ4) | $(LZ4)c32 -t - $(DATAGEN) -g6GB | $(LZ4)c32 -vq9BD | $(LZ4) -qt - -test-lz4c32-basic: lz4c32 datagen - @echo "\n ---- test lz4c32 32-bits version ----" - $(DATAGEN) -g16KB | $(LZ4)c32 -9 | $(LZ4)c32 -t - $(DATAGEN) | $(LZ4)c32 | $(LZ4)c32 -t - $(DATAGEN) -g256MB | $(LZ4)c32 -vqB4D | $(LZ4)c32 -qt - $(DATAGEN) -g6GB | $(LZ4)c32 -vqB5D | $(LZ4)c32 -qt - -test-platform: - @echo "\n ---- test lz4 $(QEMU_SYS) platform ----" - $(QEMU_SYS) $(DATAGEN) -g16KB | $(QEMU_SYS) $(LZ4) -9 | $(QEMU_SYS) $(LZ4) -t - $(QEMU_SYS) $(DATAGEN) | $(QEMU_SYS) $(LZ4) | $(QEMU_SYS) $(LZ4) -t - $(QEMU_SYS) $(DATAGEN) -g256MB | $(QEMU_SYS) $(LZ4) -vqB4D | $(QEMU_SYS) $(LZ4) -qt -ifneq ($(QEMU_SYS),qemu-arm-static) - $(QEMU_SYS) $(DATAGEN) -g3GB | $(QEMU_SYS) $(LZ4) -vqB5D | $(QEMU_SYS) $(LZ4) -qt -endif - -test-fullbench: fullbench - ./fullbench --no-prompt $(NB_LOOPS) $(TEST_FILES) - -test-fullbench32: CFLAGS += -m32 -test-fullbench32: test-fullbench - -test-fuzzer: fuzzer - ./fuzzer $(FUZZER_TIME) - -test-fuzzer32: CFLAGS += -m32 -test-fuzzer32: test-fuzzer - -test-frametest: frametest - ./frametest -v $(FUZZER_TIME) - -test-frametest32: CFLAGS += -m32 -test-frametest32: test-frametest - -test-mem: lz4 datagen fuzzer frametest fullbench - @echo "\n ---- valgrind tests : memory analyzer ----" - valgrind --leak-check=yes --error-exitcode=1 $(DATAGEN) -g50M > $(VOID) - $(DATAGEN) -g16KB > ftmdg16K - valgrind --leak-check=yes --error-exitcode=1 $(LZ4) -9 -BD -f ftmdg16K $(VOID) - $(DATAGEN) -g16KB -s2 > ftmdg16K2 - $(DATAGEN) -g16KB -s3 > ftmdg16K3 - valgrind --leak-check=yes --error-exitcode=1 $(LZ4) --force --multiple ftmdg16K ftmdg16K2 ftmdg16K3 - $(DATAGEN) -g7MB > ftmdg7M - valgrind --leak-check=yes --error-exitcode=1 $(LZ4) -9 -B5D -f ftmdg7M ftmdg16K2 - valgrind --leak-check=yes --error-exitcode=1 $(LZ4) -t ftmdg16K2 - valgrind --leak-check=yes --error-exitcode=1 $(LZ4) -bi1 ftmdg7M - valgrind --leak-check=yes --error-exitcode=1 ./fullbench -i1 ftmdg7M ftmdg16K2 - valgrind --leak-check=yes --error-exitcode=1 $(LZ4) -B4D -f -vq ftmdg7M $(VOID) - valgrind --leak-check=yes --error-exitcode=1 $(LZ4) --list -m ftm*.lz4 - valgrind --leak-check=yes --error-exitcode=1 $(LZ4) --list -m -v ftm*.lz4 - $(RM) ftm* - valgrind --leak-check=yes --error-exitcode=1 ./fuzzer -i64 -t1 - valgrind --leak-check=yes --error-exitcode=1 ./frametest -i256 - -test-mem32: lz4c32 datagen -# unfortunately, valgrind doesn't seem to work with non-native binary... - -test-decompress-partial : decompress-partial - @echo "\n ---- test decompress-partial ----" - ./decompress-partial$(EXT) - -endif diff --git a/ta6ob/lz4/tests/README.md b/ta6ob/lz4/tests/README.md deleted file mode 100644 index 75b7b9f..0000000 --- a/ta6ob/lz4/tests/README.md +++ /dev/null @@ -1,71 +0,0 @@ -Programs and scripts for automated testing of LZ4 -======================================================= - -This directory contains the following programs and scripts: -- `datagen` : Synthetic and parametrable data generator, for tests -- `frametest` : Test tool that checks lz4frame integrity on target platform -- `fullbench` : Precisely measure speed for each lz4 inner functions -- `fuzzer` : Test tool, to check lz4 integrity on target platform -- `test-lz4-speed.py` : script for testing lz4 speed difference between commits -- `test-lz4-versions.py` : compatibility test between lz4 versions stored on Github - - -#### `test-lz4-versions.py` - script for testing lz4 interoperability between versions - -This script creates `versionsTest` directory to which lz4 repository is cloned. -Then all taged (released) versions of lz4 are compiled. -In the following step interoperability between lz4 versions is checked. - - -#### `test-lz4-speed.py` - script for testing lz4 speed difference between commits - -This script creates `speedTest` directory to which lz4 repository is cloned. -Then it compiles all branches of lz4 and performs a speed benchmark for a given list of files (the `testFileNames` parameter). -After `sleepTime` (an optional parameter, default 300 seconds) seconds the script checks repository for new commits. -If a new commit is found it is compiled and a speed benchmark for this commit is performed. -The results of the speed benchmark are compared to the previous results. -If compression or decompression speed for one of lz4 levels is lower than `lowerLimit` (an optional parameter, default 0.98) the speed benchmark is restarted. -If second results are also lower than `lowerLimit` the warning e-mail is send to recipients from the list (the `emails` parameter). - -Additional remarks: -- To be sure that speed results are accurate the script should be run on a "stable" target system with no other jobs running in parallel -- Using the script with virtual machines can lead to large variations of speed results -- The speed benchmark is not performed until computers' load average is lower than `maxLoadAvg` (an optional parameter, default 0.75) -- The script sends e-mails using `mutt`; if `mutt` is not available it sends e-mails without attachments using `mail`; if both are not available it only prints a warning - - -The example usage with two test files, one e-mail address, and with an additional message: -``` -./test-lz4-speed.py "silesia.tar calgary.tar" "email@gmail.com" --message "tested on my laptop" --sleepTime 60 -``` - -To run the script in background please use: -``` -nohup ./test-lz4-speed.py testFileNames emails & -``` - -The full list of parameters: -``` -positional arguments: - testFileNames file names list for speed benchmark - emails list of e-mail addresses to send warnings - -optional arguments: - -h, --help show this help message and exit - --message MESSAGE attach an additional message to e-mail - --lowerLimit LOWERLIMIT - send email if speed is lower than given limit - --maxLoadAvg MAXLOADAVG - maximum load average to start testing - --lastCLevel LASTCLEVEL - last compression level for testing - --sleepTime SLEEPTIME - frequency of repository checking in seconds -``` - - -#### License - -All files in this directory are licensed under GPL-v2. -See [COPYING](COPYING) for details. -The text of the license is also included at the top of each source file. diff --git a/ta6ob/lz4/tests/checkFrame.c b/ta6ob/lz4/tests/checkFrame.c deleted file mode 100644 index f9a1c14..0000000 --- a/ta6ob/lz4/tests/checkFrame.c +++ /dev/null @@ -1,303 +0,0 @@ - /* - checkFrame - verify frame headers - Copyright (C) Yann Collet 2014-present - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 homepage : http://www.lz4.org - - LZ4 source repository : https://github.com/lz4/lz4 - */ - - /*-************************************ - * Includes - **************************************/ - #include "util.h" /* U32 */ - #include /* malloc, free */ - #include /* fprintf */ - #include /* strcmp */ - #include /* clock_t, clock(), CLOCKS_PER_SEC */ - #include - #include "lz4frame.h" /* include multiple times to test correctness/safety */ - #include "lz4frame.h" - #define LZ4F_STATIC_LINKING_ONLY - #include "lz4frame.h" - #include "lz4frame.h" - #include "lz4.h" /* LZ4_VERSION_STRING */ - #define XXH_STATIC_LINKING_ONLY - #include "xxhash.h" /* XXH64 */ - - - /*-************************************ - * Constants - **************************************/ - #define KB *(1U<<10) - #define MB *(1U<<20) - #define GB *(1U<<30) - - - /*-************************************ - * Macros - **************************************/ - #define DISPLAY(...) fprintf(stderr, __VA_ARGS__) - #define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); } - - /************************************** - * Exceptions - ***************************************/ - #ifndef DEBUG - # define DEBUG 0 - #endif - #define DEBUGOUTPUT(...) if (DEBUG) DISPLAY(__VA_ARGS__); - #define EXM_THROW(error, ...) \ -{ \ - DEBUGOUTPUT("Error defined at %s, line %i : \n", __FILE__, __LINE__); \ - DISPLAYLEVEL(1, "Error %i : ", error); \ - DISPLAYLEVEL(1, __VA_ARGS__); \ - DISPLAYLEVEL(1, " \n"); \ - return(error); \ -} - - - -/*-*************************************** -* Local Parameters -*****************************************/ -static U32 no_prompt = 0; -static U32 displayLevel = 2; -static U32 use_pause = 0; - - -/*-******************************************************* -* Fuzzer functions -*********************************************************/ -#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) -#define MAX(a,b) ( (a) > (b) ? (a) : (b) ) - -typedef struct { - void* srcBuffer; - size_t srcBufferSize; - void* dstBuffer; - size_t dstBufferSize; - LZ4F_decompressionContext_t ctx; -} cRess_t; - -static int createCResources(cRess_t* ress) -{ - ress->srcBufferSize = 4 MB; - ress->srcBuffer = malloc(ress->srcBufferSize); - ress->dstBufferSize = 4 MB; - ress->dstBuffer = malloc(ress->dstBufferSize); - - if (!ress->srcBuffer || !ress->dstBuffer) { - free(ress->srcBuffer); - free(ress->dstBuffer); - EXM_THROW(20, "Allocation error : not enough memory"); - } - - if (LZ4F_isError( LZ4F_createDecompressionContext(&(ress->ctx), LZ4F_VERSION) )) { - free(ress->srcBuffer); - free(ress->dstBuffer); - EXM_THROW(21, "Unable to create decompression context"); - } - return 0; -} - -static void freeCResources(cRess_t ress) -{ - free(ress.srcBuffer); - free(ress.dstBuffer); - - (void) LZ4F_freeDecompressionContext(ress.ctx); -} - -int frameCheck(cRess_t ress, FILE* const srcFile, unsigned bsid, size_t blockSize) -{ - LZ4F_errorCode_t nextToLoad = 0; - size_t curblocksize = 0; - int partialBlock = 0; - - /* Main Loop */ - for (;;) { - size_t readSize; - size_t pos = 0; - size_t decodedBytes = ress.dstBufferSize; - size_t remaining; - LZ4F_frameInfo_t frameInfo; - - /* Read input */ - readSize = fread(ress.srcBuffer, 1, ress.srcBufferSize, srcFile); - if (!readSize) break; /* reached end of file or stream */ - - while (pos < readSize) { /* still to read */ - /* Decode Input (at least partially) */ - if (!nextToLoad) { - /* LZ4F_decompress returned 0 : starting new frame */ - curblocksize = 0; - remaining = readSize - pos; - nextToLoad = LZ4F_getFrameInfo(ress.ctx, &frameInfo, (char*)(ress.srcBuffer)+pos, &remaining); - if (LZ4F_isError(nextToLoad)) - EXM_THROW(22, "Error getting frame info: %s", - LZ4F_getErrorName(nextToLoad)); - if (frameInfo.blockSizeID != bsid) - EXM_THROW(23, "Block size ID %u != expected %u", - frameInfo.blockSizeID, bsid); - pos += remaining; - /* nextToLoad should be block header size */ - remaining = nextToLoad; - decodedBytes = ress.dstBufferSize; - nextToLoad = LZ4F_decompress(ress.ctx, ress.dstBuffer, &decodedBytes, (char*)(ress.srcBuffer)+pos, &remaining, NULL); - if (LZ4F_isError(nextToLoad)) EXM_THROW(24, "Decompression error : %s", LZ4F_getErrorName(nextToLoad)); - pos += remaining; - } - decodedBytes = ress.dstBufferSize; - /* nextToLoad should be just enough to cover the next block */ - if (nextToLoad > (readSize - pos)) { - /* block is not fully contained in current buffer */ - partialBlock = 1; - remaining = readSize - pos; - } else { - if (partialBlock) { - partialBlock = 0; - } - remaining = nextToLoad; - } - nextToLoad = LZ4F_decompress(ress.ctx, ress.dstBuffer, &decodedBytes, (char*)(ress.srcBuffer)+pos, &remaining, NULL); - if (LZ4F_isError(nextToLoad)) EXM_THROW(24, "Decompression error : %s", LZ4F_getErrorName(nextToLoad)); - curblocksize += decodedBytes; - pos += remaining; - if (!partialBlock) { - /* detect small block due to end of frame; the final 4-byte frame checksum could be left in the buffer */ - if ((curblocksize != 0) && (nextToLoad > 4)) { - if (curblocksize != blockSize) - EXM_THROW(25, "Block size %u != expected %u, pos %u\n", - (unsigned)curblocksize, (unsigned)blockSize, (unsigned)pos); - } - curblocksize = 0; - } - } - } - /* can be out because readSize == 0, which could be an fread() error */ - if (ferror(srcFile)) EXM_THROW(26, "Read error"); - - if (nextToLoad!=0) EXM_THROW(27, "Unfinished stream"); - - return 0; -} - -int FUZ_usage(const char* programName) -{ - DISPLAY( "Usage :\n"); - DISPLAY( " %s [args] filename\n", programName); - DISPLAY( "\n"); - DISPLAY( "Arguments :\n"); - DISPLAY( " -b# : expected blocksizeID [4-7] (required)\n"); - DISPLAY( " -B# : expected blocksize [32-4194304] (required)\n"); - DISPLAY( " -v : verbose\n"); - DISPLAY( " -h : display help and exit\n"); - return 0; -} - - -int main(int argc, const char** argv) -{ - int argNb; - unsigned bsid=0; - size_t blockSize=0; - const char* const programName = argv[0]; - - /* Check command line */ - for (argNb=1; argNb='0') && (*argument<='9')) { - bsid *= 10; - bsid += (unsigned)(*argument - '0'); - argument++; - } - break; - - case 'B': - argument++; - blockSize=0; - while ((*argument>='0') && (*argument<='9')) { - blockSize *= 10; - blockSize += (size_t)(*argument - '0'); - argument++; - } - break; - - default: - ; - return FUZ_usage(programName); - } - } - } else { - int err; - FILE *srcFile; - cRess_t ress; - if (bsid == 0 || blockSize == 0) - return FUZ_usage(programName); - DISPLAY("Starting frame checker (%i-bits, %s)\n", (int)(sizeof(size_t)*8), LZ4_VERSION_STRING); - err = createCResources(&ress); - if (err) return (err); - srcFile = fopen(argument, "rb"); - if ( srcFile==NULL ) { - freeCResources(ress); - EXM_THROW(1, "%s: %s \n", argument, strerror(errno)); - } - assert (srcFile != NULL); - err = frameCheck(ress, srcFile, bsid, blockSize); - freeCResources(ress); - fclose(srcFile); - return (err); - } - } - return 0; -} diff --git a/ta6ob/lz4/tests/checkTag.c b/ta6ob/lz4/tests/checkTag.c deleted file mode 100644 index 4a33415..0000000 --- a/ta6ob/lz4/tests/checkTag.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - checkTag.c - Version validation tool for LZ4 - Copyright (C) Yann Collet 2018 - present - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 homepage : http://www.lz4.org - - LZ4 source repo : https://github.com/lz4/lz4 -*/ - -/* checkTag command : - * $ ./checkTag tag - * checkTag validates tags of following format : v[0-9].[0-9].[0-9]{any} - * The tag is then compared to LZ4 version number. - * They are compatible if first 3 digits are identical. - * Anything beyond that is free, and doesn't impact validation. - * Example : tag v1.8.1.2 is compatible with version 1.8.1 - * When tag and version are not compatible, program exits with error code 1. - * When they are compatible, it exists with a code 0. - * checkTag is intended to be used in automated testing environment. - */ - -#include /* printf */ -#include /* strlen, strncmp */ -#include "lz4.h" /* LZ4_VERSION_STRING */ - - -/* validate() : - * @return 1 if tag is compatible, 0 if not. - */ -static int validate(const char* const tag) -{ - size_t const tagLength = strlen(tag); - size_t const verLength = strlen(LZ4_VERSION_STRING); - - if (tagLength < 2) return 0; - if (tag[0] != 'v') return 0; - if (tagLength <= verLength) return 0; - - if (strncmp(LZ4_VERSION_STRING, tag+1, verLength)) return 0; - - return 1; -} - -int main(int argc, const char** argv) -{ - const char* const exeName = argv[0]; - const char* const tag = argv[1]; - if (argc!=2) { - printf("incorrect usage : %s tag \n", exeName); - return 2; - } - - printf("Version : %s \n", LZ4_VERSION_STRING); - printf("Tag : %s \n", tag); - - if (validate(tag)) { - printf("OK : tag is compatible with lz4 version \n"); - return 0; - } - - printf("!! error : tag and versions are not compatible !! \n"); - return 1; -} diff --git a/ta6ob/lz4/tests/datagencli.c b/ta6ob/lz4/tests/datagencli.c deleted file mode 100644 index c985197..0000000 --- a/ta6ob/lz4/tests/datagencli.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - datagencli.c - compressible data command line generator - Copyright (C) Yann Collet 2012-2016 - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - Public forum : https://groups.google.com/forum/#!forum/lz4c -*/ - -/************************************** -* Includes -**************************************/ -#include "util.h" /* U32 */ -#include /* fprintf, stderr */ -#include "datagen.h" /* RDG_generate */ -#include "lz4.h" /* LZ4_VERSION_STRING */ - - -/************************************** -* Constants -**************************************/ -#define KB *(1 <<10) -#define MB *(1 <<20) -#define GB *(1U<<30) - -#define SIZE_DEFAULT (64 KB) -#define SEED_DEFAULT 0 -#define COMPRESSIBILITY_DEFAULT 50 - - -/************************************** -* Macros -**************************************/ -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); } -static unsigned displayLevel = 2; - - -/********************************************************* -* Command line -*********************************************************/ -static int usage(char* programName) -{ - DISPLAY( "Compressible data generator\n"); - DISPLAY( "Usage :\n"); - DISPLAY( " %s [size] [args]\n", programName); - DISPLAY( "\n"); - DISPLAY( "Arguments :\n"); - DISPLAY( " -g# : generate # data (default:%i)\n", SIZE_DEFAULT); - DISPLAY( " -s# : Select seed (default:%i)\n", SEED_DEFAULT); - DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", COMPRESSIBILITY_DEFAULT); - DISPLAY( " -h : display help and exit\n"); - DISPLAY( "Special values :\n"); - DISPLAY( " -P0 : generate incompressible noise\n"); - DISPLAY( " -P100 : generate sparse files\n"); - return 0; -} - - -int main(int argc, char** argv) -{ - int argNb; - double proba = (double)COMPRESSIBILITY_DEFAULT / 100; - double litProba = 0.0; - U64 size = SIZE_DEFAULT; - U32 seed = SEED_DEFAULT; - char* programName; - - /* Check command line */ - programName = argv[0]; - for(argNb=1; argNb='0') && (*argument<='9')) - { - size *= 10; - size += *argument - '0'; - argument++; - } - if (*argument=='K') { size <<= 10; argument++; } - if (*argument=='M') { size <<= 20; argument++; } - if (*argument=='G') { size <<= 30; argument++; } - if (*argument=='B') { argument++; } - break; - case 's': - argument++; - seed=0; - while ((*argument>='0') && (*argument<='9')) - { - seed *= 10; - seed += *argument - '0'; - argument++; - } - break; - case 'P': - argument++; - proba=0.0; - while ((*argument>='0') && (*argument<='9')) - { - proba *= 10; - proba += *argument - '0'; - argument++; - } - if (proba>100.) proba=100.; - proba /= 100.; - break; - case 'L': /* hidden argument : Literal distribution probability */ - argument++; - litProba=0.; - while ((*argument>='0') && (*argument<='9')) - { - litProba *= 10; - litProba += *argument - '0'; - argument++; - } - if (litProba>100.) litProba=100.; - litProba /= 100.; - break; - case 'v': - displayLevel = 4; - argument++; - break; - default: - return usage(programName); - } - } - - } - } - - DISPLAYLEVEL(4, "Data Generator %s \n", LZ4_VERSION_STRING); - DISPLAYLEVEL(3, "Seed = %u \n", seed); - if (proba!=COMPRESSIBILITY_DEFAULT) DISPLAYLEVEL(3, "Compressibility : %i%%\n", (U32)(proba*100)); - - RDG_genOut(size, proba, litProba, seed); - DISPLAYLEVEL(1, "\n"); - - return 0; -} diff --git a/ta6ob/lz4/tests/decompress-partial.c b/ta6ob/lz4/tests/decompress-partial.c deleted file mode 100644 index 4e124b7..0000000 --- a/ta6ob/lz4/tests/decompress-partial.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "stdio.h" -#include "string.h" -#include "lz4.h" - -const char source[] = - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\n" - "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim\n" - "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea\n" - "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate\n" - "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat\n" - "cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id\n" - "est laborum.\n" - "\n" - "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium\n" - "doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore\n" - "veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim\n" - "ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia\n" - "consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque\n" - "porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur,\n" - "adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore\n" - "et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis\n" - "nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid\n" - "ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea\n" - "voluptate velit esse quam nihil molestiae consequatur, vel illum qui\n" - "dolorem eum fugiat quo voluptas nulla pariatur?\n"; - -#define BUFFER_SIZE 2048 - -int main(void) -{ - int srcLen = (int)strlen(source); - char cmpBuffer[BUFFER_SIZE]; - char outBuffer[BUFFER_SIZE]; - int cmpSize; - int i; - - cmpSize = LZ4_compress_default(source, cmpBuffer, srcLen, BUFFER_SIZE); - - for (i = cmpSize; i < cmpSize + 10; ++i) { - int result = LZ4_decompress_safe_partial(cmpBuffer, outBuffer, i, srcLen, BUFFER_SIZE); - if ((result < 0) || (result != srcLen) || memcmp(source, outBuffer, srcLen)) { - printf("test decompress-partial error \n"); - return -1; - } - } - - printf("test decompress-partial OK \n"); - return 0; -} diff --git a/ta6ob/lz4/tests/frametest.c b/ta6ob/lz4/tests/frametest.c deleted file mode 100644 index e613cbf..0000000 --- a/ta6ob/lz4/tests/frametest.c +++ /dev/null @@ -1,1281 +0,0 @@ -/* - frameTest - test tool for lz4frame - Copyright (C) Yann Collet 2014-2016 - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 homepage : http://www.lz4.org - - LZ4 source repository : https://github.com/lz4/lz4 -*/ - -/*-************************************ -* Compiler specific -**************************************/ -#ifdef _MSC_VER /* Visual Studio */ -# pragma warning(disable : 26451) /* disable: Arithmetic overflow */ -#endif - - -/*-************************************ -* Includes -**************************************/ -#include "util.h" /* U32 */ -#include /* malloc, free */ -#include /* fprintf */ -#include /* strcmp */ -#include /* clock_t, clock(), CLOCKS_PER_SEC */ -#include -#include "lz4frame.h" /* included multiple times to test correctness/safety */ -#include "lz4frame.h" -#define LZ4F_STATIC_LINKING_ONLY -#include "lz4frame.h" -#include "lz4frame.h" -#define LZ4_STATIC_LINKING_ONLY /* LZ4_DISTANCE_MAX */ -#include "lz4.h" /* LZ4_VERSION_STRING */ -#define XXH_STATIC_LINKING_ONLY -#include "xxhash.h" /* XXH64 */ - - -/* unoptimized version; solves endianess & alignment issues */ -static void FUZ_writeLE32 (void* dstVoidPtr, U32 value32) -{ - BYTE* dstPtr = (BYTE*)dstVoidPtr; - dstPtr[0] = (BYTE) value32; - dstPtr[1] = (BYTE)(value32 >> 8); - dstPtr[2] = (BYTE)(value32 >> 16); - dstPtr[3] = (BYTE)(value32 >> 24); -} - - -/*-************************************ -* Constants -**************************************/ -#define LZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U - -#define KB *(1U<<10) -#define MB *(1U<<20) -#define GB *(1U<<30) - -static const U32 nbTestsDefault = 256 KB; -#define FUZ_COMPRESSIBILITY_DEFAULT 50 -static const U32 prime1 = 2654435761U; -static const U32 prime2 = 2246822519U; - - -/*-************************************ -* Macros -**************************************/ -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (displayLevel>=l) { DISPLAY(__VA_ARGS__); } -#define DISPLAYUPDATE(l, ...) if (displayLevel>=l) { \ - if ((FUZ_GetClockSpan(g_clockTime) > refreshRate) || (displayLevel>=4)) \ - { g_clockTime = clock(); DISPLAY(__VA_ARGS__); \ - if (displayLevel>=4) fflush(stdout); } } -static const clock_t refreshRate = CLOCKS_PER_SEC / 6; -static clock_t g_clockTime = 0; - - -/*-*************************************** -* Local Parameters -*****************************************/ -static U32 no_prompt = 0; -static U32 displayLevel = 2; -static U32 use_pause = 0; - - -/*-******************************************************* -* Fuzzer functions -*********************************************************/ -#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) -#define MAX(a,b) ( (a) > (b) ? (a) : (b) ) - -static clock_t FUZ_GetClockSpan(clock_t clockStart) -{ - return clock() - clockStart; /* works even if overflow; max span ~ 30 mn */ -} - - -#define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r))) -unsigned int FUZ_rand(unsigned int* src) -{ - U32 rand32 = *src; - rand32 *= prime1; - rand32 += prime2; - rand32 = FUZ_rotl32(rand32, 13); - *src = rand32; - return rand32 >> 5; -} - - -#define FUZ_RAND15BITS (FUZ_rand(seed) & 0x7FFF) -#define FUZ_RANDLENGTH ( (FUZ_rand(seed) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15) -static void FUZ_fillCompressibleNoiseBuffer(void* buffer, size_t bufferSize, double proba, U32* seed) -{ - BYTE* BBuffer = (BYTE*)buffer; - size_t pos = 0; - U32 P32 = (U32)(32768 * proba); - - /* First Byte */ - BBuffer[pos++] = (BYTE)(FUZ_rand(seed)); - - while (pos < bufferSize) { - /* Select : Literal (noise) or copy (within 64K) */ - if (FUZ_RAND15BITS < P32) { - /* Copy (within 64K) */ - size_t const lengthRand = FUZ_RANDLENGTH + 4; - size_t const length = MIN(lengthRand, bufferSize - pos); - size_t const end = pos + length; - size_t const offsetRand = FUZ_RAND15BITS + 1; - size_t const offset = MIN(offsetRand, pos); - size_t match = pos - offset; - while (pos < end) BBuffer[pos++] = BBuffer[match++]; - } else { - /* Literal (noise) */ - size_t const lengthRand = FUZ_RANDLENGTH + 4; - size_t const length = MIN(lengthRand, bufferSize - pos); - size_t const end = pos + length; - while (pos < end) BBuffer[pos++] = (BYTE)(FUZ_rand(seed) >> 5); - } } -} - - -static unsigned FUZ_highbit(U32 v32) -{ - unsigned nbBits = 0; - if (v32==0) return 0; - while (v32) {v32 >>= 1; nbBits ++;} - return nbBits; -} - - -/*-******************************************************* -* Tests -*********************************************************/ -#define CHECK_V(v,f) v = f; if (LZ4F_isError(v)) { fprintf(stderr, "%s \n", LZ4F_getErrorName(v)); goto _output_error; } -#define CHECK(f) { LZ4F_errorCode_t const CHECK_V(err_ , f); } - -int basicTests(U32 seed, double compressibility) -{ -#define COMPRESSIBLE_NOISE_LENGTH (2 MB) - void* const CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH); - size_t const cBuffSize = LZ4F_compressFrameBound(COMPRESSIBLE_NOISE_LENGTH, NULL); - void* const compressedBuffer = malloc(cBuffSize); - void* const decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH); - U32 randState = seed; - size_t cSize, testSize; - LZ4F_decompressionContext_t dCtx = NULL; - LZ4F_compressionContext_t cctx = NULL; - U64 crcOrig; - int basicTests_error = 0; - LZ4F_preferences_t prefs; - memset(&prefs, 0, sizeof(prefs)); - - if (!CNBuffer || !compressedBuffer || !decodedBuffer) { - DISPLAY("allocation error, not enough memory to start fuzzer tests \n"); - goto _output_error; - } - FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, &randState); - crcOrig = XXH64(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, 1); - - /* LZ4F_compressBound() : special case : srcSize == 0 */ - DISPLAYLEVEL(3, "LZ4F_compressBound(0) = "); - { size_t const cBound = LZ4F_compressBound(0, NULL); - if (cBound < 64 KB) goto _output_error; - DISPLAYLEVEL(3, " %u \n", (U32)cBound); - } - - /* LZ4F_compressBound() : special case : automatic flushing enabled */ - DISPLAYLEVEL(3, "LZ4F_compressBound(1 KB, autoFlush=1) = "); - { size_t cBound; - LZ4F_preferences_t autoFlushPrefs; - memset(&autoFlushPrefs, 0, sizeof(autoFlushPrefs)); - autoFlushPrefs.autoFlush = 1; - cBound = LZ4F_compressBound(1 KB, &autoFlushPrefs); - if (cBound > 64 KB) goto _output_error; - DISPLAYLEVEL(3, " %u \n", (U32)cBound); - } - - /* LZ4F_compressBound() : special case : automatic flushing disabled */ - DISPLAYLEVEL(3, "LZ4F_compressBound(1 KB, autoFlush=0) = "); - { size_t const cBound = LZ4F_compressBound(1 KB, &prefs); - if (cBound < 64 KB) goto _output_error; - DISPLAYLEVEL(3, " %u \n", (U32)cBound); - } - - /* Special case : null-content frame */ - testSize = 0; - DISPLAYLEVEL(3, "LZ4F_compressFrame, compress null content : "); - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL)); - DISPLAYLEVEL(3, "null content encoded into a %u bytes frame \n", (unsigned)cSize); - - DISPLAYLEVEL(3, "LZ4F_createDecompressionContext \n"); - CHECK ( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) ); - - DISPLAYLEVEL(3, "LZ4F_getFrameInfo on null-content frame (#157) \n"); - assert(cSize >= LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH); - { LZ4F_frameInfo_t frame_info; - size_t const fhs = LZ4F_headerSize(compressedBuffer, LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH); - size_t avail_in = fhs; - CHECK( fhs ); - CHECK( LZ4F_getFrameInfo(dCtx, &frame_info, compressedBuffer, &avail_in) ); - if (avail_in != fhs) goto _output_error; /* must consume all, since header size is supposed to be exact */ - } - - DISPLAYLEVEL(3, "LZ4F_freeDecompressionContext \n"); - CHECK( LZ4F_freeDecompressionContext(dCtx) ); - dCtx = NULL; - - /* test one-pass frame compression */ - testSize = COMPRESSIBLE_NOISE_LENGTH; - - DISPLAYLEVEL(3, "LZ4F_compressFrame, using fast level -3 : "); - { LZ4F_preferences_t fastCompressPrefs; - memset(&fastCompressPrefs, 0, sizeof(fastCompressPrefs)); - fastCompressPrefs.compressionLevel = -3; - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, &fastCompressPrefs)); - DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize); - } - - DISPLAYLEVEL(3, "LZ4F_compressFrame, using default preferences : "); - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, NULL), CNBuffer, testSize, NULL)); - DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize); - - DISPLAYLEVEL(3, "Decompression test : \n"); - { size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH; - size_t compressedBufferSize = cSize; - - CHECK( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) ); - - DISPLAYLEVEL(3, "Single Pass decompression : "); - CHECK( LZ4F_decompress(dCtx, decodedBuffer, &decodedBufferSize, compressedBuffer, &compressedBufferSize, NULL) ); - { U64 const crcDest = XXH64(decodedBuffer, decodedBufferSize, 1); - if (crcDest != crcOrig) goto _output_error; } - DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedBufferSize); - - DISPLAYLEVEL(3, "Reusing decompression context \n"); - { size_t const missingBytes = 4; - size_t iSize = compressedBufferSize - missingBytes; - const BYTE* cBuff = (const BYTE*) compressedBuffer; - BYTE* const ostart = (BYTE*)decodedBuffer; - BYTE* op = ostart; - BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH; - size_t decResult, oSize = COMPRESSIBLE_NOISE_LENGTH; - DISPLAYLEVEL(3, "Missing last %u bytes : ", (U32)missingBytes); - CHECK_V(decResult, LZ4F_decompress(dCtx, op, &oSize, cBuff, &iSize, NULL)); - if (decResult != missingBytes) { - DISPLAY("%u bytes missing != %u bytes requested \n", (U32)missingBytes, (U32)decResult); - goto _output_error; - } - DISPLAYLEVEL(3, "indeed, requests %u bytes \n", (unsigned)decResult); - cBuff += iSize; - iSize = decResult; - op += oSize; - oSize = (size_t)(oend-op); - decResult = LZ4F_decompress(dCtx, op, &oSize, cBuff, &iSize, NULL); - if (decResult != 0) goto _output_error; /* should finish now */ - op += oSize; - if (op>oend) { DISPLAY("decompression write overflow \n"); goto _output_error; } - { U64 const crcDest = XXH64(decodedBuffer, (size_t)(op-ostart), 1); - if (crcDest != crcOrig) goto _output_error; - } } - - { size_t oSize = 0; - size_t iSize = 0; - LZ4F_frameInfo_t fi; - const BYTE* ip = (BYTE*)compressedBuffer; - - DISPLAYLEVEL(3, "Start by feeding 0 bytes, to get next input size : "); - CHECK( LZ4F_decompress(dCtx, NULL, &oSize, ip, &iSize, NULL) ); - //DISPLAYLEVEL(3, " %u \n", (unsigned)errorCode); - DISPLAYLEVEL(3, " OK \n"); - - DISPLAYLEVEL(3, "LZ4F_getFrameInfo on zero-size input : "); - { size_t nullSize = 0; - size_t const fiError = LZ4F_getFrameInfo(dCtx, &fi, ip, &nullSize); - if (LZ4F_getErrorCode(fiError) != LZ4F_ERROR_frameHeader_incomplete) { - DISPLAYLEVEL(3, "incorrect error : %s != ERROR_frameHeader_incomplete \n", - LZ4F_getErrorName(fiError)); - goto _output_error; - } - DISPLAYLEVEL(3, " correctly failed : %s \n", LZ4F_getErrorName(fiError)); - } - - DISPLAYLEVEL(3, "LZ4F_getFrameInfo on not enough input : "); - { size_t inputSize = 6; - size_t const fiError = LZ4F_getFrameInfo(dCtx, &fi, ip, &inputSize); - if (LZ4F_getErrorCode(fiError) != LZ4F_ERROR_frameHeader_incomplete) { - DISPLAYLEVEL(3, "incorrect error : %s != ERROR_frameHeader_incomplete \n", LZ4F_getErrorName(fiError)); - goto _output_error; - } - DISPLAYLEVEL(3, " correctly failed : %s \n", LZ4F_getErrorName(fiError)); - } - - DISPLAYLEVEL(3, "LZ4F_getFrameInfo on enough input : "); - iSize = LZ4F_headerSize(ip, LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH); - CHECK( iSize ); - CHECK( LZ4F_getFrameInfo(dCtx, &fi, ip, &iSize) ); - DISPLAYLEVEL(3, " correctly decoded \n"); - } - - DISPLAYLEVEL(3, "Decode a buggy input : "); - assert(COMPRESSIBLE_NOISE_LENGTH > 64); - assert(cSize > 48); - memcpy(decodedBuffer, (char*)compressedBuffer+16, 32); /* save correct data */ - memcpy((char*)compressedBuffer+16, (const char*)decodedBuffer+32, 32); /* insert noise */ - { size_t dbSize = COMPRESSIBLE_NOISE_LENGTH; - size_t cbSize = cSize; - size_t const decompressError = LZ4F_decompress(dCtx, decodedBuffer, &dbSize, - compressedBuffer, &cbSize, - NULL); - if (!LZ4F_isError(decompressError)) goto _output_error; - DISPLAYLEVEL(3, "error detected : %s \n", LZ4F_getErrorName(decompressError)); - } - memcpy((char*)compressedBuffer+16, decodedBuffer, 32); /* restore correct data */ - - DISPLAYLEVEL(3, "Reset decompression context, since it's left in error state \n"); - LZ4F_resetDecompressionContext(dCtx); /* always successful */ - - DISPLAYLEVEL(3, "Byte after byte : "); - { BYTE* const ostart = (BYTE*)decodedBuffer; - BYTE* op = ostart; - BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH; - const BYTE* ip = (const BYTE*) compressedBuffer; - const BYTE* const iend = ip + cSize; - while (ip < iend) { - size_t oSize = (size_t)(oend-op); - size_t iSize = 1; - CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) ); - op += oSize; - ip += iSize; - } - { U64 const crcDest = XXH64(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, 1); - if (crcDest != crcOrig) goto _output_error; - } - DISPLAYLEVEL(3, "Regenerated %u/%u bytes \n", (unsigned)(op-ostart), (unsigned)COMPRESSIBLE_NOISE_LENGTH); - } - } - - DISPLAYLEVEL(3, "Using 64 KB block : "); - prefs.frameInfo.blockSizeID = LZ4F_max64KB; - prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled; - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs)); - DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize); - - DISPLAYLEVEL(3, "without checksum : "); - prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum; - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs)); - DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize); - - DISPLAYLEVEL(3, "Using 256 KB block : "); - prefs.frameInfo.blockSizeID = LZ4F_max256KB; - prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled; - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs)); - DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize); - - DISPLAYLEVEL(3, "Decompression test : \n"); - { size_t const decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH; - unsigned const maxBits = FUZ_highbit((U32)decodedBufferSize); - BYTE* const ostart = (BYTE*)decodedBuffer; - BYTE* op = ostart; - BYTE* const oend = ostart + COMPRESSIBLE_NOISE_LENGTH; - const BYTE* ip = (const BYTE*)compressedBuffer; - const BYTE* const iend = (const BYTE*)compressedBuffer + cSize; - - DISPLAYLEVEL(3, "random segment sizes : "); - while (ip < iend) { - unsigned const nbBits = FUZ_rand(&randState) % maxBits; - size_t iSize = (FUZ_rand(&randState) & ((1< (size_t)(iend-ip)) iSize = (size_t)(iend-ip); - CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) ); - op += oSize; - ip += iSize; - } - { size_t const decodedSize = (size_t)(op - ostart); - U64 const crcDest = XXH64(decodedBuffer, decodedSize, 1); - if (crcDest != crcOrig) goto _output_error; - DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize); - } - - CHECK( LZ4F_freeDecompressionContext(dCtx) ); - dCtx = NULL; - } - - DISPLAYLEVEL(3, "without checksum : "); - prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum; - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) ); - DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize); - - DISPLAYLEVEL(3, "Using 1 MB block : "); - prefs.frameInfo.blockSizeID = LZ4F_max1MB; - prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled; - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) ); - DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize); - - DISPLAYLEVEL(3, "without frame checksum : "); - prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum; - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) ); - DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize); - - DISPLAYLEVEL(3, "Using 4 MB block : "); - prefs.frameInfo.blockSizeID = LZ4F_max4MB; - prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled; - { size_t const dstCapacity = LZ4F_compressFrameBound(testSize, &prefs); - DISPLAYLEVEL(4, "dstCapacity = %u ; ", (U32)dstCapacity) - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, dstCapacity, CNBuffer, testSize, &prefs) ); - DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize); - } - - DISPLAYLEVEL(3, "without frame checksum : "); - prefs.frameInfo.contentChecksumFlag = LZ4F_noContentChecksum; - { size_t const dstCapacity = LZ4F_compressFrameBound(testSize, &prefs); - DISPLAYLEVEL(4, "dstCapacity = %u ; ", (U32)dstCapacity) - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, dstCapacity, CNBuffer, testSize, &prefs) ); - DISPLAYLEVEL(3, "Compressed %u bytes into a %u bytes frame \n", (U32)testSize, (U32)cSize); - } - - DISPLAYLEVEL(3, "LZ4F_compressFrame with block checksum : "); - memset(&prefs, 0, sizeof(prefs)); - prefs.frameInfo.blockChecksumFlag = LZ4F_blockChecksumEnabled; - CHECK_V(cSize, LZ4F_compressFrame(compressedBuffer, LZ4F_compressFrameBound(testSize, &prefs), CNBuffer, testSize, &prefs) ); - DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)cSize); - - DISPLAYLEVEL(3, "Decompress with block checksum : "); - { size_t iSize = cSize; - size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH; - LZ4F_decompressionContext_t dctx; - CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) ); - CHECK( LZ4F_decompress(dctx, decodedBuffer, &decodedSize, compressedBuffer, &iSize, NULL) ); - if (decodedSize != testSize) goto _output_error; - if (iSize != cSize) goto _output_error; - { U64 const crcDest = XXH64(decodedBuffer, decodedSize, 1); - U64 const crcSrc = XXH64(CNBuffer, testSize, 1); - if (crcDest != crcSrc) goto _output_error; - } - DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize); - - CHECK( LZ4F_freeDecompressionContext(dctx) ); - } - - /* frame content size tests */ - { size_t cErr; - BYTE* const ostart = (BYTE*)compressedBuffer; - BYTE* op = ostart; - CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) ); - - DISPLAYLEVEL(3, "compress without frameSize : "); - memset(&(prefs.frameInfo), 0, sizeof(prefs.frameInfo)); - CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs)); - op += cErr; - CHECK_V(cErr, LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL)); - op += cErr; - CHECK( LZ4F_compressEnd(cctx, compressedBuffer, testSize, NULL) ); - DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)(op-ostart)); - - DISPLAYLEVEL(3, "compress with frameSize : "); - prefs.frameInfo.contentSize = testSize; - op = ostart; - CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs)); - op += cErr; - CHECK_V(cErr, LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL)); - op += cErr; - CHECK( LZ4F_compressEnd(cctx, compressedBuffer, testSize, NULL) ); - DISPLAYLEVEL(3, "Compressed %i bytes into a %i bytes frame \n", (int)testSize, (int)(op-ostart)); - - DISPLAYLEVEL(3, "compress with wrong frameSize : "); - prefs.frameInfo.contentSize = testSize+1; - op = ostart; - CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs)); - op += cErr; - CHECK_V(cErr, LZ4F_compressUpdate(cctx, op, LZ4F_compressBound(testSize, &prefs), CNBuffer, testSize, NULL)); - op += cErr; - cErr = LZ4F_compressEnd(cctx, op, testSize, NULL); - if (!LZ4F_isError(cErr)) goto _output_error; - DISPLAYLEVEL(3, "Error correctly detected : %s \n", LZ4F_getErrorName(cErr)); - - CHECK( LZ4F_freeCompressionContext(cctx) ); - cctx = NULL; - } - - /* dictID tests */ - { size_t cErr; - U32 const dictID = 0x99; - CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) ); - - DISPLAYLEVEL(3, "insert a dictID : "); - memset(&prefs.frameInfo, 0, sizeof(prefs.frameInfo)); - prefs.frameInfo.dictID = dictID; - CHECK_V(cErr, LZ4F_compressBegin(cctx, compressedBuffer, testSize, &prefs)); - DISPLAYLEVEL(3, "created frame header of size %i bytes \n", (int)cErr); - - DISPLAYLEVEL(3, "read a dictID : "); - CHECK( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) ); - memset(&prefs.frameInfo, 0, sizeof(prefs.frameInfo)); - CHECK( LZ4F_getFrameInfo(dCtx, &prefs.frameInfo, compressedBuffer, &cErr) ); - if (prefs.frameInfo.dictID != dictID) goto _output_error; - DISPLAYLEVEL(3, "%u \n", (U32)prefs.frameInfo.dictID); - - CHECK( LZ4F_freeDecompressionContext(dCtx) ); dCtx = NULL; - CHECK( LZ4F_freeCompressionContext(cctx) ); cctx = NULL; - } - - /* Dictionary compression test */ - { size_t const dictSize = 63 KB; - size_t const dstCapacity = LZ4F_compressFrameBound(dictSize, NULL); - size_t cSizeNoDict, cSizeWithDict; - LZ4F_CDict* const cdict = LZ4F_createCDict(CNBuffer, dictSize); - if (cdict == NULL) goto _output_error; - CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) ); - - DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with NULL dict : "); - CHECK_V(cSizeNoDict, - LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity, - CNBuffer, dictSize, - NULL, NULL) ); - DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeNoDict); - - CHECK( LZ4F_freeCompressionContext(cctx) ); - CHECK( LZ4F_createCompressionContext(&cctx, LZ4F_VERSION) ); - DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with dict : "); - CHECK_V(cSizeWithDict, - LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity, - CNBuffer, dictSize, - cdict, NULL) ); - DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n", - (unsigned)dictSize, (unsigned)cSizeWithDict); - if ((LZ4_DISTANCE_MAX > dictSize) && (cSizeWithDict >= cSizeNoDict)) goto _output_error; /* must be more efficient */ - crcOrig = XXH64(CNBuffer, dictSize, 0); - - DISPLAYLEVEL(3, "LZ4F_decompress_usingDict : "); - { LZ4F_dctx* dctx; - size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH; - size_t compressedSize = cSizeWithDict; - CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) ); - CHECK( LZ4F_decompress_usingDict(dctx, - decodedBuffer, &decodedSize, - compressedBuffer, &compressedSize, - CNBuffer, dictSize, - NULL) ); - if (compressedSize != cSizeWithDict) goto _output_error; - if (decodedSize != dictSize) goto _output_error; - { U64 const crcDest = XXH64(decodedBuffer, decodedSize, 0); - if (crcDest != crcOrig) goto _output_error; } - DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize); - CHECK( LZ4F_freeDecompressionContext(dctx) ); - } - - DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with dict, negative level : "); - { size_t cSizeLevelMax; - LZ4F_preferences_t cParams; - memset(&cParams, 0, sizeof(cParams)); - cParams.compressionLevel = -3; - CHECK_V(cSizeLevelMax, - LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity, - CNBuffer, dictSize, - cdict, &cParams) ); - DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeLevelMax); - } - - DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, with dict, level max : "); - { size_t cSizeLevelMax; - LZ4F_preferences_t cParams; - memset(&cParams, 0, sizeof(cParams)); - cParams.compressionLevel = LZ4F_compressionLevel_max(); - CHECK_V(cSizeLevelMax, - LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, dstCapacity, - CNBuffer, dictSize, - cdict, &cParams) ); - DISPLAYLEVEL(3, "%u bytes \n", (unsigned)cSizeLevelMax); - } - - DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, multiple linked blocks : "); - { size_t cSizeContiguous; - size_t const inSize = dictSize * 3; - size_t const outCapacity = LZ4F_compressFrameBound(inSize, NULL); - LZ4F_preferences_t cParams; - memset(&cParams, 0, sizeof(cParams)); - cParams.frameInfo.blockMode = LZ4F_blockLinked; - cParams.frameInfo.blockSizeID = LZ4F_max64KB; - CHECK_V(cSizeContiguous, - LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, outCapacity, - CNBuffer, inSize, - cdict, &cParams) ); - DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n", - (unsigned)inSize, (unsigned)cSizeContiguous); - - DISPLAYLEVEL(3, "LZ4F_decompress_usingDict on multiple linked blocks : "); - { LZ4F_dctx* dctx; - size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH; - size_t compressedSize = cSizeContiguous; - CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) ); - CHECK( LZ4F_decompress_usingDict(dctx, - decodedBuffer, &decodedSize, - compressedBuffer, &compressedSize, - CNBuffer, dictSize, - NULL) ); - if (compressedSize != cSizeContiguous) goto _output_error; - if (decodedSize != inSize) goto _output_error; - crcOrig = XXH64(CNBuffer, inSize, 0); - { U64 const crcDest = XXH64(decodedBuffer, decodedSize, 0); - if (crcDest != crcOrig) goto _output_error; } - DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize); - CHECK( LZ4F_freeDecompressionContext(dctx) ); - } - } - - - DISPLAYLEVEL(3, "LZ4F_compressFrame_usingCDict, multiple independent blocks : "); - { size_t cSizeIndep; - size_t const inSize = dictSize * 3; - size_t const outCapacity = LZ4F_compressFrameBound(inSize, NULL); - LZ4F_preferences_t cParams; - memset(&cParams, 0, sizeof(cParams)); - cParams.frameInfo.blockMode = LZ4F_blockIndependent; - cParams.frameInfo.blockSizeID = LZ4F_max64KB; - CHECK_V(cSizeIndep, - LZ4F_compressFrame_usingCDict(cctx, compressedBuffer, outCapacity, - CNBuffer, inSize, - cdict, &cParams) ); - DISPLAYLEVEL(3, "compressed %u bytes into %u bytes \n", - (unsigned)inSize, (unsigned)cSizeIndep); - - DISPLAYLEVEL(3, "LZ4F_decompress_usingDict on multiple independent blocks : "); - { LZ4F_dctx* dctx; - size_t decodedSize = COMPRESSIBLE_NOISE_LENGTH; - size_t compressedSize = cSizeIndep; - CHECK( LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION) ); - CHECK( LZ4F_decompress_usingDict(dctx, - decodedBuffer, &decodedSize, - compressedBuffer, &compressedSize, - CNBuffer, dictSize, - NULL) ); - if (compressedSize != cSizeIndep) goto _output_error; - if (decodedSize != inSize) goto _output_error; - crcOrig = XXH64(CNBuffer, inSize, 0); - { U64 const crcDest = XXH64(decodedBuffer, decodedSize, 0); - if (crcDest != crcOrig) goto _output_error; } - DISPLAYLEVEL(3, "Regenerated %u bytes \n", (U32)decodedSize); - CHECK( LZ4F_freeDecompressionContext(dctx) ); - } - } - - LZ4F_freeCDict(cdict); - CHECK( LZ4F_freeCompressionContext(cctx) ); cctx = NULL; - } - - DISPLAYLEVEL(3, "getBlockSize test: \n"); - { size_t result; - unsigned blockSizeID; - for (blockSizeID = 4; blockSizeID < 8; ++blockSizeID) { - result = LZ4F_getBlockSize(blockSizeID); - CHECK(result); - DISPLAYLEVEL(3, "Returned block size of %u bytes for blockID %u \n", - (unsigned)result, blockSizeID); - } - - /* Test an invalid input that's too large */ - result = LZ4F_getBlockSize(8); - if(!LZ4F_isError(result) || - LZ4F_getErrorCode(result) != LZ4F_ERROR_maxBlockSize_invalid) - goto _output_error; - - /* Test an invalid input that's too small */ - result = LZ4F_getBlockSize(3); - if(!LZ4F_isError(result) || - LZ4F_getErrorCode(result) != LZ4F_ERROR_maxBlockSize_invalid) - goto _output_error; - } - - - DISPLAYLEVEL(3, "Skippable frame test : \n"); - { size_t decodedBufferSize = COMPRESSIBLE_NOISE_LENGTH; - unsigned maxBits = FUZ_highbit((U32)decodedBufferSize); - BYTE* op = (BYTE*)decodedBuffer; - BYTE* const oend = (BYTE*)decodedBuffer + COMPRESSIBLE_NOISE_LENGTH; - BYTE* ip = (BYTE*)compressedBuffer; - BYTE* iend = (BYTE*)compressedBuffer + cSize + 8; - - CHECK( LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION) ); - - /* generate skippable frame */ - FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START); - FUZ_writeLE32(ip+4, (U32)cSize); - - DISPLAYLEVEL(3, "random segment sizes : \n"); - while (ip < iend) { - unsigned nbBits = FUZ_rand(&randState) % maxBits; - size_t iSize = (FUZ_rand(&randState) & ((1< (size_t)(iend-ip)) iSize = (size_t)(iend-ip); - CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) ); - op += oSize; - ip += iSize; - } - DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)decodedBufferSize); - - /* generate zero-size skippable frame */ - DISPLAYLEVEL(3, "zero-size skippable frame\n"); - ip = (BYTE*)compressedBuffer; - op = (BYTE*)decodedBuffer; - FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START+1); - FUZ_writeLE32(ip+4, 0); - iend = ip+8; - - while (ip < iend) { - unsigned const nbBits = FUZ_rand(&randState) % maxBits; - size_t iSize = (FUZ_rand(&randState) & ((1< (size_t)(iend-ip)) iSize = (size_t)(iend-ip); - CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) ); - op += oSize; - ip += iSize; - } - DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)(ip - (BYTE*)compressedBuffer - 8)); - - DISPLAYLEVEL(3, "Skippable frame header complete in first call \n"); - ip = (BYTE*)compressedBuffer; - op = (BYTE*)decodedBuffer; - FUZ_writeLE32(ip, LZ4F_MAGIC_SKIPPABLE_START+2); - FUZ_writeLE32(ip+4, 10); - iend = ip+18; - while (ip < iend) { - size_t iSize = 10; - size_t oSize = 10; - if (iSize > (size_t)(iend-ip)) iSize = (size_t)(iend-ip); - CHECK( LZ4F_decompress(dCtx, op, &oSize, ip, &iSize, NULL) ); - op += oSize; - ip += iSize; - } - DISPLAYLEVEL(3, "Skipped %i bytes \n", (int)(ip - (BYTE*)compressedBuffer - 8)); - } - - DISPLAY("Basic tests completed \n"); -_end: - free(CNBuffer); - free(compressedBuffer); - free(decodedBuffer); - LZ4F_freeDecompressionContext(dCtx); dCtx = NULL; - LZ4F_freeCompressionContext(cctx); cctx = NULL; - return basicTests_error; - -_output_error: - basicTests_error = 1; - DISPLAY("Error detected ! \n"); - goto _end; -} - - -typedef enum { o_contiguous, o_noncontiguous, o_overwrite } o_scenario_e; - -static void locateBuffDiff(const void* buff1, const void* buff2, size_t size, o_scenario_e o_scenario) -{ - if (displayLevel >= 2) { - size_t p=0; - const BYTE* b1=(const BYTE*)buff1; - const BYTE* b2=(const BYTE*)buff2; - DISPLAY("locateBuffDiff: looking for error position \n"); - if (o_scenario != o_contiguous) { - DISPLAY("mode %i: non-contiguous output (%u bytes), cannot search \n", - (int)o_scenario, (unsigned)size); - return; - } - while (p < size && b1[p]==b2[p]) p++; - if (p != size) { - DISPLAY("Error at pos %i/%i : %02X != %02X \n", (int)p, (int)size, b1[p], b2[p]); - } - } -} - -# define EXIT_MSG(...) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \ - DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); exit(1); } -# undef CHECK -# define CHECK(cond, ...) { if (cond) { EXIT_MSG(__VA_ARGS__); } } - - -size_t test_lz4f_decompression_wBuffers( - const void* cSrc, size_t cSize, - void* dst, size_t dstCapacity, o_scenario_e o_scenario, - const void* srcRef, size_t decompressedSize, - U64 crcOrig, - U32* const randState, - LZ4F_dctx* const dCtx, - U32 seed, U32 testNb, - int findErrorPos) -{ - const BYTE* ip = (const BYTE*)cSrc; - const BYTE* const iend = ip + cSize; - - BYTE* op = (BYTE*)dst; - BYTE* const oend = op + dstCapacity; - - unsigned const suggestedBits = FUZ_highbit((U32)cSize); - unsigned const maxBits = MAX(3, suggestedBits); - size_t totalOut = 0; - size_t moreToFlush = 0; - XXH64_state_t xxh64; - XXH64_reset(&xxh64, 1); - assert(ip < iend); - while (ip < iend) { - unsigned const nbBitsI = (FUZ_rand(randState) % (maxBits-1)) + 1; - unsigned const nbBitsO = (FUZ_rand(randState) % (maxBits)) + 1; - size_t const iSizeCand = (FUZ_rand(randState) & ((1< 2x4MB to test large blocks */ - void* CNBuffer = NULL; - size_t const compressedBufferSize = LZ4F_compressFrameBound(CNBufferLength, NULL) + 4 MB; /* needs some margin */ - void* compressedBuffer = NULL; - void* decodedBuffer = NULL; - U32 coreRand = seed; - LZ4F_decompressionContext_t dCtx = NULL; - LZ4F_decompressionContext_t dCtxNoise = NULL; - LZ4F_compressionContext_t cCtx = NULL; - clock_t const startClock = clock(); - clock_t const clockDuration = duration_s * CLOCKS_PER_SEC; - - /* Create buffers */ - { size_t const creationStatus = LZ4F_createDecompressionContext(&dCtx, LZ4F_VERSION); - CHECK(LZ4F_isError(creationStatus), "Allocation failed (error %i)", (int)creationStatus); } - { size_t const creationStatus = LZ4F_createDecompressionContext(&dCtxNoise, LZ4F_VERSION); - CHECK(LZ4F_isError(creationStatus), "Allocation failed (error %i)", (int)creationStatus); } - { size_t const creationStatus = LZ4F_createCompressionContext(&cCtx, LZ4F_VERSION); - CHECK(LZ4F_isError(creationStatus), "Allocation failed (error %i)", (int)creationStatus); } - CNBuffer = malloc(CNBufferLength); - CHECK(CNBuffer==NULL, "CNBuffer Allocation failed"); - compressedBuffer = malloc(compressedBufferSize); - CHECK(compressedBuffer==NULL, "compressedBuffer Allocation failed"); - decodedBuffer = calloc(1, CNBufferLength); /* calloc avoids decodedBuffer being considered "garbage" by scan-build */ - CHECK(decodedBuffer==NULL, "decodedBuffer Allocation failed"); - FUZ_fillCompressibleNoiseBuffer(CNBuffer, CNBufferLength, compressibility, &coreRand); - - /* jump to requested testNb */ - for (testNb =0; (testNb < startTest); testNb++) (void)FUZ_rand(&coreRand); /* sync randomizer */ - - /* main fuzzer test loop */ - for ( ; (testNb < nbTests) || (clockDuration > FUZ_GetClockSpan(startClock)) ; testNb++) { - U32 randState = coreRand ^ prime1; - unsigned const srcBits = (FUZ_rand(&randState) % (FUZ_highbit((U32)(CNBufferLength-1)) - 1)) + 1; - size_t const srcSize = (FUZ_rand(&randState) & ((1<frameInfo.blockChecksumFlag) { - U32 const bc32 = XXH32(op, 0, 0); - op[0] = (BYTE)bc32; /* little endian format */ - op[1] = (BYTE)(bc32>>8); - op[2] = (BYTE)(bc32>>16); - op[3] = (BYTE)(bc32>>24); - op += 4; - } } } } - } /* while (ip=oend, "LZ4F_compressFrameBound overflow"); - { size_t const dstEndSafeSize = LZ4F_compressBound(0, prefsPtr); - int const tooSmallDstEnd = ((FUZ_rand(&randState) & 31) == 3); - size_t const dstEndTooSmallSize = (FUZ_rand(&randState) % dstEndSafeSize) + 1; - size_t const dstEndSize = tooSmallDstEnd ? dstEndTooSmallSize : dstEndSafeSize; - BYTE const canaryByte = (BYTE)(FUZ_rand(&randState) & 255); - size_t flushedSize; - DISPLAYLEVEL(7,"canaryByte at pos %u / %u \n", - (unsigned)((size_t)(op - (BYTE*)compressedBuffer) + dstEndSize), - (unsigned)compressedBufferSize); - assert(op + dstEndSize < (BYTE*)compressedBuffer + compressedBufferSize); - op[dstEndSize] = canaryByte; - flushedSize = LZ4F_compressEnd(cCtx, op, dstEndSize, &cOptions); - CHECK(op[dstEndSize] != canaryByte, "LZ4F_compressEnd writes beyond dstCapacity !"); - if (LZ4F_isError(flushedSize)) { - if (tooSmallDstEnd) /* failure is allowed */ continue; - CHECK(!tooSmallDstEnd, "Compression completion failed (error %i : %s)", - (int)flushedSize, LZ4F_getErrorName(flushedSize)); - } - op += flushedSize; - } - cSize = (size_t)(op - (BYTE*)compressedBuffer); - DISPLAYLEVEL(5, "\nCompressed %u bytes into %u \n", (U32)srcSize, (U32)cSize); - } - - - /* multi-segments decompression */ - DISPLAYLEVEL(6, "normal decompression \n"); - { size_t result = test_lz4f_decompression(compressedBuffer, cSize, srcStart, srcSize, crcOrig, &randState, dCtx, seed, testNb, 1 /*findError*/ ); - CHECK (LZ4F_isError(result), "multi-segment decompression failed (error %i => %s)", - (int)result, LZ4F_getErrorName(result)); - } - -#if 1 - /* insert noise into src */ - { U32 const maxNbBits = FUZ_highbit((U32)cSize); - size_t pos = 0; - for (;;) { - /* keep some original src */ - { U32 const nbBits = FUZ_rand(&randState) % maxNbBits; - size_t const mask = (1<= cSize) break; - /* add noise */ - { U32 const nbBitsCodes = FUZ_rand(&randState) % maxNbBits; - U32 const nbBits = nbBitsCodes ? nbBitsCodes-1 : 0; - size_t const mask = (1<='0') && (*argument<='9')) { - nbTests *= 10; - nbTests += (unsigned)(*argument - '0'); - argument++; - } - break; - - case 'T': - argument++; - nbTests = 0; duration = 0; - for (;;) { - switch(*argument) - { - case 'm': duration *= 60; argument++; continue; - case 's': - case 'n': argument++; continue; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': duration *= 10; duration += (U32)(*argument++ - '0'); continue; - } - break; - } - break; - - case 's': - argument++; - seed=0; - seedset=1; - while ((*argument>='0') && (*argument<='9')) { - seed *= 10; - seed += (U32)(*argument - '0'); - argument++; - } - break; - case 't': - argument++; - testNb=0; - while ((*argument>='0') && (*argument<='9')) { - testNb *= 10; - testNb += (unsigned)(*argument - '0'); - argument++; - } - break; - case 'P': /* compressibility % */ - argument++; - proba=0; - while ((*argument>='0') && (*argument<='9')) { - proba *= 10; - proba += *argument - '0'; - argument++; - } - if (proba<0) proba=0; - if (proba>100) proba=100; - break; - default: - ; - return FUZ_usage(programName); - } - } - } - } - - /* Get Seed */ - DISPLAY("Starting lz4frame tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), LZ4_VERSION_STRING); - - if (!seedset) { - time_t const t = time(NULL); - U32 const h = XXH32(&t, sizeof(t), 1); - seed = h % 10000; - } - DISPLAY("Seed = %u\n", seed); - if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) DISPLAY("Compressibility : %i%%\n", proba); - - nbTests += (nbTests==0); /* avoid zero */ - - if (testNb==0) result = basicTests(seed, ((double)proba) / 100); - if (result) return 1; - return fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100, duration); -} diff --git a/ta6ob/lz4/tests/fullbench.c b/ta6ob/lz4/tests/fullbench.c deleted file mode 100644 index cb9b684..0000000 --- a/ta6ob/lz4/tests/fullbench.c +++ /dev/null @@ -1,869 +0,0 @@ -/* - bench.c - Demo program to benchmark open-source compression algorithm - Copyright (C) Yann Collet 2012-2016 - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 source repository : https://github.com/lz4/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ - - -#if defined(_MSC_VER) || defined(_WIN32) - /* S_ISREG & gettimeofday() are not supported by MSVC */ -# define BMK_LEGACY_TIMER 1 -#endif - - -/************************************** -* Includes -**************************************/ -#include "platform.h" /* _CRT_SECURE_NO_WARNINGS, Large Files support */ -#include "util.h" /* U32, UTIL_getFileSize */ -#include /* malloc, free */ -#include /* fprintf, fopen, ftello */ -#include /* stat64 */ -#include /* stat64 */ -#include /* strcmp */ -#include /* clock_t, clock(), CLOCKS_PER_SEC */ - -#define LZ4_DISABLE_DEPRECATE_WARNINGS /* LZ4_decompress_fast */ -#include "lz4.h" -#include "lz4hc.h" -#include "lz4frame.h" - -#include "xxhash.h" - - -/************************************** -* Constants -**************************************/ -#define PROGRAM_DESCRIPTION "LZ4 speed analyzer" -#define AUTHOR "Yann Collet" -#define WELCOME_MESSAGE "*** %s v%s %i-bits, by %s ***\n", PROGRAM_DESCRIPTION, LZ4_VERSION_STRING, (int)(sizeof(void*)*8), AUTHOR - -#define NBLOOPS 6 -#define TIMELOOP (CLOCKS_PER_SEC * 25 / 10) - -#define KB *(1 <<10) -#define MB *(1 <<20) -#define GB *(1U<<30) - -#define KNUTH 2654435761U -#define MAX_MEM (1920 MB) -#define DEFAULT_CHUNKSIZE (4 MB) - -#define ALL_COMPRESSORS 0 -#define ALL_DECOMPRESSORS 0 - - -/************************************** -* Local structures -**************************************/ -struct chunkParameters -{ - U32 id; - char* origBuffer; - char* compressedBuffer; - int origSize; - int compressedSize; -}; - - -/************************************** -* Macros -**************************************/ -#define DISPLAY(...) fprintf(stderr, __VA_ARGS__) -#define PROGRESS(...) g_noPrompt ? 0 : DISPLAY(__VA_ARGS__) - - -/************************************** -* Benchmark Parameters -**************************************/ -static int g_chunkSize = DEFAULT_CHUNKSIZE; -static int g_nbIterations = NBLOOPS; -static int g_pause = 0; -static int g_compressionTest = 1; -static int g_compressionAlgo = ALL_COMPRESSORS; -static int g_decompressionTest = 1; -static int g_decompressionAlgo = ALL_DECOMPRESSORS; -static int g_noPrompt = 0; - -static void BMK_setBlocksize(int bsize) -{ - g_chunkSize = bsize; - DISPLAY("-Using Block Size of %i KB-\n", g_chunkSize>>10); -} - -static void BMK_setNbIterations(int nbLoops) -{ - g_nbIterations = nbLoops; - DISPLAY("- %i iterations -\n", g_nbIterations); -} - -static void BMK_setPause(void) -{ - g_pause = 1; -} - - -/********************************************************* -* Private functions -*********************************************************/ -static clock_t BMK_GetClockSpan( clock_t clockStart ) -{ - return clock() - clockStart; /* works even if overflow; max span ~30 mn */ -} - - -static size_t BMK_findMaxMem(U64 requiredMem) -{ - size_t step = 64 MB; - BYTE* testmem = NULL; - - requiredMem = (((requiredMem >> 26) + 1) << 26); - requiredMem += 2*step; - if (requiredMem > MAX_MEM) requiredMem = MAX_MEM; - - while (!testmem) { - if (requiredMem > step) requiredMem -= step; - else requiredMem >>= 1; - testmem = (BYTE*) malloc ((size_t)requiredMem); - } - free (testmem); - - /* keep some space available */ - if (requiredMem > step) requiredMem -= step; - else requiredMem >>= 1; - - return (size_t)requiredMem; -} - - -/********************************************************* -* Memory management, to test LZ4_USER_MEMORY_FUNCTIONS -*********************************************************/ -void* LZ4_malloc(size_t s) { return malloc(s); } -void* LZ4_calloc(size_t n, size_t s) { return calloc(n,s); } -void LZ4_free(void* p) { free(p); } - - -/********************************************************* -* Benchmark function -*********************************************************/ -static LZ4_stream_t LZ4_stream; -static void local_LZ4_resetDictT(void) -{ - void* const r = LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); - assert(r != NULL); (void)r; -} - -static void local_LZ4_createStream(void) -{ - void* const r = LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); - assert(r != NULL); (void)r; -} - -static int local_LZ4_saveDict(const char* in, char* out, int inSize) -{ - (void)in; - return LZ4_saveDict(&LZ4_stream, out, inSize); -} - -static int local_LZ4_compress_default_large(const char* in, char* out, int inSize) -{ - return LZ4_compress_default(in, out, inSize, LZ4_compressBound(inSize)); -} - -static int local_LZ4_compress_default_small(const char* in, char* out, int inSize) -{ - return LZ4_compress_default(in, out, inSize, LZ4_compressBound(inSize)-1); -} - -static int local_LZ4_compress_destSize(const char* in, char* out, int inSize) -{ - return LZ4_compress_destSize(in, out, &inSize, LZ4_compressBound(inSize)-1); -} - -static int local_LZ4_compress_fast0(const char* in, char* out, int inSize) -{ - return LZ4_compress_fast(in, out, inSize, LZ4_compressBound(inSize), 0); -} - -static int local_LZ4_compress_fast1(const char* in, char* out, int inSize) -{ - return LZ4_compress_fast(in, out, inSize, LZ4_compressBound(inSize), 1); -} - -static int local_LZ4_compress_fast2(const char* in, char* out, int inSize) -{ - return LZ4_compress_fast(in, out, inSize, LZ4_compressBound(inSize), 2); -} - -static int local_LZ4_compress_fast17(const char* in, char* out, int inSize) -{ - return LZ4_compress_fast(in, out, inSize, LZ4_compressBound(inSize), 17); -} - -static int local_LZ4_compress_fast_extState0(const char* in, char* out, int inSize) -{ - return LZ4_compress_fast_extState(&LZ4_stream, in, out, inSize, LZ4_compressBound(inSize), 0); -} - -static int local_LZ4_compress_fast_continue0(const char* in, char* out, int inSize) -{ - return LZ4_compress_fast_continue(&LZ4_stream, in, out, inSize, LZ4_compressBound(inSize), 0); -} - -#ifndef LZ4_DLL_IMPORT -#if defined (__cplusplus) -extern "C" { -#endif - -/* declare hidden function */ -extern int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize); - -#if defined (__cplusplus) -} -#endif - -static int local_LZ4_compress_forceDict(const char* in, char* out, int inSize) -{ - return LZ4_compress_forceExtDict(&LZ4_stream, in, out, inSize); -} -#endif - - -/* HC compression functions */ -LZ4_streamHC_t LZ4_streamHC; -static void local_LZ4_resetStreamHC(void) -{ - LZ4_initStreamHC(&LZ4_streamHC, sizeof(LZ4_streamHC)); -} - -static int local_LZ4_saveDictHC(const char* in, char* out, int inSize) -{ - (void)in; - return LZ4_saveDictHC(&LZ4_streamHC, out, inSize); -} - -static int local_LZ4_compress_HC(const char* in, char* out, int inSize) -{ - return LZ4_compress_HC(in, out, inSize, LZ4_compressBound(inSize), 9); -} - -static int local_LZ4_compress_HC_extStateHC(const char* in, char* out, int inSize) -{ - return LZ4_compress_HC_extStateHC(&LZ4_streamHC, in, out, inSize, LZ4_compressBound(inSize), 9); -} - -static int local_LZ4_compress_HC_continue(const char* in, char* out, int inSize) -{ - return LZ4_compress_HC_continue(&LZ4_streamHC, in, out, inSize, LZ4_compressBound(inSize)); -} - - -/* decompression functions */ -static int local_LZ4_decompress_fast(const char* in, char* out, int inSize, int outSize) -{ - (void)inSize; - LZ4_decompress_fast(in, out, outSize); - return outSize; -} - -static int local_LZ4_decompress_fast_usingDict_prefix(const char* in, char* out, int inSize, int outSize) -{ - (void)inSize; - LZ4_decompress_fast_usingDict(in, out, outSize, out - 65536, 65536); - return outSize; -} - -static int local_LZ4_decompress_fast_usingExtDict(const char* in, char* out, int inSize, int outSize) -{ - (void)inSize; - LZ4_decompress_fast_usingDict(in, out, outSize, out - 65536, 65535); - return outSize; -} - -static int local_LZ4_decompress_safe_withPrefix64k(const char* in, char* out, int inSize, int outSize) -{ - LZ4_decompress_safe_withPrefix64k(in, out, inSize, outSize); - return outSize; -} - -static int local_LZ4_decompress_safe_usingDict(const char* in, char* out, int inSize, int outSize) -{ - LZ4_decompress_safe_usingDict(in, out, inSize, outSize, out - 65536, 65536); - return outSize; -} - -#ifndef LZ4_DLL_IMPORT -#if defined (__cplusplus) -extern "C" { -#endif - -extern int LZ4_decompress_safe_forceExtDict(const char* in, char* out, int inSize, int outSize, const void* dict, size_t dictSize); - -#if defined (__cplusplus) -} -#endif - -static int local_LZ4_decompress_safe_forceExtDict(const char* in, char* out, int inSize, int outSize) -{ - (void)inSize; - LZ4_decompress_safe_forceExtDict(in, out, inSize, outSize, out - 65536, 65536); - return outSize; -} -#endif - -static int local_LZ4_decompress_safe_partial(const char* in, char* out, int inSize, int outSize) -{ - int result = LZ4_decompress_safe_partial(in, out, inSize, outSize - 5, outSize); - if (result < 0) return result; - return outSize; -} - - -/* frame functions */ -static int local_LZ4F_compressFrame(const char* in, char* out, int inSize) -{ - assert(inSize >= 0); - return (int)LZ4F_compressFrame(out, LZ4F_compressFrameBound((size_t)inSize, NULL), in, (size_t)inSize, NULL); -} - -static LZ4F_decompressionContext_t g_dCtx; - -static int local_LZ4F_decompress(const char* in, char* out, int inSize, int outSize) -{ - size_t srcSize = (size_t)inSize; - size_t dstSize = (size_t)outSize; - size_t result; - assert(inSize >= 0); - assert(outSize >= 0); - result = LZ4F_decompress(g_dCtx, out, &dstSize, in, &srcSize, NULL); - if (result!=0) { DISPLAY("Error decompressing frame : unfinished frame \n"); exit(8); } - if (srcSize != (size_t)inSize) { DISPLAY("Error decompressing frame : read size incorrect \n"); exit(9); } - return (int)dstSize; -} - -static int local_LZ4F_decompress_followHint(const char* src, char* dst, int srcSize, int dstSize) -{ - size_t totalInSize = (size_t)srcSize; - size_t maxOutSize = (size_t)dstSize; - - size_t inPos = 0; - size_t inSize = 0; - size_t outPos = 0; - size_t outRemaining = maxOutSize - outPos; - - for (;;) { - size_t const sizeHint = LZ4F_decompress(g_dCtx, dst+outPos, &outRemaining, src+inPos, &inSize, NULL); - assert(!LZ4F_isError(sizeHint)); - - inPos += inSize; - inSize = sizeHint; - - outPos += outRemaining; - outRemaining = maxOutSize - outPos; - - if (!sizeHint) break; - } - - /* frame completed */ - if (inPos != totalInSize) { - DISPLAY("Error decompressing frame : must read (%u) full frame (%u) \n", - (unsigned)inPos, (unsigned)totalInSize); - exit(10); - } - return (int)outPos; - -} - -/* always provide input by block of 64 KB */ -static int local_LZ4F_decompress_noHint(const char* src, char* dst, int srcSize, int dstSize) -{ - size_t totalInSize = (size_t)srcSize; - size_t maxOutSize = (size_t)dstSize; - - size_t inPos = 0; - size_t inSize = 64 KB; - size_t outPos = 0; - size_t outRemaining = maxOutSize - outPos; - - for (;;) { - size_t const sizeHint = LZ4F_decompress(g_dCtx, dst+outPos, &outRemaining, src+inPos, &inSize, NULL); - assert(!LZ4F_isError(sizeHint)); - - inPos += inSize; - inSize = (inPos + 64 KB <= totalInSize) ? 64 KB : totalInSize - inPos; - - outPos += outRemaining; - outRemaining = maxOutSize - outPos; - - if (!sizeHint) break; - } - - /* frame completed */ - if (inPos != totalInSize) { - DISPLAY("Error decompressing frame : must read (%u) full frame (%u) \n", - (unsigned)inPos, (unsigned)totalInSize); - exit(10); - } - return (int)outPos; - -} - -#define NB_COMPRESSION_ALGORITHMS 100 -#define NB_DECOMPRESSION_ALGORITHMS 100 -int fullSpeedBench(const char** fileNamesTable, int nbFiles) -{ - int fileIdx=0; - - /* Init */ - { size_t const errorCode = LZ4F_createDecompressionContext(&g_dCtx, LZ4F_VERSION); - if (LZ4F_isError(errorCode)) { DISPLAY("dctx allocation issue \n"); return 10; } } - - /* Loop for each fileName */ - while (fileIdx inFileSize) benchedSize = (size_t)inFileSize; - if (benchedSize < inFileSize) { - DISPLAY("Not enough memory for '%s' full size; testing %i MB only... \n", - inFileName, (int)(benchedSize>>20)); - } - - /* Allocation */ - chunkP = (struct chunkParameters*) malloc(((benchedSize / (size_t)g_chunkSize)+1) * sizeof(struct chunkParameters)); - orig_buff = (char*) malloc(benchedSize); - nbChunks = (int) ((benchedSize + (size_t)g_chunkSize - 1) / (size_t)g_chunkSize); - maxCompressedChunkSize = LZ4_compressBound(g_chunkSize); - compressedBuffSize = nbChunks * maxCompressedChunkSize; - compressed_buff = (char*)malloc((size_t)compressedBuffSize); - if(!chunkP || !orig_buff || !compressed_buff) { - DISPLAY("\nError: not enough memory! \n"); - fclose(inFile); - free(orig_buff); - free(compressed_buff); - free(chunkP); - return(12); - } - - /* Fill in src buffer */ - DISPLAY("Loading %s... \r", inFileName); - readSize = fread(orig_buff, 1, benchedSize, inFile); - fclose(inFile); - - if (readSize != benchedSize) { - DISPLAY("\nError: problem reading file '%s' !! \n", inFileName); - free(orig_buff); - free(compressed_buff); - free(chunkP); - return 13; - } - - /* Calculating input Checksum */ - crcOriginal = XXH32(orig_buff, benchedSize,0); - - - /* Bench */ - { int loopNb, nb_loops, chunkNb, cAlgNb, dAlgNb; - size_t cSize=0; - double ratio=0.; - - DISPLAY("\r%79s\r", ""); - DISPLAY(" %s : \n", inFileName); - - /* Bench Compression Algorithms */ - for (cAlgNb=0; (cAlgNb <= NB_COMPRESSION_ALGORITHMS) && (g_compressionTest); cAlgNb++) { - const char* compressorName; - int (*compressionFunction)(const char*, char*, int); - void (*initFunction)(void) = NULL; - double bestTime = 100000000.; - - /* filter compressionAlgo only */ - if ((g_compressionAlgo != ALL_COMPRESSORS) && (g_compressionAlgo != cAlgNb)) continue; - - /* Init data chunks */ - { int i; - size_t remaining = benchedSize; - char* in = orig_buff; - char* out = compressed_buff; - assert(nbChunks >= 1); - for (i=0; i 0); - if (remaining > (size_t)g_chunkSize) { - chunkP[i].origSize = g_chunkSize; - remaining -= (size_t)g_chunkSize; - } else { - chunkP[i].origSize = (int)remaining; - remaining = 0; - } - chunkP[i].compressedBuffer = out; out += maxCompressedChunkSize; - chunkP[i].compressedSize = 0; - } - } - - switch(cAlgNb) - { - case 0 : DISPLAY("Compression functions : \n"); continue; - case 1 : compressionFunction = local_LZ4_compress_default_large; compressorName = "LZ4_compress_default"; break; - case 2 : compressionFunction = local_LZ4_compress_default_small; compressorName = "LZ4_compress_default(small dst)"; break; - case 3 : compressionFunction = local_LZ4_compress_destSize; compressorName = "LZ4_compress_destSize"; break; - case 4 : compressionFunction = local_LZ4_compress_fast0; compressorName = "LZ4_compress_fast(0)"; break; - case 5 : compressionFunction = local_LZ4_compress_fast1; compressorName = "LZ4_compress_fast(1)"; break; - case 6 : compressionFunction = local_LZ4_compress_fast2; compressorName = "LZ4_compress_fast(2)"; break; - case 7 : compressionFunction = local_LZ4_compress_fast17; compressorName = "LZ4_compress_fast(17)"; break; - case 8 : compressionFunction = local_LZ4_compress_fast_extState0; compressorName = "LZ4_compress_fast_extState(0)"; break; - case 9 : compressionFunction = local_LZ4_compress_fast_continue0; initFunction = local_LZ4_createStream; compressorName = "LZ4_compress_fast_continue(0)"; break; - - case 10: compressionFunction = local_LZ4_compress_HC; compressorName = "LZ4_compress_HC"; break; - case 12: compressionFunction = local_LZ4_compress_HC_extStateHC; compressorName = "LZ4_compress_HC_extStateHC"; break; - case 14: compressionFunction = local_LZ4_compress_HC_continue; initFunction = local_LZ4_resetStreamHC; compressorName = "LZ4_compress_HC_continue"; break; -#ifndef LZ4_DLL_IMPORT - case 20: compressionFunction = local_LZ4_compress_forceDict; initFunction = local_LZ4_resetDictT; compressorName = "LZ4_compress_forceDict"; break; -#endif - case 30: compressionFunction = local_LZ4F_compressFrame; compressorName = "LZ4F_compressFrame"; - chunkP[0].origSize = (int)benchedSize; nbChunks=1; - break; - case 40: compressionFunction = local_LZ4_saveDict; compressorName = "LZ4_saveDict"; - if (chunkP[0].origSize < 8) { DISPLAY(" cannot bench %s with less then 8 bytes \n", compressorName); continue; } - LZ4_loadDict(&LZ4_stream, chunkP[0].origBuffer, chunkP[0].origSize); - break; - case 41: compressionFunction = local_LZ4_saveDictHC; compressorName = "LZ4_saveDictHC"; - if (chunkP[0].origSize < 8) { DISPLAY(" cannot bench %s with less then 8 bytes \n", compressorName); continue; } - LZ4_loadDictHC(&LZ4_streamHC, chunkP[0].origBuffer, chunkP[0].origSize); - break; - default : - continue; /* unknown ID : just skip */ - } - - for (loopNb = 1; loopNb <= g_nbIterations; loopNb++) { - double averageTime; - clock_t clockTime; - - PROGRESS("%2i-%-34.34s :%10i ->\r", loopNb, compressorName, (int)benchedSize); - { size_t i; for (i=0; i%9i (%5.2f%%),%7.1f MB/s\r", loopNb, compressorName, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / bestTime / 1000000); - } - - if (ratio<100.) - DISPLAY("%2i-%-34.34s :%10i ->%9i (%5.2f%%),%7.1f MB/s\n", cAlgNb, compressorName, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / bestTime / 1000000); - else - DISPLAY("%2i-%-34.34s :%10i ->%9i (%5.1f%%),%7.1f MB/s\n", cAlgNb, compressorName, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / bestTime / 100000); - } - - /* Prepare layout for decompression */ - /* Init data chunks */ - { int i; - size_t remaining = benchedSize; - char* in = orig_buff; - char* out = compressed_buff; - - nbChunks = (int) (((int)benchedSize + (g_chunkSize-1))/ g_chunkSize); - for (i=0; i g_chunkSize) { - chunkP[i].origSize = g_chunkSize; - remaining -= (size_t)g_chunkSize; - } else { - chunkP[i].origSize = (int)remaining; - remaining = 0; - } - chunkP[i].compressedBuffer = out; out += maxCompressedChunkSize; - chunkP[i].compressedSize = 0; - } - } - for (chunkNb=0; chunkNb\r", loopNb, dName, (int)benchedSize); - - nb_loops = 0; - clockTime = clock(); - while(clock() == clockTime); - clockTime = clock(); - while(BMK_GetClockSpan(clockTime) < TIMELOOP) { - for (chunkNb=0; chunkNb %7.1f MB/s\r", loopNb, dName, (int)benchedSize, (double)benchedSize / bestTime / 1000000); - - /* CRC Checking */ - crcDecoded = XXH32(orig_buff, benchedSize, 0); - if (checkResult && (crcOriginal!=crcDecoded)) { - DISPLAY("\n!!! WARNING !!! %14s : Invalid Checksum : %x != %x\n", - inFileName, (unsigned)crcOriginal, (unsigned)crcDecoded); - exit(1); - } } - - DISPLAY("%2i-%-34.34s :%10i -> %7.1f MB/s\n", dAlgNb, dName, (int)benchedSize, (double)benchedSize / bestTime / 1000000); - } - } - free(orig_buff); - free(compressed_buff); - free(chunkP); - } - - LZ4F_freeDecompressionContext(g_dCtx); - if (g_pause) { printf("press enter...\n"); (void)getchar(); } - - return 0; -} - - -static int usage(const char* exename) -{ - DISPLAY( "Usage :\n"); - DISPLAY( " %s [arg] file1 file2 ... fileX\n", exename); - DISPLAY( "Arguments :\n"); - DISPLAY( " -c : compression tests only\n"); - DISPLAY( " -d : decompression tests only\n"); - DISPLAY( " -H/-h : Help (this text + advanced options)\n"); - return 0; -} - -static int usage_advanced(void) -{ - DISPLAY( "\nAdvanced options :\n"); - DISPLAY( " -c# : test only compression function # [1-%i]\n", NB_COMPRESSION_ALGORITHMS); - DISPLAY( " -d# : test only decompression function # [1-%i]\n", NB_DECOMPRESSION_ALGORITHMS); - DISPLAY( " -i# : iteration loops [1-9](default : %i)\n", NBLOOPS); - DISPLAY( " -B# : Block size [4-7](default : 7)\n"); - return 0; -} - -static int badusage(const char* exename) -{ - DISPLAY("Wrong parameters\n"); - usage(exename); - return 0; -} - -int main(int argc, const char** argv) -{ - int i, - filenamesStart=2; - const char* exename = argv[0]; - const char* input_filename=0; - - // Welcome message - DISPLAY(WELCOME_MESSAGE); - - if (argc<2) { badusage(exename); return 1; } - - for(i=1; i= '0') && (argument[1]<= '9')) { - g_compressionAlgo *= 10; - g_compressionAlgo += argument[1] - '0'; - argument++; - } - break; - - // Select decompression algorithm only - case 'd': - g_compressionTest = 0; - while ((argument[1]>= '0') && (argument[1]<= '9')) { - g_decompressionAlgo *= 10; - g_decompressionAlgo += argument[1] - '0'; - argument++; - } - break; - - // Display help on usage - case 'h' : - case 'H': usage(exename); usage_advanced(); return 0; - - // Modify Block Properties - case 'B': - while (argument[1]!=0) - switch(argument[1]) - { - case '4': - case '5': - case '6': - case '7': - { int B = argument[1] - '0'; - int S = 1 << (8 + 2*B); - BMK_setBlocksize(S); - argument++; - break; - } - case 'D': argument++; break; - default : goto _exit_blockProperties; - } -_exit_blockProperties: - break; - - // Modify Nb Iterations - case 'i': - if ((argument[1] >='0') && (argument[1] <='9')) { - int iters = argument[1] - '0'; - BMK_setNbIterations(iters); - argument++; - } - break; - - // Pause at the end (hidden option) - case 'p': BMK_setPause(); break; - - // Unknown command - default : badusage(exename); return 1; - } - } - continue; - } - - // first provided filename is input - if (!input_filename) { input_filename=argument; filenamesStart=i; continue; } - - } - - // No input filename ==> Error - if(!input_filename) { badusage(exename); return 1; } - - return fullSpeedBench(argv+filenamesStart, argc-filenamesStart); - -} diff --git a/ta6ob/lz4/tests/fuzzer.c b/ta6ob/lz4/tests/fuzzer.c deleted file mode 100644 index a824813..0000000 --- a/ta6ob/lz4/tests/fuzzer.c +++ /dev/null @@ -1,1841 +0,0 @@ -/* - fuzzer.c - Fuzzer test tool for LZ4 - Copyright (C) Yann Collet 2012-2017 - - GPL v2 License - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - You can contact the author at : - - LZ4 homepage : http://www.lz4.org - - LZ4 source repo : https://github.com/lz4/lz4 -*/ - -/*-************************************ -* Compiler options -**************************************/ -#ifdef _MSC_VER /* Visual Studio */ -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -# pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */ -# pragma warning(disable : 4310) /* disable: C4310: constant char value > 127 */ -#endif - - -/*-************************************ -* Dependencies -**************************************/ -#if defined(__unix__) && !defined(_AIX) /* must be included before platform.h for MAP_ANONYMOUS */ -# undef _GNU_SOURCE /* in case it's already defined */ -# define _GNU_SOURCE /* MAP_ANONYMOUS even in -std=c99 mode */ -# include /* mmap */ -#endif -#include "platform.h" /* _CRT_SECURE_NO_WARNINGS */ -#include "util.h" /* U32 */ -#include -#include /* fgets, sscanf */ -#include /* strcmp */ -#include /* clock_t, clock, CLOCKS_PER_SEC */ -#include -#include /* INT_MAX */ - -#if defined(_AIX) -# include /* mmap */ -#endif - -#define LZ4_DISABLE_DEPRECATE_WARNINGS /* LZ4_decompress_fast */ -#define LZ4_STATIC_LINKING_ONLY -#include "lz4.h" -#define LZ4_HC_STATIC_LINKING_ONLY -#include "lz4hc.h" -#define XXH_STATIC_LINKING_ONLY -#include "xxhash.h" - - -/*-************************************ -* Basic Types -**************************************/ -#if !defined(__cplusplus) && !(defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -typedef size_t uintptr_t; /* true on most systems, except OpenVMS-64 (which doesn't need address overflow test) */ -#endif - - -/*-************************************ -* Constants -**************************************/ -#define NB_ATTEMPTS (1<<16) -#define COMPRESSIBLE_NOISE_LENGTH (1 << 21) -#define FUZ_MAX_BLOCK_SIZE (1 << 17) -#define FUZ_MAX_DICT_SIZE (1 << 15) -#define FUZ_COMPRESSIBILITY_DEFAULT 60 -#define PRIME1 2654435761U -#define PRIME2 2246822519U -#define PRIME3 3266489917U - -#define KB *(1U<<10) -#define MB *(1U<<20) -#define GB *(1U<<30) - - -/*-*************************************** -* Macros -*****************************************/ -#define DISPLAY(...) fprintf(stdout, __VA_ARGS__) -#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); } -static int g_displayLevel = 2; - -#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) - - -/*-******************************************************* -* Fuzzer functions -*********************************************************/ -static clock_t FUZ_GetClockSpan(clock_t clockStart) -{ - return clock() - clockStart; /* works even if overflow; max span ~ 30mn */ -} - -static void FUZ_displayUpdate(unsigned testNb) -{ - static clock_t g_time = 0; - static const clock_t g_refreshRate = CLOCKS_PER_SEC / 5; - if ((FUZ_GetClockSpan(g_time) > g_refreshRate) || (g_displayLevel>=4)) { - g_time = clock(); - DISPLAY("\r%5u ", testNb); - fflush(stdout); - } -} - -static U32 FUZ_rotl32(U32 u32, U32 nbBits) -{ - return ((u32 << nbBits) | (u32 >> (32 - nbBits))); -} - -static U32 FUZ_highbit32(U32 v32) -{ - unsigned nbBits = 0; - if (v32==0) return 0; - while (v32) { v32 >>= 1; nbBits++; } - return nbBits; -} - -static U32 FUZ_rand(U32* src) -{ - U32 rand32 = *src; - rand32 *= PRIME1; - rand32 ^= PRIME2; - rand32 = FUZ_rotl32(rand32, 13); - *src = rand32; - return rand32; -} - - -#define FUZ_RAND15BITS ((FUZ_rand(seed) >> 3) & 32767) -#define FUZ_RANDLENGTH ( ((FUZ_rand(seed) >> 7) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15) -static void FUZ_fillCompressibleNoiseBuffer(void* buffer, size_t bufferSize, double proba, U32* seed) -{ - BYTE* const BBuffer = (BYTE*)buffer; - size_t pos = 0; - U32 const P32 = (U32)(32768 * proba); - - /* First Bytes */ - while (pos < 20) - BBuffer[pos++] = (BYTE)(FUZ_rand(seed)); - - while (pos < bufferSize) { - /* Select : Literal (noise) or copy (within 64K) */ - if (FUZ_RAND15BITS < P32) { - /* Copy (within 64K) */ - size_t const length = (size_t)FUZ_RANDLENGTH + 4; - size_t const d = MIN(pos+length, bufferSize); - size_t match; - size_t offset = (size_t)FUZ_RAND15BITS + 1; - while (offset > pos) offset >>= 1; - match = pos - offset; - while (pos < d) BBuffer[pos++] = BBuffer[match++]; - } else { - /* Literal (noise) */ - size_t const length = FUZ_RANDLENGTH; - size_t const d = MIN(pos+length, bufferSize); - while (pos < d) BBuffer[pos++] = (BYTE)(FUZ_rand(seed) >> 5); - } - } -} - - -#define MAX_NB_BUFF_I134 150 -#define BLOCKSIZE_I134 (32 MB) -/*! FUZ_AddressOverflow() : -* Aggressively pushes memory allocation limits, -* and generates patterns which create address space overflow. -* only possible in 32-bits mode */ -static int FUZ_AddressOverflow(void) -{ - char* buffers[MAX_NB_BUFF_I134+1]; - int nbBuff=0; - int highAddress = 0; - - DISPLAY("Overflow tests : "); - - /* Only possible in 32-bits */ - if (sizeof(void*)==8) { - DISPLAY("64 bits mode : no overflow \n"); - fflush(stdout); - return 0; - } - - buffers[0] = (char*)malloc(BLOCKSIZE_I134); - buffers[1] = (char*)malloc(BLOCKSIZE_I134); - if ((!buffers[0]) || (!buffers[1])) { - free(buffers[0]); free(buffers[1]); - DISPLAY("not enough memory for tests \n"); - return 0; - } - - for (nbBuff=2; nbBuff < MAX_NB_BUFF_I134; nbBuff++) { - DISPLAY("%3i \b\b\b\b", nbBuff); fflush(stdout); - buffers[nbBuff] = (char*)malloc(BLOCKSIZE_I134); - if (buffers[nbBuff]==NULL) goto _endOfTests; - - if (((uintptr_t)buffers[nbBuff] > (uintptr_t)0x80000000) && (!highAddress)) { - DISPLAY("high address detected : "); - fflush(stdout); - highAddress=1; - } - - { size_t const sizeToGenerateOverflow = (size_t)(- ((uintptr_t)buffers[nbBuff-1]) + 512); - int const nbOf255 = (int)((sizeToGenerateOverflow / 255) + 1); - char* const input = buffers[nbBuff-1]; - char* output = buffers[nbBuff]; - int r; - input[0] = (char)0xF0; /* Literal length overflow */ - input[1] = (char)0xFF; - input[2] = (char)0xFF; - input[3] = (char)0xFF; - { int u; for(u = 4; u <= nbOf255+4; u++) input[u] = (char)0xff; } - r = LZ4_decompress_safe(input, output, nbOf255+64, BLOCKSIZE_I134); - if (r>0) { DISPLAY("LZ4_decompress_safe = %i \n", r); goto _overflowError; } - input[0] = (char)0x1F; /* Match length overflow */ - input[1] = (char)0x01; - input[2] = (char)0x01; - input[3] = (char)0x00; - r = LZ4_decompress_safe(input, output, nbOf255+64, BLOCKSIZE_I134); - if (r>0) { DISPLAY("LZ4_decompress_safe = %i \n", r); goto _overflowError; } - - output = buffers[nbBuff-2]; /* Reverse in/out pointer order */ - input[0] = (char)0xF0; /* Literal length overflow */ - input[1] = (char)0xFF; - input[2] = (char)0xFF; - input[3] = (char)0xFF; - r = LZ4_decompress_safe(input, output, nbOf255+64, BLOCKSIZE_I134); - if (r>0) goto _overflowError; - input[0] = (char)0x1F; /* Match length overflow */ - input[1] = (char)0x01; - input[2] = (char)0x01; - input[3] = (char)0x00; - r = LZ4_decompress_safe(input, output, nbOf255+64, BLOCKSIZE_I134); - if (r>0) goto _overflowError; - } - } - - nbBuff++; -_endOfTests: - { int i; for (i=0 ; i=4) { \ - printf("\r%4u - %2u :", cycleNb, testNb); \ - printf(" " __VA_ARGS__); \ - printf(" "); \ - fflush(stdout); \ - } } - - - /* init */ - if(!CNBuffer || !compressedBuffer || !decodedBuffer || !LZ4dictHC) { - DISPLAY("Not enough memory to start fuzzer tests"); - exit(1); - } - if ( LZ4_initStream(&LZ4dictBody, sizeof(LZ4dictBody)) == NULL) abort(); - { U32 randState = coreRandState ^ PRIME3; - FUZ_fillCompressibleNoiseBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, &randState); - } - - /* move to startCycle */ - for (cycleNb = 0; cycleNb < startCycle; cycleNb++) - (void) FUZ_rand(&coreRandState); /* sync coreRandState */ - - /* Main test loop */ - for (cycleNb = startCycle; - (cycleNb < nbCycles) || (FUZ_GetClockSpan(clockStart) < clockDuration); - cycleNb++) { - U32 testNb = 0; - U32 randState = FUZ_rand(&coreRandState) ^ PRIME3; - int const blockSize = (FUZ_rand(&randState) % (FUZ_MAX_BLOCK_SIZE-1)) + 1; - int const blockStart = (int)(FUZ_rand(&randState) % (U32)(COMPRESSIBLE_NOISE_LENGTH - blockSize - 1)) + 1; - int const dictSizeRand = FUZ_rand(&randState) % FUZ_MAX_DICT_SIZE; - int const dictSize = MIN(dictSizeRand, blockStart - 1); - int const compressionLevel = FUZ_rand(&randState) % (LZ4HC_CLEVEL_MAX+1); - const char* block = ((char*)CNBuffer) + blockStart; - const char* dict = block - dictSize; - int compressedSize, HCcompressedSize; - int blockContinueCompressedSize; - U32 const crcOrig = XXH32(block, (size_t)blockSize, 0); - int ret; - - FUZ_displayUpdate(cycleNb); - - /* Compression tests */ - if ( ((FUZ_rand(&randState) & 63) == 2) - && ((size_t)blockSize < labSize) ) { - memcpy(lowAddrBuffer, block, blockSize); - block = (const char*)lowAddrBuffer; - } - - /* Test compression destSize */ - FUZ_DISPLAYTEST("test LZ4_compress_destSize()"); - { int cSize, srcSize = blockSize; - int const targetSize = srcSize * (int)((FUZ_rand(&randState) & 127)+1) >> 7; - char const endCheck = (char)(FUZ_rand(&randState) & 255); - compressedBuffer[targetSize] = endCheck; - cSize = LZ4_compress_destSize(block, compressedBuffer, &srcSize, targetSize); - FUZ_CHECKTEST(cSize > targetSize, "LZ4_compress_destSize() result larger than dst buffer !"); - FUZ_CHECKTEST(compressedBuffer[targetSize] != endCheck, "LZ4_compress_destSize() overwrite dst buffer !"); - FUZ_CHECKTEST(srcSize > blockSize, "LZ4_compress_destSize() read more than src buffer !"); - DISPLAYLEVEL(5, "destSize : %7i/%7i; content%7i/%7i ", cSize, targetSize, srcSize, blockSize); - if (targetSize>0) { - /* check correctness */ - U32 const crcBase = XXH32(block, (size_t)srcSize, 0); - char const canary = (char)(FUZ_rand(&randState) & 255); - FUZ_CHECKTEST((cSize==0), "LZ4_compress_destSize() compression failed"); - FUZ_DISPLAYTEST(); - decodedBuffer[srcSize] = canary; - { int const dSize = LZ4_decompress_safe(compressedBuffer, decodedBuffer, cSize, srcSize); - FUZ_CHECKTEST(dSize<0, "LZ4_decompress_safe() failed on data compressed by LZ4_compress_destSize"); - FUZ_CHECKTEST(dSize!=srcSize, "LZ4_decompress_safe() failed : did not fully decompressed data"); - } - FUZ_CHECKTEST(decodedBuffer[srcSize] != canary, "LZ4_decompress_safe() overwrite dst buffer !"); - { U32 const crcDec = XXH32(decodedBuffer, (size_t)srcSize, 0); - FUZ_CHECKTEST(crcDec!=crcBase, "LZ4_decompress_safe() corrupted decoded data"); - } } - DISPLAYLEVEL(5, " OK \n"); - } - - /* Test compression HC destSize */ - FUZ_DISPLAYTEST("test LZ4_compress_HC_destSize()"); - { int cSize, srcSize = blockSize; - int const targetSize = srcSize * (int)((FUZ_rand(&randState) & 127)+1) >> 7; - char const endCheck = (char)(FUZ_rand(&randState) & 255); - void* const ctx = LZ4_createHC(block); - FUZ_CHECKTEST(ctx==NULL, "LZ4_createHC() allocation failed"); - compressedBuffer[targetSize] = endCheck; - cSize = LZ4_compress_HC_destSize(ctx, block, compressedBuffer, &srcSize, targetSize, compressionLevel); - DISPLAYLEVEL(5, "LZ4_compress_HC_destSize(%i): destSize : %7i/%7i; content%7i/%7i ", - compressionLevel, cSize, targetSize, srcSize, blockSize); - LZ4_freeHC(ctx); - FUZ_CHECKTEST(cSize > targetSize, "LZ4_compress_HC_destSize() result larger than dst buffer !"); - FUZ_CHECKTEST(compressedBuffer[targetSize] != endCheck, "LZ4_compress_HC_destSize() overwrite dst buffer !"); - FUZ_CHECKTEST(srcSize > blockSize, "LZ4_compress_HC_destSize() fed more than src buffer !"); - if (targetSize>0) { - /* check correctness */ - U32 const crcBase = XXH32(block, (size_t)srcSize, 0); - char const canary = (char)(FUZ_rand(&randState) & 255); - FUZ_CHECKTEST((cSize==0), "LZ4_compress_HC_destSize() compression failed"); - FUZ_DISPLAYTEST(); - decodedBuffer[srcSize] = canary; - { int const dSize = LZ4_decompress_safe(compressedBuffer, decodedBuffer, cSize, srcSize); - FUZ_CHECKTEST(dSize<0, "LZ4_decompress_safe failed (%i) on data compressed by LZ4_compressHC_destSize", dSize); - FUZ_CHECKTEST(dSize!=srcSize, "LZ4_decompress_safe failed : decompressed %i bytes, was supposed to decompress %i bytes", dSize, srcSize); - } - FUZ_CHECKTEST(decodedBuffer[srcSize] != canary, "LZ4_decompress_safe overwrite dst buffer !"); - { U32 const crcDec = XXH32(decodedBuffer, (size_t)srcSize, 0); - FUZ_CHECKTEST(crcDec!=crcBase, "LZ4_decompress_safe() corrupted decoded data"); - } } - DISPLAYLEVEL(5, " OK \n"); - } - - /* Test compression HC */ - FUZ_DISPLAYTEST("test LZ4_compress_HC()"); - HCcompressedSize = LZ4_compress_HC(block, compressedBuffer, blockSize, (int)compressedBufferSize, compressionLevel); - FUZ_CHECKTEST(HCcompressedSize==0, "LZ4_compress_HC() failed"); - - /* Test compression HC using external state */ - FUZ_DISPLAYTEST("test LZ4_compress_HC_extStateHC()"); - { int const r = LZ4_compress_HC_extStateHC(stateLZ4HC, block, compressedBuffer, blockSize, (int)compressedBufferSize, compressionLevel); - FUZ_CHECKTEST(r==0, "LZ4_compress_HC_extStateHC() failed") - } - - /* Test compression HC using fast reset external state */ - FUZ_DISPLAYTEST("test LZ4_compress_HC_extStateHC_fastReset()"); - { int const r = LZ4_compress_HC_extStateHC_fastReset(stateLZ4HC, block, compressedBuffer, blockSize, (int)compressedBufferSize, compressionLevel); - FUZ_CHECKTEST(r==0, "LZ4_compress_HC_extStateHC_fastReset() failed"); - } - - /* Test compression using external state */ - FUZ_DISPLAYTEST("test LZ4_compress_fast_extState()"); - { int const r = LZ4_compress_fast_extState(stateLZ4, block, compressedBuffer, blockSize, (int)compressedBufferSize, 8); - FUZ_CHECKTEST(r==0, "LZ4_compress_fast_extState() failed"); } - - /* Test compression using fast reset external state*/ - FUZ_DISPLAYTEST(); - { int const r = LZ4_compress_fast_extState_fastReset(stateLZ4, block, compressedBuffer, blockSize, (int)compressedBufferSize, 8); - FUZ_CHECKTEST(r==0, "LZ4_compress_fast_extState_fastReset() failed"); } - - /* Test compression */ - FUZ_DISPLAYTEST("test LZ4_compress_default()"); - compressedSize = LZ4_compress_default(block, compressedBuffer, blockSize, (int)compressedBufferSize); - FUZ_CHECKTEST(compressedSize<=0, "LZ4_compress_default() failed"); - - /* Decompression tests */ - - /* Test decompress_fast() with input buffer size exactly correct => must not read out of bound */ - { char* const cBuffer_exact = (char*)malloc((size_t)compressedSize); - assert(cBuffer_exact != NULL); - assert(compressedSize <= (int)compressedBufferSize); - memcpy(cBuffer_exact, compressedBuffer, compressedSize); - - /* Test decoding with output size exactly correct => must work */ - FUZ_DISPLAYTEST("LZ4_decompress_fast() with exact output buffer"); - { int const r = LZ4_decompress_fast(cBuffer_exact, decodedBuffer, blockSize); - FUZ_CHECKTEST(r<0, "LZ4_decompress_fast failed despite correct space"); - FUZ_CHECKTEST(r!=compressedSize, "LZ4_decompress_fast failed : did not fully read compressed data"); - } - { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_fast corrupted decoded data"); - } - - /* Test decoding with one byte missing => must fail */ - FUZ_DISPLAYTEST("LZ4_decompress_fast() with output buffer 1-byte too short"); - decodedBuffer[blockSize-1] = 0; - { int const r = LZ4_decompress_fast(cBuffer_exact, decodedBuffer, blockSize-1); - FUZ_CHECKTEST(r>=0, "LZ4_decompress_fast should have failed, due to Output Size being too small"); - } - FUZ_CHECKTEST(decodedBuffer[blockSize-1]!=0, "LZ4_decompress_fast overrun specified output buffer"); - - /* Test decoding with one byte too much => must fail */ - FUZ_DISPLAYTEST(); - { int const r = LZ4_decompress_fast(cBuffer_exact, decodedBuffer, blockSize+1); - FUZ_CHECKTEST(r>=0, "LZ4_decompress_fast should have failed, due to Output Size being too large"); - } - - /* Test decoding with output size exactly what's necessary => must work */ - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize] = 0; - { int const r = LZ4_decompress_safe(cBuffer_exact, decodedBuffer, compressedSize, blockSize); - FUZ_CHECKTEST(r<0, "LZ4_decompress_safe failed despite sufficient space"); - FUZ_CHECKTEST(r!=blockSize, "LZ4_decompress_safe did not regenerate original data"); - } - FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe corrupted decoded data"); - } - - /* Test decoding with more than enough output size => must work */ - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize] = 0; - decodedBuffer[blockSize+1] = 0; - { int const r = LZ4_decompress_safe(cBuffer_exact, decodedBuffer, compressedSize, blockSize+1); - FUZ_CHECKTEST(r<0, "LZ4_decompress_safe failed despite amply sufficient space"); - FUZ_CHECKTEST(r!=blockSize, "LZ4_decompress_safe did not regenerate original data"); - } - FUZ_CHECKTEST(decodedBuffer[blockSize+1], "LZ4_decompress_safe overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe corrupted decoded data"); - } - - /* Test decoding with output size being one byte too short => must fail */ - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize-1] = 0; - { int const r = LZ4_decompress_safe(cBuffer_exact, decodedBuffer, compressedSize, blockSize-1); - FUZ_CHECKTEST(r>=0, "LZ4_decompress_safe should have failed, due to Output Size being one byte too short"); - } - FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_safe overrun specified output buffer size"); - - /* Test decoding with output size being 10 bytes too short => must fail */ - FUZ_DISPLAYTEST(); - if (blockSize>10) { - decodedBuffer[blockSize-10] = 0; - { int const r = LZ4_decompress_safe(cBuffer_exact, decodedBuffer, compressedSize, blockSize-10); - FUZ_CHECKTEST(r>=0, "LZ4_decompress_safe should have failed, due to Output Size being 10 bytes too short"); - } - FUZ_CHECKTEST(decodedBuffer[blockSize-10], "LZ4_decompress_safe overrun specified output buffer size"); - } - - /* noisy src decompression test */ - - /* insert noise into src */ - { U32 const maxNbBits = FUZ_highbit32((U32)compressedSize); - size_t pos = 0; - for (;;) { - /* keep some original src */ - { U32 const nbBits = FUZ_rand(&randState) % maxNbBits; - size_t const mask = (1<= (size_t)compressedSize) break; - /* add noise */ - { U32 const nbBitsCodes = FUZ_rand(&randState) % maxNbBits; - U32 const nbBits = nbBitsCodes ? nbBitsCodes-1 : 0; - size_t const mask = (1< blockSize, "LZ4_decompress_safe on noisy src : result is too large : %u > %u (dst buffer)", (unsigned)decompressResult, (unsigned)blockSize); - } - { U32 endCheck; memcpy(&endCheck, decodedBuffer+blockSize, sizeof(endCheck)); - FUZ_CHECKTEST(endMark!=endCheck, "LZ4_decompress_safe on noisy src : dst buffer overflow"); - } } /* noisy src decompression test */ - - free(cBuffer_exact); - } - - /* Test decoding with input size being one byte too short => must fail */ - FUZ_DISPLAYTEST(); - { int const r = LZ4_decompress_safe(compressedBuffer, decodedBuffer, compressedSize-1, blockSize); - FUZ_CHECKTEST(r>=0, "LZ4_decompress_safe should have failed, due to input size being one byte too short (blockSize=%i, result=%i, compressedSize=%i)", blockSize, r, compressedSize); - } - - /* Test decoding with input size being one byte too large => must fail */ - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize] = 0; - { int const r = LZ4_decompress_safe(compressedBuffer, decodedBuffer, compressedSize+1, blockSize); - FUZ_CHECKTEST(r>=0, "LZ4_decompress_safe should have failed, due to input size being too large"); - } - FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe overrun specified output buffer size"); - - /* Test partial decoding => must work */ - FUZ_DISPLAYTEST("test LZ4_decompress_safe_partial"); - { size_t const missingOutBytes = FUZ_rand(&randState) % (unsigned)blockSize; - int const targetSize = (int)((size_t)blockSize - missingOutBytes); - size_t const extraneousInBytes = FUZ_rand(&randState) % 2; - int const inCSize = (int)((size_t)compressedSize + extraneousInBytes); - char const sentinel = decodedBuffer[targetSize] = block[targetSize] ^ 0x5A; - int const decResult = LZ4_decompress_safe_partial(compressedBuffer, decodedBuffer, inCSize, targetSize, blockSize); - FUZ_CHECKTEST(decResult<0, "LZ4_decompress_safe_partial failed despite valid input data (error:%i)", decResult); - FUZ_CHECKTEST(decResult != targetSize, "LZ4_decompress_safe_partial did not regenerated required amount of data (%i < %i <= %i)", decResult, targetSize, blockSize); - FUZ_CHECKTEST(decodedBuffer[targetSize] != sentinel, "LZ4_decompress_safe_partial overwrite beyond requested size (though %i <= %i <= %i)", decResult, targetSize, blockSize); - FUZ_CHECKTEST(memcmp(block, decodedBuffer, (size_t)targetSize), "LZ4_decompress_safe_partial: corruption detected in regenerated data"); - } - - /* Test Compression with limited output size */ - - /* Test compression with output size being exactly what's necessary (should work) */ - FUZ_DISPLAYTEST("test LZ4_compress_default() with output buffer just the right size"); - ret = LZ4_compress_default(block, compressedBuffer, blockSize, compressedSize); - FUZ_CHECKTEST(ret==0, "LZ4_compress_default() failed despite sufficient space"); - - /* Test compression with output size being exactly what's necessary and external state (should work) */ - FUZ_DISPLAYTEST("test LZ4_compress_fast_extState() with output buffer just the right size"); - ret = LZ4_compress_fast_extState(stateLZ4, block, compressedBuffer, blockSize, compressedSize, 1); - FUZ_CHECKTEST(ret==0, "LZ4_compress_fast_extState() failed despite sufficient space"); - - /* Test HC compression with output size being exactly what's necessary (should work) */ - FUZ_DISPLAYTEST("test LZ4_compress_HC() with output buffer just the right size"); - ret = LZ4_compress_HC(block, compressedBuffer, blockSize, HCcompressedSize, compressionLevel); - FUZ_CHECKTEST(ret==0, "LZ4_compress_HC() failed despite sufficient space"); - - /* Test HC compression with output size being exactly what's necessary (should work) */ - FUZ_DISPLAYTEST("test LZ4_compress_HC_extStateHC() with output buffer just the right size"); - ret = LZ4_compress_HC_extStateHC(stateLZ4HC, block, compressedBuffer, blockSize, HCcompressedSize, compressionLevel); - FUZ_CHECKTEST(ret==0, "LZ4_compress_HC_extStateHC() failed despite sufficient space"); - - /* Test compression with missing bytes into output buffer => must fail */ - FUZ_DISPLAYTEST("test LZ4_compress_default() with output buffer a bit too short"); - { int missingBytes = (FUZ_rand(&randState) % 0x3F) + 1; - if (missingBytes >= compressedSize) missingBytes = compressedSize-1; - missingBytes += !missingBytes; /* avoid special case missingBytes==0 */ - compressedBuffer[compressedSize-missingBytes] = 0; - { int const cSize = LZ4_compress_default(block, compressedBuffer, blockSize, compressedSize-missingBytes); - FUZ_CHECKTEST(cSize, "LZ4_compress_default should have failed (output buffer too small by %i byte)", missingBytes); - } - FUZ_CHECKTEST(compressedBuffer[compressedSize-missingBytes], "LZ4_compress_default overran output buffer ! (%i missingBytes)", missingBytes) - } - - /* Test HC compression with missing bytes into output buffer => must fail */ - FUZ_DISPLAYTEST("test LZ4_compress_HC() with output buffer a bit too short"); - { int missingBytes = (FUZ_rand(&randState) % 0x3F) + 1; - if (missingBytes >= HCcompressedSize) missingBytes = HCcompressedSize-1; - missingBytes += !missingBytes; /* avoid special case missingBytes==0 */ - compressedBuffer[HCcompressedSize-missingBytes] = 0; - { int const hcSize = LZ4_compress_HC(block, compressedBuffer, blockSize, HCcompressedSize-missingBytes, compressionLevel); - FUZ_CHECKTEST(hcSize, "LZ4_compress_HC should have failed (output buffer too small by %i byte)", missingBytes); - } - FUZ_CHECKTEST(compressedBuffer[HCcompressedSize-missingBytes], "LZ4_compress_HC overran output buffer ! (%i missingBytes)", missingBytes) - } - - - /*-******************/ - /* Dictionary tests */ - /*-******************/ - - /* Compress using dictionary */ - FUZ_DISPLAYTEST("test LZ4_compress_fast_continue() with dictionary of size %i", dictSize); - { LZ4_stream_t LZ4_stream; - LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); - LZ4_compress_fast_continue (&LZ4_stream, dict, compressedBuffer, dictSize, (int)compressedBufferSize, 1); /* Just to fill hash tables */ - blockContinueCompressedSize = LZ4_compress_fast_continue (&LZ4_stream, block, compressedBuffer, blockSize, (int)compressedBufferSize, 1); - FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_fast_continue failed"); - } - - /* Decompress with dictionary as prefix */ - FUZ_DISPLAYTEST("test LZ4_decompress_fast_usingDict() with dictionary as prefix"); - memcpy(decodedBuffer, dict, dictSize); - ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer+dictSize, blockSize, decodedBuffer, dictSize); - FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_decompress_fast_usingDict did not read all compressed block input"); - { U32 const crcCheck = XXH32(decodedBuffer+dictSize, (size_t)blockSize, 0); - if (crcCheck!=crcOrig) { - FUZ_findDiff(block, decodedBuffer); - EXIT_MSG("LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize); - } } - - FUZ_DISPLAYTEST("test LZ4_decompress_safe_usingDict()"); - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer+dictSize, blockContinueCompressedSize, blockSize, decodedBuffer, dictSize); - FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); - { U32 const crcCheck = XXH32(decodedBuffer+dictSize, (size_t)blockSize, 0); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); - } - - /* Compress using External dictionary */ - FUZ_DISPLAYTEST("test LZ4_compress_fast_continue(), with non-contiguous dictionary"); - dict -= (size_t)(FUZ_rand(&randState) & 0xF) + 1; /* create space, so now dictionary is an ExtDict */ - if (dict < (char*)CNBuffer) dict = (char*)CNBuffer; - LZ4_loadDict(&LZ4dictBody, dict, dictSize); - blockContinueCompressedSize = LZ4_compress_fast_continue(&LZ4dictBody, block, compressedBuffer, blockSize, (int)compressedBufferSize, 1); - FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_fast_continue failed"); - - FUZ_DISPLAYTEST("LZ4_compress_fast_continue() with dictionary and output buffer too short by one byte"); - LZ4_loadDict(&LZ4dictBody, dict, dictSize); - ret = LZ4_compress_fast_continue(&LZ4dictBody, block, compressedBuffer, blockSize, blockContinueCompressedSize-1, 1); - FUZ_CHECKTEST(ret>0, "LZ4_compress_fast_continue using ExtDict should fail : one missing byte for output buffer : %i written, %i buffer", ret, blockContinueCompressedSize); - - FUZ_DISPLAYTEST("test LZ4_compress_fast_continue() with dictionary loaded with LZ4_loadDict()"); - DISPLAYLEVEL(5, " compress %i bytes from buffer(%p) into dst(%p) using dict(%p) of size %i \n", - blockSize, (const void *)block, (void *)decodedBuffer, (const void *)dict, dictSize); - LZ4_loadDict(&LZ4dictBody, dict, dictSize); - ret = LZ4_compress_fast_continue(&LZ4dictBody, block, compressedBuffer, blockSize, blockContinueCompressedSize, 1); - FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_limitedOutput_compressed size is different (%i != %i)", ret, blockContinueCompressedSize); - FUZ_CHECKTEST(ret<=0, "LZ4_compress_fast_continue should work : enough size available within output buffer"); - - /* Decompress with dictionary as external */ - FUZ_DISPLAYTEST("test LZ4_decompress_fast_usingDict() with dictionary as extDict"); - DISPLAYLEVEL(5, " decoding %i bytes from buffer(%p) using dict(%p) of size %i \n", - blockSize, (void *)decodedBuffer, (const void *)dict, dictSize); - decodedBuffer[blockSize] = 0; - ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer, blockSize, dict, dictSize); - FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_decompress_fast_usingDict did not read all compressed block input"); - FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_fast_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - if (crcCheck!=crcOrig) { - FUZ_findDiff(block, decodedBuffer); - EXIT_MSG("LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize); - } } - - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize] = 0; - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize); - FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); - FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); - } - - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize-1] = 0; - ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer, blockSize-1, dict, dictSize); - FUZ_CHECKTEST(ret>=0, "LZ4_decompress_fast_usingDict should have failed : wrong original size (-1 byte)"); - FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_fast_usingDict overrun specified output buffer size"); - - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize-1] = 0; - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize-1, dict, dictSize); - FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe_usingDict should have failed : not enough output size (-1 byte)"); - FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); - - FUZ_DISPLAYTEST(); - { int const missingBytes = (FUZ_rand(&randState) & 0xF) + 2; - if (blockSize > missingBytes) { - decodedBuffer[blockSize-missingBytes] = 0; - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize-missingBytes, dict, dictSize); - FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe_usingDict should have failed : output buffer too small (-%i byte)", missingBytes); - FUZ_CHECKTEST(decodedBuffer[blockSize-missingBytes], "LZ4_decompress_safe_usingDict overrun specified output buffer size (-%i byte) (blockSize=%i)", missingBytes, blockSize); - } } - - /* Compress using external dictionary stream */ - { LZ4_stream_t LZ4_stream; - int expectedSize; - U32 expectedCrc; - - FUZ_DISPLAYTEST("LZ4_compress_fast_continue() after LZ4_loadDict()"); - LZ4_loadDict(&LZ4dictBody, dict, dictSize); - expectedSize = LZ4_compress_fast_continue(&LZ4dictBody, block, compressedBuffer, blockSize, (int)compressedBufferSize, 1); - FUZ_CHECKTEST(expectedSize<=0, "LZ4_compress_fast_continue reference compression for extDictCtx should have succeeded"); - expectedCrc = XXH32(compressedBuffer, (size_t)expectedSize, 0); - - FUZ_DISPLAYTEST("LZ4_compress_fast_continue() after LZ4_attach_dictionary()"); - LZ4_loadDict(&LZ4dictBody, dict, dictSize); - LZ4_initStream(&LZ4_stream, sizeof(LZ4_stream)); - LZ4_attach_dictionary(&LZ4_stream, &LZ4dictBody); - blockContinueCompressedSize = LZ4_compress_fast_continue(&LZ4_stream, block, compressedBuffer, blockSize, (int)compressedBufferSize, 1); - FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_fast_continue using extDictCtx failed"); - - /* In the future, it might be desirable to let extDictCtx mode's - * output diverge from the output generated by regular extDict mode. - * Until that time, this comparison serves as a good regression - * test. - */ - FUZ_CHECKTEST(blockContinueCompressedSize != expectedSize, "LZ4_compress_fast_continue using extDictCtx produced different-sized output (%d expected vs %d actual)", expectedSize, blockContinueCompressedSize); - FUZ_CHECKTEST(XXH32(compressedBuffer, (size_t)blockContinueCompressedSize, 0) != expectedCrc, "LZ4_compress_fast_continue using extDictCtx produced different output"); - - FUZ_DISPLAYTEST("LZ4_compress_fast_continue() after LZ4_attach_dictionary(), but output buffer is 1 byte too short"); - LZ4_resetStream_fast(&LZ4_stream); - LZ4_attach_dictionary(&LZ4_stream, &LZ4dictBody); - ret = LZ4_compress_fast_continue(&LZ4_stream, block, compressedBuffer, blockSize, blockContinueCompressedSize-1, 1); - FUZ_CHECKTEST(ret>0, "LZ4_compress_fast_continue using extDictCtx should fail : one missing byte for output buffer : %i written, %i buffer", ret, blockContinueCompressedSize); - /* note : context is no longer dirty after a failed compressed block */ - - FUZ_DISPLAYTEST(); - LZ4_resetStream_fast(&LZ4_stream); - LZ4_attach_dictionary(&LZ4_stream, &LZ4dictBody); - ret = LZ4_compress_fast_continue(&LZ4_stream, block, compressedBuffer, blockSize, blockContinueCompressedSize, 1); - FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_limitedOutput_compressed size is different (%i != %i)", ret, blockContinueCompressedSize); - FUZ_CHECKTEST(ret<=0, "LZ4_compress_fast_continue using extDictCtx should work : enough size available within output buffer"); - FUZ_CHECKTEST(ret != expectedSize, "LZ4_compress_fast_continue using extDictCtx produced different-sized output"); - FUZ_CHECKTEST(XXH32(compressedBuffer, (size_t)ret, 0) != expectedCrc, "LZ4_compress_fast_continue using extDictCtx produced different output"); - - FUZ_DISPLAYTEST(); - LZ4_resetStream_fast(&LZ4_stream); - LZ4_attach_dictionary(&LZ4_stream, &LZ4dictBody); - ret = LZ4_compress_fast_continue(&LZ4_stream, block, compressedBuffer, blockSize, blockContinueCompressedSize, 1); - FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_limitedOutput_compressed size is different (%i != %i)", ret, blockContinueCompressedSize); - FUZ_CHECKTEST(ret<=0, "LZ4_compress_fast_continue using extDictCtx with re-used context should work : enough size available within output buffer"); - FUZ_CHECKTEST(ret != expectedSize, "LZ4_compress_fast_continue using extDictCtx produced different-sized output"); - FUZ_CHECKTEST(XXH32(compressedBuffer, (size_t)ret, 0) != expectedCrc, "LZ4_compress_fast_continue using extDictCtx produced different output"); - } - - /* Decompress with dictionary as external */ - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize] = 0; - ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer, blockSize, dict, dictSize); - FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_decompress_fast_usingDict did not read all compressed block input"); - FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_fast_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - if (crcCheck!=crcOrig) { - FUZ_findDiff(block, decodedBuffer); - EXIT_MSG("LZ4_decompress_fast_usingDict corrupted decoded data (dict %i)", dictSize); - } } - - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize] = 0; - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize); - FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); - FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - FUZ_CHECKTEST(crcCheck!=crcOrig, "LZ4_decompress_safe_usingDict corrupted decoded data"); - } - - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize-1] = 0; - ret = LZ4_decompress_fast_usingDict(compressedBuffer, decodedBuffer, blockSize-1, dict, dictSize); - FUZ_CHECKTEST(ret>=0, "LZ4_decompress_fast_usingDict should have failed : wrong original size (-1 byte)"); - FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_fast_usingDict overrun specified output buffer size"); - - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize-1] = 0; - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize-1, dict, dictSize); - FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe_usingDict should have failed : not enough output size (-1 byte)"); - FUZ_CHECKTEST(decodedBuffer[blockSize-1], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); - - FUZ_DISPLAYTEST("LZ4_decompress_safe_usingDict with a too small output buffer"); - { int const missingBytes = (FUZ_rand(&randState) & 0xF) + 2; - if (blockSize > missingBytes) { - decodedBuffer[blockSize-missingBytes] = 0; - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize-missingBytes, dict, dictSize); - FUZ_CHECKTEST(ret>=0, "LZ4_decompress_safe_usingDict should have failed : output buffer too small (-%i byte)", missingBytes); - FUZ_CHECKTEST(decodedBuffer[blockSize-missingBytes], "LZ4_decompress_safe_usingDict overrun specified output buffer size (-%i byte) (blockSize=%i)", missingBytes, blockSize); - } } - - /* Compress HC using External dictionary */ - FUZ_DISPLAYTEST("LZ4_compress_HC_continue with an external dictionary"); - dict -= (FUZ_rand(&randState) & 7); /* even bigger separation */ - if (dict < (char*)CNBuffer) dict = (char*)CNBuffer; - LZ4_loadDictHC(LZ4dictHC, dict, dictSize); - LZ4_setCompressionLevel (LZ4dictHC, compressionLevel); - blockContinueCompressedSize = LZ4_compress_HC_continue(LZ4dictHC, block, compressedBuffer, blockSize, (int)compressedBufferSize); - FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_HC_continue failed"); - FUZ_CHECKTEST(LZ4dictHC->internal_donotuse.dirty, "Context should be clean"); - - FUZ_DISPLAYTEST("LZ4_compress_HC_continue with same external dictionary, but output buffer 1 byte too short"); - LZ4_loadDictHC(LZ4dictHC, dict, dictSize); - ret = LZ4_compress_HC_continue(LZ4dictHC, block, compressedBuffer, blockSize, blockContinueCompressedSize-1); - FUZ_CHECKTEST(ret>0, "LZ4_compress_HC_continue using ExtDict should fail : one missing byte for output buffer (expected %i, but result=%i)", blockContinueCompressedSize, ret); - /* note : context is no longer dirty after a failed compressed block */ - - FUZ_DISPLAYTEST("LZ4_compress_HC_continue with same external dictionary, and output buffer exactly the right size"); - LZ4_loadDictHC(LZ4dictHC, dict, dictSize); - ret = LZ4_compress_HC_continue(LZ4dictHC, block, compressedBuffer, blockSize, blockContinueCompressedSize); - FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_HC_continue size is different : ret(%i) != expected(%i)", ret, blockContinueCompressedSize); - FUZ_CHECKTEST(ret<=0, "LZ4_compress_HC_continue should work : enough size available within output buffer"); - FUZ_CHECKTEST(LZ4dictHC->internal_donotuse.dirty, "Context should be clean"); - - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize] = 0; - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize); - FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); - FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - if (crcCheck!=crcOrig) { - FUZ_findDiff(block, decodedBuffer); - EXIT_MSG("LZ4_decompress_safe_usingDict corrupted decoded data"); - } } - - /* Compress HC using external dictionary stream */ - FUZ_DISPLAYTEST(); - { LZ4_streamHC_t* const LZ4_streamHC = LZ4_createStreamHC(); - - LZ4_loadDictHC(LZ4dictHC, dict, dictSize); - LZ4_attach_HC_dictionary(LZ4_streamHC, LZ4dictHC); - LZ4_setCompressionLevel (LZ4_streamHC, compressionLevel); - blockContinueCompressedSize = LZ4_compress_HC_continue(LZ4_streamHC, block, compressedBuffer, blockSize, (int)compressedBufferSize); - FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_HC_continue with ExtDictCtx failed"); - FUZ_CHECKTEST(LZ4_streamHC->internal_donotuse.dirty, "Context should be clean"); - - FUZ_DISPLAYTEST(); - LZ4_resetStreamHC_fast (LZ4_streamHC, compressionLevel); - LZ4_attach_HC_dictionary(LZ4_streamHC, LZ4dictHC); - ret = LZ4_compress_HC_continue(LZ4_streamHC, block, compressedBuffer, blockSize, blockContinueCompressedSize-1); - FUZ_CHECKTEST(ret>0, "LZ4_compress_HC_continue using ExtDictCtx should fail : one missing byte for output buffer (%i != %i)", ret, blockContinueCompressedSize); - /* note : context is no longer dirty after a failed compressed block */ - - FUZ_DISPLAYTEST(); - LZ4_resetStreamHC_fast (LZ4_streamHC, compressionLevel); - LZ4_attach_HC_dictionary(LZ4_streamHC, LZ4dictHC); - ret = LZ4_compress_HC_continue(LZ4_streamHC, block, compressedBuffer, blockSize, blockContinueCompressedSize); - FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_HC_continue using ExtDictCtx size is different (%i != %i)", ret, blockContinueCompressedSize); - FUZ_CHECKTEST(ret<=0, "LZ4_compress_HC_continue using ExtDictCtx should work : enough size available within output buffer"); - FUZ_CHECKTEST(LZ4_streamHC->internal_donotuse.dirty, "Context should be clean"); - - FUZ_DISPLAYTEST(); - LZ4_resetStreamHC_fast (LZ4_streamHC, compressionLevel); - LZ4_attach_HC_dictionary(LZ4_streamHC, LZ4dictHC); - ret = LZ4_compress_HC_continue(LZ4_streamHC, block, compressedBuffer, blockSize, blockContinueCompressedSize); - FUZ_CHECKTEST(ret!=blockContinueCompressedSize, "LZ4_compress_HC_continue using ExtDictCtx and fast reset size is different (%i != %i)", - ret, blockContinueCompressedSize); - FUZ_CHECKTEST(ret<=0, "LZ4_compress_HC_continue using ExtDictCtx and fast reset should work : enough size available within output buffer"); - FUZ_CHECKTEST(LZ4_streamHC->internal_donotuse.dirty, "Context should be clean"); - - LZ4_freeStreamHC(LZ4_streamHC); - } - - FUZ_DISPLAYTEST(); - decodedBuffer[blockSize] = 0; - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, blockSize, dict, dictSize); - FUZ_CHECKTEST(ret!=blockSize, "LZ4_decompress_safe_usingDict did not regenerate original data"); - FUZ_CHECKTEST(decodedBuffer[blockSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size"); - { U32 const crcCheck = XXH32(decodedBuffer, (size_t)blockSize, 0); - if (crcCheck!=crcOrig) { - FUZ_findDiff(block, decodedBuffer); - EXIT_MSG("LZ4_decompress_safe_usingDict corrupted decoded data"); - } } - - /* Compress HC continue destSize */ - FUZ_DISPLAYTEST(); - { int const availableSpace = (int)(FUZ_rand(&randState) % (U32)blockSize) + 5; - int consumedSize = blockSize; - FUZ_DISPLAYTEST(); - LZ4_loadDictHC(LZ4dictHC, dict, dictSize); - LZ4_setCompressionLevel(LZ4dictHC, compressionLevel); - blockContinueCompressedSize = LZ4_compress_HC_continue_destSize(LZ4dictHC, block, compressedBuffer, &consumedSize, availableSpace); - DISPLAYLEVEL(5, " LZ4_compress_HC_continue_destSize : compressed %6i/%6i into %6i/%6i at cLevel=%i \n", - consumedSize, blockSize, blockContinueCompressedSize, availableSpace, compressionLevel); - FUZ_CHECKTEST(blockContinueCompressedSize==0, "LZ4_compress_HC_continue_destSize failed"); - FUZ_CHECKTEST(blockContinueCompressedSize > availableSpace, "LZ4_compress_HC_continue_destSize write overflow"); - FUZ_CHECKTEST(consumedSize > blockSize, "LZ4_compress_HC_continue_destSize read overflow"); - - FUZ_DISPLAYTEST(); - decodedBuffer[consumedSize] = 0; - ret = LZ4_decompress_safe_usingDict(compressedBuffer, decodedBuffer, blockContinueCompressedSize, consumedSize, dict, dictSize); - FUZ_CHECKTEST(ret != consumedSize, "LZ4_decompress_safe_usingDict regenerated %i bytes (%i expected)", ret, consumedSize); - FUZ_CHECKTEST(decodedBuffer[consumedSize], "LZ4_decompress_safe_usingDict overrun specified output buffer size") - { U32 const crcSrc = XXH32(block, (size_t)consumedSize, 0); - U32 const crcDst = XXH32(decodedBuffer, (size_t)consumedSize, 0); - if (crcSrc!=crcDst) { - FUZ_findDiff(block, decodedBuffer); - EXIT_MSG("LZ4_decompress_safe_usingDict corrupted decoded data"); - } } - } - - /* ***** End of tests *** */ - /* Fill stats */ - assert(blockSize >= 0); - bytes += (unsigned)blockSize; - assert(compressedSize >= 0); - cbytes += (unsigned)compressedSize; - assert(HCcompressedSize >= 0); - hcbytes += (unsigned)HCcompressedSize; - assert(blockContinueCompressedSize >= 0); - ccbytes += (unsigned)blockContinueCompressedSize; - } - - if (nbCycles<=1) nbCycles = cycleNb; /* end by time */ - bytes += !bytes; /* avoid division by 0 */ - printf("\r%7u /%7u - ", cycleNb, nbCycles); - printf("all tests completed successfully \n"); - printf("compression ratio: %0.3f%%\n", (double)cbytes/bytes*100); - printf("HC compression ratio: %0.3f%%\n", (double)hcbytes/bytes*100); - printf("ratio with dict: %0.3f%%\n", (double)ccbytes/bytes*100); - - /* release memory */ - free(CNBuffer); - free(compressedBuffer); - free(decodedBuffer); - FUZ_freeLowAddr(lowAddrBuffer, labSize); - LZ4_freeStreamHC(LZ4dictHC); - free(stateLZ4); - free(stateLZ4HC); - return result; -} - - -#define testInputSize (196 KB) -#define testCompressedSize (130 KB) -#define ringBufferSize (8 KB) - -static void FUZ_unitTests(int compressionLevel) -{ - const unsigned testNb = 0; - const unsigned seed = 0; - const unsigned cycleNb= 0; - char* testInput = (char*)malloc(testInputSize); - char* testCompressed = (char*)malloc(testCompressedSize); - char* testVerify = (char*)malloc(testInputSize); - char ringBuffer[ringBufferSize] = {0}; - U32 randState = 1; - - /* Init */ - if (!testInput || !testCompressed || !testVerify) { - EXIT_MSG("not enough memory for FUZ_unitTests"); - } - FUZ_fillCompressibleNoiseBuffer(testInput, testInputSize, 0.50, &randState); - - /* 32-bits address space overflow test */ - FUZ_AddressOverflow(); - - /* Test decoding with empty input */ - DISPLAYLEVEL(3, "LZ4_decompress_safe() with empty input \n"); - LZ4_decompress_safe(testCompressed, testVerify, 0, testInputSize); - - /* Test decoding with a one byte input */ - DISPLAYLEVEL(3, "LZ4_decompress_safe() with one byte input \n"); - { char const tmp = (char)0xFF; - LZ4_decompress_safe(&tmp, testVerify, 1, testInputSize); - } - - /* Test decoding shortcut edge case */ - DISPLAYLEVEL(3, "LZ4_decompress_safe() with shortcut edge case \n"); - { char tmp[17]; - /* 14 bytes of literals, followed by a 14 byte match. - * Should not read beyond the end of the buffer. - * See https://github.com/lz4/lz4/issues/508. */ - *tmp = (char)0xEE; - memset(tmp + 1, 0, 14); - tmp[15] = 14; - tmp[16] = 0; - { int const r = LZ4_decompress_safe(tmp, testVerify, sizeof(tmp), testInputSize); - FUZ_CHECKTEST(r >= 0, "LZ4_decompress_safe() should fail"); - } } - - - /* to be tested with undefined sanitizer */ - DISPLAYLEVEL(3, "LZ4_compress_default() with NULL input:"); - { int const maxCSize = LZ4_compressBound(0); - int const cSize = LZ4_compress_default(NULL, testCompressed, 0, maxCSize); - FUZ_CHECKTEST(!(cSize==1 && testCompressed[0]==0), - "compressing empty should give byte 0" - " (maxCSize == %i) (cSize == %i) (byte == 0x%02X)", - maxCSize, cSize, testCompressed[0]); - } - DISPLAYLEVEL(3, " OK \n"); - - DISPLAYLEVEL(3, "LZ4_compress_default() with both NULL input and output:"); - { int const cSize = LZ4_compress_default(NULL, NULL, 0, 0); - FUZ_CHECKTEST(cSize != 0, - "compressing into NULL must fail" - " (cSize == %i != 0)", cSize); - } - DISPLAYLEVEL(3, " OK \n"); - - /* in-place compression test */ - DISPLAYLEVEL(3, "in-place compression using LZ4_compress_default() :"); - { int const sampleSize = 65 KB; - int const maxCSize = LZ4_COMPRESSBOUND(sampleSize); - int const outSize = LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCSize); - int const startInputIndex = outSize - sampleSize; - char* const startInput = testCompressed + startInputIndex; - XXH32_hash_t const crcOrig = XXH32(testInput, sampleSize, 0); - int cSize; - assert(outSize < (int)testCompressedSize); - memcpy(startInput, testInput, sampleSize); /* copy at end of buffer */ - /* compress in-place */ - cSize = LZ4_compress_default(startInput, testCompressed, sampleSize, maxCSize); - assert(cSize != 0); /* ensure compression is successful */ - assert(maxCSize < INT_MAX); - assert(cSize <= maxCSize); - /* decompress and verify */ - { int const dSize = LZ4_decompress_safe(testCompressed, testVerify, cSize, testInputSize); - assert(dSize == sampleSize); /* correct size */ - { XXH32_hash_t const crcCheck = XXH32(testVerify, (size_t)dSize, 0); - FUZ_CHECKTEST(crcCheck != crcOrig, "LZ4_decompress_safe decompression corruption"); - } } } - DISPLAYLEVEL(3, " OK \n"); - - /* in-place decompression test */ - DISPLAYLEVEL(3, "in-place decompression, limit case:"); - { int const sampleSize = 65 KB; - - FUZ_fillCompressibleNoiseBuffer(testInput, sampleSize, 0.0, &randState); - memset(testInput, 0, 267); /* calculated exactly so that compressedSize == originalSize-1 */ - - { XXH64_hash_t const crcOrig = XXH64(testInput, sampleSize, 0); - int const cSize = LZ4_compress_default(testInput, testCompressed, sampleSize, testCompressedSize); - assert(cSize == sampleSize - 1); /* worst case for in-place decompression */ - - { int const bufferSize = LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(sampleSize); - int const startInputIndex = bufferSize - cSize; - char* const startInput = testVerify + startInputIndex; - memcpy(startInput, testCompressed, cSize); - - /* decompress and verify */ - { int const dSize = LZ4_decompress_safe(startInput, testVerify, cSize, sampleSize); - assert(dSize == sampleSize); /* correct size */ - { XXH64_hash_t const crcCheck = XXH64(testVerify, (size_t)dSize, 0); - FUZ_CHECKTEST(crcCheck != crcOrig, "LZ4_decompress_safe decompression corruption"); - } } } } } - DISPLAYLEVEL(3, " OK \n"); - - DISPLAYLEVEL(3, "LZ4_initStream with multiple valid alignments : "); - { typedef struct { - LZ4_stream_t state1; - LZ4_stream_t state2; - char c; - LZ4_stream_t state3; - } shct; - shct* const shc = (shct*)malloc(sizeof(*shc)); - assert(shc != NULL); - memset(shc, 0, sizeof(*shc)); - DISPLAYLEVEL(4, "state1(%p) state2(%p) state3(%p) LZ4_stream_t size(0x%x): ", - &(shc->state1), &(shc->state2), &(shc->state3), (unsigned)sizeof(LZ4_stream_t)); - FUZ_CHECKTEST( LZ4_initStream(&(shc->state1), sizeof(shc->state1)) == NULL, "state1 (%p) failed init", &(shc->state1) ); - FUZ_CHECKTEST( LZ4_initStream(&(shc->state2), sizeof(shc->state2)) == NULL, "state2 (%p) failed init", &(shc->state2) ); - FUZ_CHECKTEST( LZ4_initStream(&(shc->state3), sizeof(shc->state3)) == NULL, "state3 (%p) failed init", &(shc->state3) ); - FUZ_CHECKTEST( LZ4_initStream((char*)&(shc->state1) + 1, sizeof(shc->state1)) != NULL, - "hc1+1 (%p) init must fail, due to bad alignment", (char*)&(shc->state1) + 1 ); - free(shc); - } - DISPLAYLEVEL(3, "all inits OK \n"); - - /* Allocation test */ - { LZ4_stream_t* const statePtr = LZ4_createStream(); - FUZ_CHECKTEST(statePtr==NULL, "LZ4_createStream() allocation failed"); - LZ4_freeStream(statePtr); - } - - /* LZ4 streaming tests */ - { LZ4_stream_t streamingState; - - /* simple compression test */ - LZ4_initStream(&streamingState, sizeof(streamingState)); - { int const cs = LZ4_compress_fast_continue(&streamingState, testInput, testCompressed, testCompressedSize, testCompressedSize-1, 1); - FUZ_CHECKTEST(cs==0, "LZ4_compress_fast_continue() compression failed!"); - { int const r = LZ4_decompress_safe(testCompressed, testVerify, cs, testCompressedSize); - FUZ_CHECKTEST(r!=(int)testCompressedSize, "LZ4_decompress_safe() decompression failed"); - } } - { U64 const crcOrig = XXH64(testInput, testCompressedSize, 0); - U64 const crcNew = XXH64(testVerify, testCompressedSize, 0); - FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe() decompression corruption"); - } - - /* early saveDict */ - DISPLAYLEVEL(3, "saveDict (right after init) : "); - { LZ4_stream_t* const ctx = LZ4_initStream(&streamingState, sizeof(streamingState)); - assert(ctx != NULL); /* ensure init is successful */ - - /* Check access violation with asan */ - FUZ_CHECKTEST( LZ4_saveDict(ctx, NULL, 0) != 0, - "LZ4_saveDict() can't save anything into (NULL,0)"); - - /* Check access violation with asan */ - { char tmp_buffer[240] = { 0 }; - FUZ_CHECKTEST( LZ4_saveDict(ctx, tmp_buffer, sizeof(tmp_buffer)) != 0, - "LZ4_saveDict() can't save anything since compression hasn't started"); - } } - DISPLAYLEVEL(3, "OK \n"); - - /* ring buffer test */ - { XXH64_state_t xxhOrig; - XXH64_state_t xxhNewSafe, xxhNewFast; - LZ4_streamDecode_t decodeStateSafe, decodeStateFast; - const U32 maxMessageSizeLog = 10; - const U32 maxMessageSizeMask = (1< ringBufferSize) rNext = 0; - if (dNext + messageSize > dBufferSize) dNext = 0; - } } - } - - DISPLAYLEVEL(3, "LZ4_initStreamHC with multiple valid alignments : "); - { typedef struct { - LZ4_streamHC_t hc1; - LZ4_streamHC_t hc2; - char c; - LZ4_streamHC_t hc3; - } shct; - shct* const shc = (shct*)malloc(sizeof(*shc)); - assert(shc != NULL); - memset(shc, 0, sizeof(*shc)); - DISPLAYLEVEL(4, "hc1(%p) hc2(%p) hc3(%p) size(0x%x): ", - &(shc->hc1), &(shc->hc2), &(shc->hc3), (unsigned)sizeof(LZ4_streamHC_t)); - FUZ_CHECKTEST( LZ4_initStreamHC(&(shc->hc1), sizeof(shc->hc1)) == NULL, "hc1 (%p) failed init", &(shc->hc1) ); - FUZ_CHECKTEST( LZ4_initStreamHC(&(shc->hc2), sizeof(shc->hc2)) == NULL, "hc2 (%p) failed init", &(shc->hc2) ); - FUZ_CHECKTEST( LZ4_initStreamHC(&(shc->hc3), sizeof(shc->hc3)) == NULL, "hc3 (%p) failed init", &(shc->hc3) ); - FUZ_CHECKTEST( LZ4_initStreamHC((char*)&(shc->hc1) + 1, sizeof(shc->hc1)) != NULL, - "hc1+1 (%p) init must fail, due to bad alignment", (char*)&(shc->hc1) + 1 ); - free(shc); - } - DISPLAYLEVEL(3, "all inits OK \n"); - - /* LZ4 HC streaming tests */ - { LZ4_streamHC_t sHC; /* statically allocated */ - int result; - LZ4_initStreamHC(&sHC, sizeof(sHC)); - - /* Allocation test */ - DISPLAYLEVEL(3, "Basic HC allocation : "); - { LZ4_streamHC_t* const sp = LZ4_createStreamHC(); - FUZ_CHECKTEST(sp==NULL, "LZ4_createStreamHC() allocation failed"); - LZ4_freeStreamHC(sp); - } - DISPLAYLEVEL(3, "OK \n"); - - /* simple HC compression test */ - DISPLAYLEVEL(3, "Simple HC round-trip : "); - { U64 const crc64 = XXH64(testInput, testCompressedSize, 0); - LZ4_setCompressionLevel(&sHC, compressionLevel); - result = LZ4_compress_HC_continue(&sHC, testInput, testCompressed, testCompressedSize, testCompressedSize-1); - FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() compression failed"); - FUZ_CHECKTEST(sHC.internal_donotuse.dirty, "Context should be clean"); - - result = LZ4_decompress_safe(testCompressed, testVerify, result, testCompressedSize); - FUZ_CHECKTEST(result!=(int)testCompressedSize, "LZ4_decompress_safe() decompression failed"); - { U64 const crcNew = XXH64(testVerify, testCompressedSize, 0); - FUZ_CHECKTEST(crc64!=crcNew, "LZ4_decompress_safe() decompression corruption"); - } } - DISPLAYLEVEL(3, "OK \n"); - - /* saveDictHC test #926 */ - DISPLAYLEVEL(3, "saveDictHC test #926 : "); - { LZ4_streamHC_t* const ctx = LZ4_initStreamHC(&sHC, sizeof(sHC)); - assert(ctx != NULL); /* ensure init is successful */ - - /* Check access violation with asan */ - FUZ_CHECKTEST( LZ4_saveDictHC(ctx, NULL, 0) != 0, - "LZ4_saveDictHC() can't save anything into (NULL,0)"); - - /* Check access violation with asan */ - { char tmp_buffer[240] = { 0 }; - FUZ_CHECKTEST( LZ4_saveDictHC(ctx, tmp_buffer, sizeof(tmp_buffer)) != 0, - "LZ4_saveDictHC() can't save anything since compression hasn't started"); - } } - DISPLAYLEVEL(3, "OK \n"); - - /* long sequence test */ - DISPLAYLEVEL(3, "Long sequence HC_destSize test : "); - { size_t const blockSize = 1 MB; - size_t const targetSize = 4116; /* size carefully selected to trigger an overflow */ - void* const block = malloc(blockSize); - void* const dstBlock = malloc(targetSize+1); - BYTE const sentinel = 101; - int srcSize; - - assert(block != NULL); assert(dstBlock != NULL); - memset(block, 0, blockSize); - ((char*)dstBlock)[targetSize] = sentinel; - - LZ4_resetStreamHC_fast(&sHC, 3); - assert(blockSize < INT_MAX); - srcSize = (int)blockSize; - assert(targetSize < INT_MAX); - result = LZ4_compress_HC_destSize(&sHC, (const char*)block, (char*)dstBlock, &srcSize, (int)targetSize, 3); - DISPLAYLEVEL(4, "cSize=%i; readSize=%i; ", result, srcSize); - FUZ_CHECKTEST(result != 4116, "LZ4_compress_HC_destSize() : " - "compression (%i->%i) must fill dstBuffer (%i) exactly", - srcSize, result, (int)targetSize); - FUZ_CHECKTEST(((char*)dstBlock)[targetSize] != sentinel, - "LZ4_compress_HC_destSize() overwrites dst buffer"); - FUZ_CHECKTEST(srcSize < 1045000, "LZ4_compress_HC_destSize() doesn't compress enough" - " (%i -> %i , expected > %i)", srcSize, result, 1045000); - - LZ4_resetStreamHC_fast(&sHC, 3); /* make sure the context is clean after the test */ - free(block); - free(dstBlock); - } - DISPLAYLEVEL(3, " OK \n"); - - /* simple dictionary HC compression test */ - DISPLAYLEVEL(3, "HC dictionary compression test : "); - { U64 const crc64 = XXH64(testInput + 64 KB, testCompressedSize, 0); - LZ4_resetStreamHC_fast(&sHC, compressionLevel); - LZ4_loadDictHC(&sHC, testInput, 64 KB); - { int const cSize = LZ4_compress_HC_continue(&sHC, testInput + 64 KB, testCompressed, testCompressedSize, testCompressedSize-1); - FUZ_CHECKTEST(cSize==0, "LZ4_compressHC_limitedOutput_continue() dictionary compression failed : @return = %i", cSize); - FUZ_CHECKTEST(sHC.internal_donotuse.dirty, "Context should be clean"); - { int const dSize = LZ4_decompress_safe_usingDict(testCompressed, testVerify, cSize, testCompressedSize, testInput, 64 KB); - FUZ_CHECKTEST(dSize!=(int)testCompressedSize, "LZ4_decompress_safe() simple dictionary decompression test failed"); - } } - { U64 const crcNew = XXH64(testVerify, testCompressedSize, 0); - FUZ_CHECKTEST(crc64!=crcNew, "LZ4_decompress_safe() simple dictionary decompression test : corruption"); - } } - DISPLAYLEVEL(3, " OK \n"); - - /* multiple HC compression test with dictionary */ - { int result1, result2; - int segSize = testCompressedSize / 2; - XXH64_hash_t const crc64 = ( (void)assert((unsigned)segSize + testCompressedSize < testInputSize) , - XXH64(testInput + segSize, testCompressedSize, 0) ); - LZ4_resetStreamHC_fast(&sHC, compressionLevel); - LZ4_loadDictHC(&sHC, testInput, segSize); - result1 = LZ4_compress_HC_continue(&sHC, testInput + segSize, testCompressed, segSize, segSize -1); - FUZ_CHECKTEST(result1==0, "LZ4_compressHC_limitedOutput_continue() dictionary compression failed : result = %i", result1); - FUZ_CHECKTEST(sHC.internal_donotuse.dirty, "Context should be clean"); - result2 = LZ4_compress_HC_continue(&sHC, testInput + 2*(size_t)segSize, testCompressed+result1, segSize, segSize-1); - FUZ_CHECKTEST(result2==0, "LZ4_compressHC_limitedOutput_continue() dictionary compression failed : result = %i", result2); - FUZ_CHECKTEST(sHC.internal_donotuse.dirty, "Context should be clean"); - - result = LZ4_decompress_safe_usingDict(testCompressed, testVerify, result1, segSize, testInput, segSize); - FUZ_CHECKTEST(result!=segSize, "LZ4_decompress_safe() dictionary decompression part 1 failed"); - result = LZ4_decompress_safe_usingDict(testCompressed+result1, testVerify+segSize, result2, segSize, testInput, 2*segSize); - FUZ_CHECKTEST(result!=segSize, "LZ4_decompress_safe() dictionary decompression part 2 failed"); - { XXH64_hash_t const crcNew = XXH64(testVerify, testCompressedSize, 0); - FUZ_CHECKTEST(crc64!=crcNew, "LZ4_decompress_safe() dictionary decompression corruption"); - } } - - /* remote dictionary HC compression test */ - { U64 const crc64 = XXH64(testInput + 64 KB, testCompressedSize, 0); - LZ4_resetStreamHC_fast(&sHC, compressionLevel); - LZ4_loadDictHC(&sHC, testInput, 32 KB); - result = LZ4_compress_HC_continue(&sHC, testInput + 64 KB, testCompressed, testCompressedSize, testCompressedSize-1); - FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() remote dictionary failed : result = %i", result); - FUZ_CHECKTEST(sHC.internal_donotuse.dirty, "Context should be clean"); - - result = LZ4_decompress_safe_usingDict(testCompressed, testVerify, result, testCompressedSize, testInput, 32 KB); - FUZ_CHECKTEST(result!=(int)testCompressedSize, "LZ4_decompress_safe_usingDict() decompression failed following remote dictionary HC compression test"); - { U64 const crcNew = XXH64(testVerify, testCompressedSize, 0); - FUZ_CHECKTEST(crc64!=crcNew, "LZ4_decompress_safe_usingDict() decompression corruption"); - } } - - /* multiple HC compression with ext. dictionary */ - { XXH64_state_t crcOrigState; - XXH64_state_t crcNewState; - const char* dict = testInput + 3; - size_t dictSize = (FUZ_rand(&randState) & 8191); - char* dst = testVerify; - - size_t segStart = dictSize + 7; - size_t segSize = (FUZ_rand(&randState) & 8191); - int segNb = 1; - - LZ4_resetStreamHC_fast(&sHC, compressionLevel); - LZ4_loadDictHC(&sHC, dict, (int)dictSize); - - XXH64_reset(&crcOrigState, 0); - XXH64_reset(&crcNewState, 0); - - while (segStart + segSize < testInputSize) { - XXH64_hash_t crcOrig; - XXH64_update(&crcOrigState, testInput + segStart, segSize); - crcOrig = XXH64_digest(&crcOrigState); - assert(segSize <= INT_MAX); - result = LZ4_compress_HC_continue(&sHC, testInput + segStart, testCompressed, (int)segSize, LZ4_compressBound((int)segSize)); - FUZ_CHECKTEST(result==0, "LZ4_compressHC_limitedOutput_continue() dictionary compression failed : result = %i", result); - FUZ_CHECKTEST(sHC.internal_donotuse.dirty, "Context should be clean"); - - result = LZ4_decompress_safe_usingDict(testCompressed, dst, result, (int)segSize, dict, (int)dictSize); - FUZ_CHECKTEST(result!=(int)segSize, "LZ4_decompress_safe_usingDict() dictionary decompression part %i failed", (int)segNb); - XXH64_update(&crcNewState, dst, segSize); - { U64 const crcNew = XXH64_digest(&crcNewState); - if (crcOrig != crcNew) FUZ_findDiff(dst, testInput+segStart); - FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe_usingDict() part %i corruption", segNb); - } - - dict = dst; - dictSize = segSize; - - dst += segSize + 1; - segNb ++; - - segStart += segSize + (FUZ_rand(&randState) & 0xF) + 1; - segSize = (FUZ_rand(&randState) & 8191); - } } - - /* ring buffer test */ - { XXH64_state_t xxhOrig; - XXH64_state_t xxhNewSafe, xxhNewFast; - LZ4_streamDecode_t decodeStateSafe, decodeStateFast; - const U32 maxMessageSizeLog = 10; - const U32 maxMessageSizeMask = (1< ringBufferSize) rNext = 0; - if (dNext + messageSize > dBufferSize) dNext = 0; - } - } - - /* Ring buffer test : Non synchronized decoder */ - /* This test uses minimum amount of memory required to setup a decoding ring buffer - * while being unsynchronized with encoder - * (no assumption done on how the data is encoded, it just follows LZ4 format specification). - * This size is documented in lz4.h, and is LZ4_decoderRingBufferSize(maxBlockSize). - */ - { XXH64_state_t xxhOrig; - XXH64_state_t xxhNewSafe, xxhNewFast; - XXH64_hash_t crcOrig; - LZ4_streamDecode_t decodeStateSafe, decodeStateFast; - const int maxMessageSizeLog = 12; - const int maxMessageSize = 1 << maxMessageSizeLog; - const int maxMessageSizeMask = maxMessageSize - 1; - int messageSize; - U32 totalMessageSize = 0; - const int dBufferSize = LZ4_decoderRingBufferSize(maxMessageSize); - char* const ringBufferSafe = testVerify; - char* const ringBufferFast = testVerify + dBufferSize + 1; /* used by LZ4_decompress_fast_continue */ - int iNext = 0; - int dNext = 0; - int compressedSize; - - assert((size_t)dBufferSize * 2 + 1 < testInputSize); /* space used by ringBufferSafe and ringBufferFast */ - XXH64_reset(&xxhOrig, 0); - XXH64_reset(&xxhNewSafe, 0); - XXH64_reset(&xxhNewFast, 0); - LZ4_resetStreamHC_fast(&sHC, compressionLevel); - LZ4_setStreamDecode(&decodeStateSafe, NULL, 0); - LZ4_setStreamDecode(&decodeStateFast, NULL, 0); - -#define BSIZE1 (dBufferSize - (maxMessageSize-1)) - - /* first block */ - messageSize = BSIZE1; /* note : we cheat a bit here, in theory no message should be > maxMessageSize. We just want to fill the decoding ring buffer once. */ - XXH64_update(&xxhOrig, testInput + iNext, (size_t)messageSize); - crcOrig = XXH64_digest(&xxhOrig); - - compressedSize = LZ4_compress_HC_continue(&sHC, testInput + iNext, testCompressed, messageSize, testCompressedSize-ringBufferSize); - FUZ_CHECKTEST(compressedSize==0, "LZ4_compress_HC_continue() compression failed"); - FUZ_CHECKTEST(sHC.internal_donotuse.dirty, "Context should be clean"); - - result = LZ4_decompress_safe_continue(&decodeStateSafe, testCompressed, ringBufferSafe + dNext, compressedSize, messageSize); - FUZ_CHECKTEST(result!=messageSize, "64K D.ringBuffer : LZ4_decompress_safe_continue() test failed"); - - XXH64_update(&xxhNewSafe, ringBufferSafe + dNext, (size_t)messageSize); - { U64 const crcNew = XXH64_digest(&xxhNewSafe); - FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe_continue() decompression corruption"); } - - result = LZ4_decompress_fast_continue(&decodeStateFast, testCompressed, ringBufferFast + dNext, messageSize); - FUZ_CHECKTEST(result!=compressedSize, "64K D.ringBuffer : LZ4_decompress_fast_continue() test failed"); - - XXH64_update(&xxhNewFast, ringBufferFast + dNext, (size_t)messageSize); - { U64 const crcNew = XXH64_digest(&xxhNewFast); - FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_fast_continue() decompression corruption"); } - - /* prepare second message */ - dNext += messageSize; - assert(messageSize >= 0); - totalMessageSize += (unsigned)messageSize; - messageSize = maxMessageSize; - iNext = BSIZE1+1; - assert(BSIZE1 >= 65535); - memcpy(testInput + iNext, testInput + (BSIZE1-65535), messageSize); /* will generate a match at max distance == 65535 */ - FUZ_CHECKTEST(dNext+messageSize <= dBufferSize, "Ring buffer test : second message should require restarting from beginning"); - dNext = 0; - - while (totalMessageSize < 9 MB) { - XXH64_update(&xxhOrig, testInput + iNext, (size_t)messageSize); - crcOrig = XXH64_digest(&xxhOrig); - - compressedSize = LZ4_compress_HC_continue(&sHC, testInput + iNext, testCompressed, messageSize, testCompressedSize-ringBufferSize); - FUZ_CHECKTEST(compressedSize==0, "LZ4_compress_HC_continue() compression failed"); - FUZ_CHECKTEST(sHC.internal_donotuse.dirty, "Context should be clean"); - DISPLAYLEVEL(5, "compressed %i bytes to %i bytes \n", messageSize, compressedSize); - - /* test LZ4_decompress_safe_continue */ - assert(dNext < dBufferSize); - assert(dBufferSize - dNext >= maxMessageSize); - result = LZ4_decompress_safe_continue(&decodeStateSafe, - testCompressed, ringBufferSafe + dNext, - compressedSize, dBufferSize - dNext); /* works without knowing messageSize, under assumption that messageSize <= maxMessageSize */ - FUZ_CHECKTEST(result!=messageSize, "D.ringBuffer : LZ4_decompress_safe_continue() test failed"); - XXH64_update(&xxhNewSafe, ringBufferSafe + dNext, (size_t)messageSize); - { U64 const crcNew = XXH64_digest(&xxhNewSafe); - if (crcOrig != crcNew) FUZ_findDiff(testInput + iNext, ringBufferSafe + dNext); - FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_safe_continue() decompression corruption during D.ringBuffer test"); - } - - /* test LZ4_decompress_fast_continue in its own buffer ringBufferFast */ - result = LZ4_decompress_fast_continue(&decodeStateFast, testCompressed, ringBufferFast + dNext, messageSize); - FUZ_CHECKTEST(result!=compressedSize, "D.ringBuffer : LZ4_decompress_fast_continue() test failed"); - XXH64_update(&xxhNewFast, ringBufferFast + dNext, (size_t)messageSize); - { U64 const crcNew = XXH64_digest(&xxhNewFast); - if (crcOrig != crcNew) FUZ_findDiff(testInput + iNext, ringBufferFast + dNext); - FUZ_CHECKTEST(crcOrig!=crcNew, "LZ4_decompress_fast_continue() decompression corruption during D.ringBuffer test"); - } - - /* prepare next message */ - dNext += messageSize; - assert(messageSize >= 0); - totalMessageSize += (unsigned)messageSize; - messageSize = (FUZ_rand(&randState) & maxMessageSizeMask) + 1; - iNext = (FUZ_rand(&randState) & 65535); - if (dNext + maxMessageSize > dBufferSize) dNext = 0; - } - } /* Ring buffer test : Non synchronized decoder */ - } - - DISPLAYLEVEL(3, "LZ4_compress_HC_destSize : "); - /* encode congenerical sequence test for HC compressors */ - { LZ4_streamHC_t* const sHC = LZ4_createStreamHC(); - int const src_buf_size = 3 MB; - int const dst_buf_size = 6 KB; - int const payload = 0; - int const dst_step = 43; - int const dst_min_len = 33 + (FUZ_rand(&randState) % dst_step); - int const dst_max_len = 5000; - int slen, dlen; - char* sbuf1 = (char*)malloc(src_buf_size + 1); - char* sbuf2 = (char*)malloc(src_buf_size + 1); - char* dbuf1 = (char*)malloc(dst_buf_size + 1); - char* dbuf2 = (char*)malloc(dst_buf_size + 1); - - assert(sHC != NULL); - assert(dst_buf_size > dst_max_len); - if (!sbuf1 || !sbuf2 || !dbuf1 || !dbuf2) { - EXIT_MSG("not enough memory for FUZ_unitTests (destSize)"); - } - for (dlen = dst_min_len; dlen <= dst_max_len; dlen += dst_step) { - int src_len = (dlen - 10)*255 + 24; - if (src_len + 10 >= src_buf_size) break; /* END of check */ - for (slen = src_len - 3; slen <= src_len + 3; slen++) { - int srcsz1, srcsz2; - int dsz1, dsz2; - int res1, res2; - char const endchk = (char)0x88; - DISPLAYLEVEL(5, "slen = %i, ", slen); - - srcsz1 = slen; - memset(sbuf1, payload, slen); - memset(dbuf1, 0, dlen); - dbuf1[dlen] = endchk; - dsz1 = LZ4_compress_destSize(sbuf1, dbuf1, &srcsz1, dlen); - DISPLAYLEVEL(5, "LZ4_compress_destSize: %i bytes compressed into %i bytes, ", srcsz1, dsz1); - DISPLAYLEVEL(5, "last token : 0x%0X, ", dbuf1[dsz1 - 6]); - DISPLAYLEVEL(5, "last ML extra lenbyte : 0x%0X, \n", dbuf1[dsz1 - 7]); - FUZ_CHECKTEST(dbuf1[dlen] != endchk, "LZ4_compress_destSize() overwrite dst buffer !"); - FUZ_CHECKTEST(dsz1 <= 0, "LZ4_compress_destSize() compression failed"); - FUZ_CHECKTEST(dsz1 > dlen, "LZ4_compress_destSize() result larger than dst buffer !"); - FUZ_CHECKTEST(srcsz1 > slen, "LZ4_compress_destSize() read more than src buffer !"); - - res1 = LZ4_decompress_safe(dbuf1, sbuf1, dsz1, src_buf_size); - FUZ_CHECKTEST(res1 != srcsz1, "LZ4_compress_destSize() decompression failed!"); - - srcsz2 = slen; - memset(sbuf2, payload, slen); - memset(dbuf2, 0, dlen); - dbuf2[dlen] = endchk; - LZ4_resetStreamHC(sHC, compressionLevel); - dsz2 = LZ4_compress_HC_destSize(sHC, sbuf2, dbuf2, &srcsz2, dlen, compressionLevel); - DISPLAYLEVEL(5, "LZ4_compress_HC_destSize: %i bytes compressed into %i bytes, ", srcsz2, dsz2); - DISPLAYLEVEL(5, "last token : 0x%0X, ", dbuf2[dsz2 - 6]); - DISPLAYLEVEL(5, "last ML extra lenbyte : 0x%0X, \n", dbuf2[dsz2 - 7]); - FUZ_CHECKTEST(dbuf2[dlen] != endchk, "LZ4_compress_HC_destSize() overwrite dst buffer !"); - FUZ_CHECKTEST(dsz2 <= 0, "LZ4_compress_HC_destSize() compression failed"); - FUZ_CHECKTEST(dsz2 > dlen, "LZ4_compress_HC_destSize() result larger than dst buffer !"); - FUZ_CHECKTEST(srcsz2 > slen, "LZ4_compress_HC_destSize() read more than src buffer !"); - FUZ_CHECKTEST(dsz2 != dsz1, "LZ4_compress_HC_destSize() return incorrect result !"); - FUZ_CHECKTEST(srcsz2 != srcsz1, "LZ4_compress_HC_destSize() return incorrect src buffer size " - ": srcsz2(%i) != srcsz1(%i)", srcsz2, srcsz1); - FUZ_CHECKTEST(memcmp(dbuf2, dbuf1, (size_t)dsz2), "LZ4_compress_HC_destSize() return incorrect data into dst buffer !"); - - res2 = LZ4_decompress_safe(dbuf2, sbuf1, dsz2, src_buf_size); - FUZ_CHECKTEST(res2 != srcsz1, "LZ4_compress_HC_destSize() decompression failed!"); - - FUZ_CHECKTEST(memcmp(sbuf1, sbuf2, (size_t)res2), "LZ4_compress_HC_destSize() decompression corruption!"); - } - } - LZ4_freeStreamHC(sHC); - free(sbuf1); - free(sbuf2); - free(dbuf1); - free(dbuf2); - } - DISPLAYLEVEL(3, " OK \n"); - - - /* clean up */ - free(testInput); - free(testCompressed); - free(testVerify); - - printf("All unit tests completed successfully compressionLevel=%d \n", compressionLevel); - return; -} - - - -/* ======================================= - * CLI - * ======================================= */ - -static int FUZ_usage(const char* programName) -{ - DISPLAY( "Usage :\n"); - DISPLAY( " %s [args]\n", programName); - DISPLAY( "\n"); - DISPLAY( "Arguments :\n"); - DISPLAY( " -i# : Nb of tests (default:%i) \n", NB_ATTEMPTS); - DISPLAY( " -T# : Duration of tests, in seconds (default: use Nb of tests) \n"); - DISPLAY( " -s# : Select seed (default:prompt user)\n"); - DISPLAY( " -t# : Select starting test number (default:0)\n"); - DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT); - DISPLAY( " -v : verbose\n"); - DISPLAY( " -p : pause at the end\n"); - DISPLAY( " -h : display help and exit\n"); - return 0; -} - - -int main(int argc, const char** argv) -{ - U32 seed = 0; - int seedset = 0; - int argNb; - unsigned nbTests = NB_ATTEMPTS; - unsigned testNb = 0; - int proba = FUZ_COMPRESSIBILITY_DEFAULT; - int use_pause = 0; - const char* programName = argv[0]; - U32 duration = 0; - - /* Check command line */ - for(argNb=1; argNb='0') && (*argument<='9')) { - nbTests *= 10; - nbTests += (unsigned)(*argument - '0'); - argument++; - } - break; - - case 'T': - argument++; - nbTests = 0; duration = 0; - for (;;) { - switch(*argument) - { - case 'm': duration *= 60; argument++; continue; - case 's': - case 'n': argument++; continue; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': duration *= 10; duration += (U32)(*argument++ - '0'); continue; - } - break; - } - break; - - case 's': - argument++; - seed=0; seedset=1; - while ((*argument>='0') && (*argument<='9')) { - seed *= 10; - seed += (U32)(*argument - '0'); - argument++; - } - break; - - case 't': /* select starting test nb */ - argument++; - testNb=0; - while ((*argument>='0') && (*argument<='9')) { - testNb *= 10; - testNb += (unsigned)(*argument - '0'); - argument++; - } - break; - - case 'P': /* change probability */ - argument++; - proba=0; - while ((*argument>='0') && (*argument<='9')) { - proba *= 10; - proba += *argument - '0'; - argument++; - } - if (proba<0) proba=0; - if (proba>100) proba=100; - break; - default: ; - } - } - } - } - - printf("Starting LZ4 fuzzer (%i-bits, v%s)\n", (int)(sizeof(size_t)*8), LZ4_versionString()); - - if (!seedset) { - time_t const t = time(NULL); - U32 const h = XXH32(&t, sizeof(t), 1); - seed = h % 10000; - } - printf("Seed = %u\n", seed); - - if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) printf("Compressibility : %i%%\n", proba); - - if ((seedset==0) && (testNb==0)) { FUZ_unitTests(LZ4HC_CLEVEL_DEFAULT); FUZ_unitTests(LZ4HC_CLEVEL_OPT_MIN); } - - nbTests += (nbTests==0); /* avoid zero */ - - { int const result = FUZ_test(seed, nbTests, testNb, ((double)proba) / 100, duration); - if (use_pause) { - DISPLAY("press enter ... \n"); - (void)getchar(); - } - return result; - } -} diff --git a/ta6ob/lz4/tests/roundTripTest.c b/ta6ob/lz4/tests/roundTripTest.c deleted file mode 100644 index 2d34451..0000000 --- a/ta6ob/lz4/tests/roundTripTest.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under both the BSD-style license (found in the - * LICENSE file in the root directory of this source tree) and the GPLv2 (found - * in the COPYING file in the root directory of this source tree). - * You may select, at your option, one of the above-listed licenses. - */ - -/* - * This program takes a file in input, - * performs an LZ4 round-trip test (compress + decompress) - * compares the result with original - * and generates an abort() on corruption detection, - * in order for afl to register the event as a crash. -*/ - - -/*=========================================== -* Tuning Constant -*==========================================*/ -#ifndef MIN_CLEVEL -# define MIN_CLEVEL (int)(-5) -#endif - - - -/*=========================================== -* Dependencies -*==========================================*/ -#include /* size_t */ -#include /* malloc, free, exit */ -#include /* fprintf */ -#include /* strcmp */ -#include -#include /* stat */ -#include /* stat */ -#include "xxhash.h" - -#include "lz4.h" -#include "lz4hc.h" - - -/*=========================================== -* Macros -*==========================================*/ -#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) - -#define MSG(...) fprintf(stderr, __VA_ARGS__) - -#define CONTROL_MSG(c, ...) { \ - if ((c)) { \ - MSG(__VA_ARGS__); \ - MSG(" \n"); \ - abort(); \ - } \ -} - - -static size_t checkBuffers(const void* buff1, const void* buff2, size_t buffSize) -{ - const char* const ip1 = (const char*)buff1; - const char* const ip2 = (const char*)buff2; - size_t pos; - - for (pos=0; pos= LZ4_compressBound(srcSize)` - * for compression to be guaranteed to work */ -static void roundTripTest(void* resultBuff, size_t resultBuffCapacity, - void* compressedBuff, size_t compressedBuffCapacity, - const void* srcBuff, size_t srcSize, - int clevel) -{ - int const proposed_clevel = clevel ? clevel : select_clevel(srcBuff, srcSize); - int const selected_clevel = proposed_clevel < 0 ? -proposed_clevel : proposed_clevel; /* if level < 0, it becomes an accelearion value */ - compressFn compress = selected_clevel >= LZ4HC_CLEVEL_MIN ? LZ4_compress_HC : LZ4_compress_fast; - int const cSize = compress((const char*)srcBuff, (char*)compressedBuff, (int)srcSize, (int)compressedBuffCapacity, selected_clevel); - CONTROL_MSG(cSize == 0, "Compression error !"); - - { int const dSize = LZ4_decompress_safe((const char*)compressedBuff, (char*)resultBuff, cSize, (int)resultBuffCapacity); - CONTROL_MSG(dSize < 0, "Decompression detected an error !"); - CONTROL_MSG(dSize != (int)srcSize, "Decompression corruption error : wrong decompressed size !"); - } - - /* check potential content corruption error */ - assert(resultBuffCapacity >= srcSize); - { size_t const errorPos = checkBuffers(srcBuff, resultBuff, srcSize); - CONTROL_MSG(errorPos != srcSize, - "Silent decoding corruption, at pos %u !!!", - (unsigned)errorPos); - } - -} - -static void roundTripCheck(const void* srcBuff, size_t srcSize, int clevel) -{ - size_t const cBuffSize = LZ4_compressBound((int)srcSize); - void* const cBuff = malloc(cBuffSize); - void* const rBuff = malloc(cBuffSize); - - if (!cBuff || !rBuff) { - fprintf(stderr, "not enough memory ! \n"); - exit(1); - } - - roundTripTest(rBuff, cBuffSize, - cBuff, cBuffSize, - srcBuff, srcSize, - clevel); - - free(rBuff); - free(cBuff); -} - - -static size_t getFileSize(const char* infilename) -{ - int r; -#if defined(_MSC_VER) - struct _stat64 statbuf; - r = _stat64(infilename, &statbuf); - if (r || !(statbuf.st_mode & S_IFREG)) return 0; /* No good... */ -#else - struct stat statbuf; - r = stat(infilename, &statbuf); - if (r || !S_ISREG(statbuf.st_mode)) return 0; /* No good... */ -#endif - return (size_t)statbuf.st_size; -} - - -static int isDirectory(const char* infilename) -{ - int r; -#if defined(_MSC_VER) - struct _stat64 statbuf; - r = _stat64(infilename, &statbuf); - if (!r && (statbuf.st_mode & _S_IFDIR)) return 1; -#else - struct stat statbuf; - r = stat(infilename, &statbuf); - if (!r && S_ISDIR(statbuf.st_mode)) return 1; -#endif - return 0; -} - - -/** loadFile() : - * requirement : `buffer` size >= `fileSize` */ -static void loadFile(void* buffer, const char* fileName, size_t fileSize) -{ - FILE* const f = fopen(fileName, "rb"); - if (isDirectory(fileName)) { - MSG("Ignoring %s directory \n", fileName); - exit(2); - } - if (f==NULL) { - MSG("Impossible to open %s \n", fileName); - exit(3); - } - { size_t const readSize = fread(buffer, 1, fileSize, f); - if (readSize != fileSize) { - MSG("Error reading %s \n", fileName); - exit(5); - } } - fclose(f); -} - - -static void fileCheck(const char* fileName, int clevel) -{ - size_t const fileSize = getFileSize(fileName); - void* const buffer = malloc(fileSize + !fileSize /* avoid 0 */); - if (!buffer) { - MSG("not enough memory \n"); - exit(4); - } - loadFile(buffer, fileName, fileSize); - roundTripCheck(buffer, fileSize, clevel); - free (buffer); -} - - -int bad_usage(const char* exeName) -{ - MSG(" \n"); - MSG("bad usage: \n"); - MSG(" \n"); - MSG("%s [Options] fileName \n", exeName); - MSG(" \n"); - MSG("Options: \n"); - MSG("-# : use #=[0-9] compression level (default:0 == random) \n"); - return 1; -} - - -int main(int argCount, const char** argv) -{ - const char* const exeName = argv[0]; - int argNb = 1; - int clevel = 0; - - assert(argCount >= 1); - if (argCount < 2) return bad_usage(exeName); - - if (argv[1][0] == '-') { - clevel = argv[1][1] - '0'; - argNb = 2; - } - - if (argNb >= argCount) return bad_usage(exeName); - - fileCheck(argv[argNb], clevel); - MSG("no pb detected \n"); - return 0; -} diff --git a/ta6ob/lz4/tests/test-lz4-list.py b/ta6ob/lz4/tests/test-lz4-list.py deleted file mode 100644 index ce89757..0000000 --- a/ta6ob/lz4/tests/test-lz4-list.py +++ /dev/null @@ -1,282 +0,0 @@ -#! /usr/bin/env python3 -import subprocess -import time -import glob -import os -import tempfile -import unittest - -SIZES = [3, 11] # Always 2 sizes -MIB = 1048576 -LZ4 = os.path.dirname(os.path.realpath(__file__)) + "/../lz4" -if not os.path.exists(LZ4): - LZ4 = os.path.dirname(os.path.realpath(__file__)) + "/../programs/lz4" -TEMP = tempfile.gettempdir() - - -class NVerboseFileInfo(object): - def __init__(self, line_in): - self.line = line_in - splitlines = line_in.split() - if len(splitlines) != 7: - errout("Unexpected line: {}".format(line_in)) - self.frames, self.type, self.block, self.compressed, self.uncompressed, self.ratio, self.filename = splitlines - self.exp_unc_size = 0 - # Get real file sizes - if "concat-all" in self.filename or "2f--content-size" in self.filename: - for i in SIZES: - self.exp_unc_size += os.path.getsize("{}/test_list_{}M".format(TEMP, i)) - else: - uncompressed_filename = self.filename.split("-")[0] - self.exp_unc_size += os.path.getsize("{}/{}".format(TEMP, uncompressed_filename)) - self.exp_comp_size = os.path.getsize("{}/{}".format(TEMP, self.filename)) - - -class TestNonVerbose(unittest.TestCase): - @classmethod - def setUpClass(self): - self.nvinfo_list = [] - for i, line in enumerate(execute("{} --list -m {}/test_list_*.lz4".format(LZ4, TEMP), print_output=True)): - if i > 0: - self.nvinfo_list.append(NVerboseFileInfo(line)) - - def test_frames(self): - all_concat_frames = 0 - all_concat_index = None - for i, nvinfo in enumerate(self.nvinfo_list): - if "concat-all" in nvinfo.filename: - all_concat_index = i - elif "2f--content-size" in nvinfo.filename: - self.assertEqual("2", nvinfo.frames, nvinfo.line) - all_concat_frames += 2 - else: - self.assertEqual("1", nvinfo.frames, nvinfo.line) - all_concat_frames += 1 - self.assertNotEqual(None, all_concat_index, "Couldn't find concat-all file index.") - self.assertEqual(self.nvinfo_list[all_concat_index].frames, str(all_concat_frames), self.nvinfo_list[all_concat_index].line) - - def test_frame_types(self): - for nvinfo in self.nvinfo_list: - if "-lz4f-" in nvinfo.filename: - self.assertEqual(nvinfo.type, "LZ4Frame", nvinfo.line) - elif "-legc-" in nvinfo.filename: - self.assertEqual(nvinfo.type, "LegacyFrame", nvinfo.line) - elif "-skip-" in nvinfo.filename: - self.assertEqual(nvinfo.type, "SkippableFrame", nvinfo.line) - - def test_block(self): - for nvinfo in self.nvinfo_list: - # if "-leg" in nvinfo.filename or "-skip" in nvinfo.filename: - # self.assertEqual(nvinfo.block, "-", nvinfo.line) - if "--BD" in nvinfo.filename: - self.assertRegex(nvinfo.block, "^B[0-9]+D$", nvinfo.line) - elif "--BI" in nvinfo.filename: - self.assertRegex(nvinfo.block, "^B[0-9]+I$", nvinfo.line) - - def test_compressed_size(self): - for nvinfo in self.nvinfo_list: - self.assertEqual(nvinfo.compressed, to_human(nvinfo.exp_comp_size), nvinfo.line) - - def test_ratio(self): - for nvinfo in self.nvinfo_list: - if "--content-size" in nvinfo.filename: - self.assertEqual(nvinfo.ratio, "{:.2f}%".format(float(nvinfo.exp_comp_size) / float(nvinfo.exp_unc_size) * 100), nvinfo.line) - - def test_uncompressed_size(self): - for nvinfo in self.nvinfo_list: - if "--content-size" in nvinfo.filename: - self.assertEqual(nvinfo.uncompressed, to_human(nvinfo.exp_unc_size), nvinfo.line) - - -class VerboseFileInfo(object): - def __init__(self, lines): - # Parse lines - self.frame_list = [] - self.file_frame_map = [] - for i, line in enumerate(lines): - if i == 0: - self.filename = line - continue - elif i == 1: - # Skip header - continue - frame_info = dict(zip(["frame", "type", "block", "checksum", "compressed", "uncompressed", "ratio"], line.split())) - frame_info["line"] = line - self.frame_list.append(frame_info) - - -class TestVerbose(unittest.TestCase): - @classmethod - def setUpClass(self): - # Even do we're listing 2 files to test multiline working as expected. - # we're only really interested in testing the output of the concat-all file. - self.vinfo_list = [] - start = end = 0 - output = execute("{} --list -m -v {}/test_list_concat-all.lz4 {}/test_list_*M-lz4f-2f--content-size.lz4".format(LZ4, TEMP, TEMP), print_output=True) - for i, line in enumerate(output): - if line.startswith("test_list"): - if start != 0 and end != 0: - self.vinfo_list.append(VerboseFileInfo(output[start:end])) - start = i - if not line: - end = i - self.vinfo_list.append(VerboseFileInfo(output[start:end])) - # Populate file_frame_map as a reference of the expected info - concat_file_list = glob.glob("/tmp/test_list_[!concat]*.lz4") - # One of the files has 2 frames so duplicate it in this list to map each frame 1 to a single file - for i, filename in enumerate(concat_file_list): - if "2f--content-size" in filename: - concat_file_list.insert(i, filename) - break - self.cvinfo = self.vinfo_list[0] - self.cvinfo.file_frame_map = concat_file_list - self.cvinfo.compressed_size = os.path.getsize("{}/test_list_concat-all.lz4".format(TEMP)) - - def test_filename(self): - for i, vinfo in enumerate(self.vinfo_list): - self.assertRegex(vinfo.filename, "^test_list_.*({}/{})".format(i + 1, len(self.vinfo_list))) - - def test_frame_number(self): - for vinfo in self.vinfo_list: - for i, frame_info in enumerate(vinfo.frame_list): - self.assertEqual(frame_info["frame"], str(i + 1), frame_info["line"]) - - def test_frame_type(self): - for i, frame_info in enumerate(self.cvinfo.frame_list): - if "-lz4f-" in self.cvinfo.file_frame_map[i]: - self.assertEqual(self.cvinfo.frame_list[i]["type"], "LZ4Frame", self.cvinfo.frame_list[i]["line"]) - elif "-legc-" in self.cvinfo.file_frame_map[i]: - self.assertEqual(self.cvinfo.frame_list[i]["type"], "LegacyFrame", self.cvinfo.frame_list[i]["line"]) - elif "-skip-" in self.cvinfo.file_frame_map[i]: - self.assertEqual(self.cvinfo.frame_list[i]["type"], "SkippableFrame", self.cvinfo.frame_list[i]["line"]) - - def test_block(self): - for i, frame_info in enumerate(self.cvinfo.frame_list): - if "--BD" in self.cvinfo.file_frame_map[i]: - self.assertRegex(self.cvinfo.frame_list[i]["block"], "^B[0-9]+D$", self.cvinfo.frame_list[i]["line"]) - elif "--BI" in self.cvinfo.file_frame_map[i]: - self.assertEqual(self.cvinfo.frame_list[i]["block"], "^B[0-9]+I$", self.cvinfo.frame_list[i]["line"]) - - def test_checksum(self): - for i, frame_info in enumerate(self.cvinfo.frame_list): - if "-lz4f-" in self.cvinfo.file_frame_map[i] and "--no-frame-crc" not in self.cvinfo.file_frame_map[i]: - self.assertEqual(self.cvinfo.frame_list[i]["checksum"], "XXH32", self.cvinfo.frame_list[i]["line"]) - - def test_compressed(self): - total = 0 - for i, frame_info in enumerate(self.cvinfo.frame_list): - if "-2f-" not in self.cvinfo.file_frame_map[i]: - expected_size = os.path.getsize(self.cvinfo.file_frame_map[i]) - self.assertEqual(self.cvinfo.frame_list[i]["compressed"], str(expected_size), self.cvinfo.frame_list[i]["line"]) - total += int(self.cvinfo.frame_list[i]["compressed"]) - self.assertEqual(total, self.cvinfo.compressed_size, "Expected total sum ({}) to match {} filesize".format(total, self.cvinfo.filename)) - - def test_uncompressed(self): - for i, frame_info in enumerate(self.cvinfo.frame_list): - ffm = self.cvinfo.file_frame_map[i] - if "-2f-" not in ffm and "--content-size" in ffm: - expected_size_unc = int(ffm[ffm.rindex("_") + 1:ffm.index("M")]) * 1048576 - self.assertEqual(self.cvinfo.frame_list[i]["uncompressed"], str(expected_size_unc), self.cvinfo.frame_list[i]["line"]) - - def test_ratio(self): - for i, frame_info in enumerate(self.cvinfo.frame_list): - if "--content-size" in self.cvinfo.file_frame_map[i]: - self.assertEqual(self.cvinfo.frame_list[i]['ratio'], - "{:.2f}%".format(float(self.cvinfo.frame_list[i]['compressed']) / float(self.cvinfo.frame_list[i]['uncompressed']) * 100), - self.cvinfo.frame_list[i]["line"]) - - -def to_human(size): - for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']: - if size < 1024.0: - break - size /= 1024.0 - return "{:.2f}{}".format(size, unit) - - -def log(text): - print(time.strftime("%Y/%m/%d %H:%M:%S") + ' - ' + text) - - -def errout(text, err=1): - log(text) - exit(err) - - -def execute(command, print_command=True, print_output=False, print_error=True, param_shell=True): - if os.environ.get('QEMU_SYS'): - command = "{} {}".format(os.environ['QEMU_SYS'], command) - if print_command: - log("> " + command) - popen = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=param_shell) - stdout_lines, stderr_lines = popen.communicate() - stderr_lines = stderr_lines.decode("utf-8") - stdout_lines = stdout_lines.decode("utf-8") - if print_output: - if stdout_lines: - print(stdout_lines) - if stderr_lines: - print(stderr_lines) - if popen.returncode is not None and popen.returncode != 0: - if stderr_lines and not print_output and print_error: - print(stderr_lines) - errout("Failed to run: {}\n".format(command, stdout_lines + stderr_lines)) - return (stdout_lines + stderr_lines).splitlines() - - -def cleanup(silent=False): - for f in glob.glob("{}/test_list*".format(TEMP)): - if not silent: - log("Deleting {}".format(f)) - os.unlink(f) - - -def datagen(file_name, size): - non_sparse_size = size // 2 - sparse_size = size - non_sparse_size - with open(file_name, "wb") as f: - f.seek(sparse_size) - f.write(os.urandom(non_sparse_size)) - - -def generate_files(): - # file format ~ test_list-f.lz4 ~ - # Generate LZ4Frames - for i in SIZES: - filename = "{}/test_list_{}M".format(TEMP, i) - log("Generating {}".format(filename)) - datagen(filename, i * MIB) - for j in ["--content-size", "-BI", "-BD", "-BX", "--no-frame-crc"]: - lz4file = "{}-lz4f-1f{}.lz4".format(filename, j) - execute("{} {} {} {}".format(LZ4, j, filename, lz4file)) - # Generate skippable frames - lz4file = "{}-skip-1f.lz4".format(filename) - skipsize = i * 1024 - skipbytes = bytes([80, 42, 77, 24]) + skipsize.to_bytes(4, byteorder='little', signed=False) - with open(lz4file, 'wb') as f: - f.write(skipbytes) - f.write(os.urandom(skipsize)) - # Generate legacy frames - lz4file = "{}-legc-1f.lz4".format(filename) - execute("{} -l {} {}".format(LZ4, filename, lz4file)) - - # Concatenate --content-size files - file_list = glob.glob("{}/test_list_*-lz4f-1f--content-size.lz4".format(TEMP)) - with open("{}/test_list_{}M-lz4f-2f--content-size.lz4".format(TEMP, sum(SIZES)), 'ab') as outfile: - for fname in file_list: - with open(fname, 'rb') as infile: - outfile.write(infile.read()) - - # Concatenate all files - file_list = glob.glob("{}/test_list_*.lz4".format(TEMP)) - with open("{}/test_list_concat-all.lz4".format(TEMP), 'ab') as outfile: - for fname in file_list: - with open(fname, 'rb') as infile: - outfile.write(infile.read()) - - -if __name__ == '__main__': - cleanup() - generate_files() - unittest.main(verbosity=2, exit=False) - cleanup(silent=True) diff --git a/ta6ob/lz4/tests/test-lz4-speed.py b/ta6ob/lz4/tests/test-lz4-speed.py deleted file mode 100644 index ca8f010..0000000 --- a/ta6ob/lz4/tests/test-lz4-speed.py +++ /dev/null @@ -1,351 +0,0 @@ -#! /usr/bin/env python3 - -# -# Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. -# All rights reserved. -# -# This source code is licensed under the BSD-style license found in the -# LICENSE file in the root directory of this source tree. An additional grant -# of patent rights can be found in the PATENTS file in the same directory. -# - -# Limitations: -# - doesn't support filenames with spaces -# - dir1/lz4 and dir2/lz4 will be merged in a single results file - -import argparse -import os -import string -import subprocess -import time -import traceback -import hashlib - -script_version = 'v1.7.2 (2016-11-08)' -default_repo_url = 'https://github.com/lz4/lz4.git' -working_dir_name = 'speedTest' -working_path = os.getcwd() + '/' + working_dir_name # /path/to/lz4/tests/speedTest -clone_path = working_path + '/' + 'lz4' # /path/to/lz4/tests/speedTest/lz4 -email_header = 'lz4_speedTest' -pid = str(os.getpid()) -verbose = False -clang_version = "unknown" -gcc_version = "unknown" -args = None - - -def hashfile(hasher, fname, blocksize=65536): - with open(fname, "rb") as f: - for chunk in iter(lambda: f.read(blocksize), b""): - hasher.update(chunk) - return hasher.hexdigest() - - -def log(text): - print(time.strftime("%Y/%m/%d %H:%M:%S") + ' - ' + text) - - -def execute(command, print_command=True, print_output=False, print_error=True, param_shell=True): - if print_command: - log("> " + command) - popen = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=param_shell, cwd=execute.cwd) - stdout_lines, stderr_lines = popen.communicate(timeout=args.timeout) - stderr_lines = stderr_lines.decode("utf-8") - stdout_lines = stdout_lines.decode("utf-8") - if print_output: - if stdout_lines: - print(stdout_lines) - if stderr_lines: - print(stderr_lines) - if popen.returncode is not None and popen.returncode != 0: - if stderr_lines and not print_output and print_error: - print(stderr_lines) - raise RuntimeError(stdout_lines + stderr_lines) - return (stdout_lines + stderr_lines).splitlines() -execute.cwd = None - - -def does_command_exist(command): - try: - execute(command, verbose, False, False) - except Exception: - return False - return True - - -def send_email(emails, topic, text, have_mutt, have_mail): - logFileName = working_path + '/' + 'tmpEmailContent' - with open(logFileName, "w") as myfile: - myfile.writelines(text) - myfile.close() - if have_mutt: - execute('mutt -s "' + topic + '" ' + emails + ' < ' + logFileName, verbose) - elif have_mail: - execute('mail -s "' + topic + '" ' + emails + ' < ' + logFileName, verbose) - else: - log("e-mail cannot be sent (mail or mutt not found)") - - -def send_email_with_attachments(branch, commit, last_commit, args, text, results_files, - logFileName, have_mutt, have_mail): - with open(logFileName, "w") as myfile: - myfile.writelines(text) - myfile.close() - email_topic = '[%s:%s] Warning for %s:%s last_commit=%s speed<%s ratio<%s' \ - % (email_header, pid, branch, commit, last_commit, - args.lowerLimit, args.ratioLimit) - if have_mutt: - execute('mutt -s "' + email_topic + '" ' + args.emails + ' -a ' + results_files - + ' < ' + logFileName) - elif have_mail: - execute('mail -s "' + email_topic + '" ' + args.emails + ' < ' + logFileName) - else: - log("e-mail cannot be sent (mail or mutt not found)") - - -def git_get_branches(): - execute('git fetch -p', verbose) - branches = execute('git branch -rl', verbose) - output = [] - for line in branches: - if ("HEAD" not in line) and ("coverity_scan" not in line) and ("gh-pages" not in line): - output.append(line.strip()) - return output - - -def git_get_changes(branch, commit, last_commit): - fmt = '--format="%h: (%an) %s, %ar"' - if last_commit is None: - commits = execute('git log -n 10 %s %s' % (fmt, commit)) - else: - commits = execute('git --no-pager log %s %s..%s' % (fmt, last_commit, commit)) - return str('Changes in %s since %s:\n' % (branch, last_commit)) + '\n'.join(commits) - - -def get_last_results(resultsFileName): - if not os.path.isfile(resultsFileName): - return None, None, None, None - commit = None - csize = [] - cspeed = [] - dspeed = [] - with open(resultsFileName, 'r') as f: - for line in f: - words = line.split() - if len(words) <= 4: # branch + commit + compilerVer + md5 - commit = words[1] - csize = [] - cspeed = [] - dspeed = [] - if (len(words) == 8) or (len(words) == 9): # results: "filename" or "XX files" - csize.append(int(words[1])) - cspeed.append(float(words[3])) - dspeed.append(float(words[5])) - return commit, csize, cspeed, dspeed - - -def benchmark_and_compare(branch, commit, last_commit, args, executableName, md5sum, compilerVersion, resultsFileName, - testFilePath, fileName, last_csize, last_cspeed, last_dspeed): - sleepTime = 30 - while os.getloadavg()[0] > args.maxLoadAvg: - log("WARNING: bench loadavg=%.2f is higher than %s, sleeping for %s seconds" - % (os.getloadavg()[0], args.maxLoadAvg, sleepTime)) - time.sleep(sleepTime) - start_load = str(os.getloadavg()) - result = execute('programs/%s -rqi5b1e%s %s' % (executableName, args.lastCLevel, testFilePath), print_output=True) - end_load = str(os.getloadavg()) - linesExpected = args.lastCLevel + 1 - if len(result) != linesExpected: - raise RuntimeError("ERROR: number of result lines=%d is different that expected %d\n%s" % (len(result), linesExpected, '\n'.join(result))) - with open(resultsFileName, "a") as myfile: - myfile.write('%s %s %s md5=%s\n' % (branch, commit, compilerVersion, md5sum)) - myfile.write('\n'.join(result) + '\n') - myfile.close() - if (last_cspeed == None): - log("WARNING: No data for comparison for branch=%s file=%s " % (branch, fileName)) - return "" - commit, csize, cspeed, dspeed = get_last_results(resultsFileName) - text = "" - for i in range(0, min(len(cspeed), len(last_cspeed))): - print("%s:%s -%d cSpeed=%6.2f cLast=%6.2f cDiff=%1.4f dSpeed=%6.2f dLast=%6.2f dDiff=%1.4f ratioDiff=%1.4f %s" % (branch, commit, i+1, cspeed[i], last_cspeed[i], cspeed[i]/last_cspeed[i], dspeed[i], last_dspeed[i], dspeed[i]/last_dspeed[i], float(last_csize[i])/csize[i], fileName)) - if (cspeed[i]/last_cspeed[i] < args.lowerLimit): - text += "WARNING: %s -%d cSpeed=%.2f cLast=%.2f cDiff=%.4f %s\n" % (executableName, i+1, cspeed[i], last_cspeed[i], cspeed[i]/last_cspeed[i], fileName) - if (dspeed[i]/last_dspeed[i] < args.lowerLimit): - text += "WARNING: %s -%d dSpeed=%.2f dLast=%.2f dDiff=%.4f %s\n" % (executableName, i+1, dspeed[i], last_dspeed[i], dspeed[i]/last_dspeed[i], fileName) - if (float(last_csize[i])/csize[i] < args.ratioLimit): - text += "WARNING: %s -%d cSize=%d last_cSize=%d diff=%.4f %s\n" % (executableName, i+1, csize[i], last_csize[i], float(last_csize[i])/csize[i], fileName) - if text: - text = args.message + ("\nmaxLoadAvg=%s load average at start=%s end=%s\n%s last_commit=%s md5=%s\n" % (args.maxLoadAvg, start_load, end_load, compilerVersion, last_commit, md5sum)) + text - return text - - -def update_config_file(branch, commit): - last_commit = None - commitFileName = working_path + "/commit_" + branch.replace("/", "_") + ".txt" - if os.path.isfile(commitFileName): - with open(commitFileName, 'r') as infile: - last_commit = infile.read() - with open(commitFileName, 'w') as outfile: - outfile.write(commit) - return last_commit - - -def double_check(branch, commit, args, executableName, md5sum, compilerVersion, resultsFileName, filePath, fileName): - last_commit, csize, cspeed, dspeed = get_last_results(resultsFileName) - if not args.dry_run: - text = benchmark_and_compare(branch, commit, last_commit, args, executableName, md5sum, compilerVersion, resultsFileName, filePath, fileName, csize, cspeed, dspeed) - if text: - log("WARNING: redoing tests for branch %s: commit %s" % (branch, commit)) - text = benchmark_and_compare(branch, commit, last_commit, args, executableName, md5sum, compilerVersion, resultsFileName, filePath, fileName, csize, cspeed, dspeed) - return text - - -def test_commit(branch, commit, last_commit, args, testFilePaths, have_mutt, have_mail): - local_branch = branch.split('/')[1] - version = local_branch.rpartition('-')[2] + '_' + commit - if not args.dry_run: - execute('make -C programs clean lz4 CC=clang MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion -DLZ4_GIT_COMMIT=%s" && ' % version + - 'mv programs/lz4 programs/lz4_clang && ' + - 'make -C programs clean lz4 lz4c32 MOREFLAGS="-DLZ4_GIT_COMMIT=%s"' % version) - md5_lz4 = hashfile(hashlib.md5(), clone_path + '/programs/lz4') - md5_lz4c32 = hashfile(hashlib.md5(), clone_path + '/programs/lz4c32') - md5_lz4_clang = hashfile(hashlib.md5(), clone_path + '/programs/lz4_clang') - print("md5(lz4)=%s\nmd5(lz4c32)=%s\nmd5(lz4_clang)=%s" % (md5_lz4, md5_lz4c32, md5_lz4_clang)) - print("gcc_version=%s clang_version=%s" % (gcc_version, clang_version)) - - logFileName = working_path + "/log_" + branch.replace("/", "_") + ".txt" - text_to_send = [] - results_files = "" - - for filePath in testFilePaths: - fileName = filePath.rpartition('/')[2] - resultsFileName = working_path + "/results_" + branch.replace("/", "_") + "_" + fileName.replace(".", "_") + ".txt" - text = double_check(branch, commit, args, 'lz4', md5_lz4, 'gcc_version='+gcc_version, resultsFileName, filePath, fileName) - if text: - text_to_send.append(text) - results_files += resultsFileName + " " - resultsFileName = working_path + "/results32_" + branch.replace("/", "_") + "_" + fileName.replace(".", "_") + ".txt" - text = double_check(branch, commit, args, 'lz4c32', md5_lz4c32, 'gcc_version='+gcc_version, resultsFileName, filePath, fileName) - if text: - text_to_send.append(text) - results_files += resultsFileName + " " - resultsFileName = working_path + "/resultsClang_" + branch.replace("/", "_") + "_" + fileName.replace(".", "_") + ".txt" - text = double_check(branch, commit, args, 'lz4_clang', md5_lz4_clang, 'clang_version='+clang_version, resultsFileName, filePath, fileName) - if text: - text_to_send.append(text) - results_files += resultsFileName + " " - if text_to_send: - send_email_with_attachments(branch, commit, last_commit, args, text_to_send, results_files, logFileName, have_mutt, have_mail) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('testFileNames', help='file or directory names list for speed benchmark') - parser.add_argument('emails', help='list of e-mail addresses to send warnings') - parser.add_argument('--message', '-m', help='attach an additional message to e-mail', default="") - parser.add_argument('--repoURL', help='changes default repository URL', default=default_repo_url) - parser.add_argument('--lowerLimit', '-l', type=float, help='send email if speed is lower than given limit', default=0.98) - parser.add_argument('--ratioLimit', '-r', type=float, help='send email if ratio is lower than given limit', default=0.999) - parser.add_argument('--maxLoadAvg', type=float, help='maximum load average to start testing', default=0.75) - parser.add_argument('--lastCLevel', type=int, help='last compression level for testing', default=5) - parser.add_argument('--sleepTime', '-s', type=int, help='frequency of repository checking in seconds', default=300) - parser.add_argument('--timeout', '-t', type=int, help='timeout for executing shell commands', default=1800) - parser.add_argument('--dry-run', dest='dry_run', action='store_true', help='not build', default=False) - parser.add_argument('--verbose', '-v', action='store_true', help='more verbose logs', default=False) - args = parser.parse_args() - verbose = args.verbose - - # check if test files are accessible - testFileNames = args.testFileNames.split() - testFilePaths = [] - for fileName in testFileNames: - fileName = os.path.expanduser(fileName) - if os.path.isfile(fileName) or os.path.isdir(fileName): - testFilePaths.append(os.path.abspath(fileName)) - else: - log("ERROR: File/directory not found: " + fileName) - exit(1) - - # check availability of e-mail senders - have_mutt = does_command_exist("mutt -h") - have_mail = does_command_exist("mail -V") - if not have_mutt and not have_mail: - log("ERROR: e-mail senders 'mail' or 'mutt' not found") - exit(1) - - clang_version = execute("clang -v 2>&1 | grep 'clang version' | sed -e 's:.*version \\([0-9.]*\\).*:\\1:' -e 's:\\.\\([0-9][0-9]\\):\\1:g'", verbose)[0]; - gcc_version = execute("gcc -dumpversion", verbose)[0]; - - if verbose: - print("PARAMETERS:\nrepoURL=%s" % args.repoURL) - print("working_path=%s" % working_path) - print("clone_path=%s" % clone_path) - print("testFilePath(%s)=%s" % (len(testFilePaths), testFilePaths)) - print("message=%s" % args.message) - print("emails=%s" % args.emails) - print("maxLoadAvg=%s" % args.maxLoadAvg) - print("lowerLimit=%s" % args.lowerLimit) - print("ratioLimit=%s" % args.ratioLimit) - print("lastCLevel=%s" % args.lastCLevel) - print("sleepTime=%s" % args.sleepTime) - print("timeout=%s" % args.timeout) - print("dry_run=%s" % args.dry_run) - print("verbose=%s" % args.verbose) - print("have_mutt=%s have_mail=%s" % (have_mutt, have_mail)) - - # clone lz4 repo if needed - if not os.path.isdir(working_path): - os.mkdir(working_path) - if not os.path.isdir(clone_path): - execute.cwd = working_path - execute('git clone ' + args.repoURL) - if not os.path.isdir(clone_path): - log("ERROR: lz4 clone not found: " + clone_path) - exit(1) - execute.cwd = clone_path - - # check if speedTest.pid already exists - pidfile = "./speedTest.pid" - if os.path.isfile(pidfile): - log("ERROR: %s already exists, exiting" % pidfile) - exit(1) - - send_email(args.emails, '[%s:%s] test-lz4-speed.py %s has been started' % (email_header, pid, script_version), args.message, have_mutt, have_mail) - with open(pidfile, 'w') as the_file: - the_file.write(pid) - - branch = "" - commit = "" - first_time = True - while True: - try: - if first_time: - first_time = False - else: - if verbose: - log("sleep for %s seconds" % args.sleepTime) - time.sleep(args.sleepTime) - loadavg = os.getloadavg()[0] - if (loadavg <= args.maxLoadAvg): - branches = git_get_branches() - for branch in branches: - commit = execute('git show -s --format=%h ' + branch, verbose)[0] - last_commit = update_config_file(branch, commit) - if commit == last_commit: - log("skipping branch %s: head %s already processed" % (branch, commit)) - else: - log("build branch %s: head %s is different from prev %s" % (branch, commit, last_commit)) - execute('git checkout -- . && git checkout ' + branch) - print(git_get_changes(branch, commit, last_commit)) - test_commit(branch, commit, last_commit, args, testFilePaths, have_mutt, have_mail) - else: - log("WARNING: main loadavg=%.2f is higher than %s" % (loadavg, args.maxLoadAvg)) - except Exception as e: - stack = traceback.format_exc() - email_topic = '[%s:%s] ERROR in %s:%s' % (email_header, pid, branch, commit) - send_email(args.emails, email_topic, stack, have_mutt, have_mail) - print(stack) - except KeyboardInterrupt: - os.unlink(pidfile) - send_email(args.emails, '[%s:%s] test-lz4-speed.py %s has been stopped' % (email_header, pid, script_version), args.message, have_mutt, have_mail) - exit(0) diff --git a/ta6ob/lz4/tests/test-lz4-versions.py b/ta6ob/lz4/tests/test-lz4-versions.py deleted file mode 100644 index d7fd199..0000000 --- a/ta6ob/lz4/tests/test-lz4-versions.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env python3 -"""Test LZ4 interoperability between versions""" - -# -# Copyright (C) 2011-present, Takayuki Matsuoka -# All rights reserved. -# GPL v2 License -# - -import glob -import subprocess -import filecmp -import os -import shutil -import sys -import hashlib - -repo_url = 'https://github.com/lz4/lz4.git' -tmp_dir_name = 'tests/versionsTest' -make_cmd = 'make' -git_cmd = 'git' -test_dat_src = 'README.md' -test_dat = 'test_dat' -head = 'v999' - -def proc(cmd_args, pipe=True, dummy=False): - if dummy: - return - if pipe: - subproc = subprocess.Popen(cmd_args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - else: - subproc = subprocess.Popen(cmd_args) - return subproc.communicate() - -def make(args, pipe=True): - return proc([make_cmd] + args, pipe) - -def git(args, pipe=True): - return proc([git_cmd] + args, pipe) - -def get_git_tags(): - stdout, stderr = git(['tag', '-l', 'r[0-9][0-9][0-9]']) - tags = stdout.decode('utf-8').split() - stdout, stderr = git(['tag', '-l', 'v[1-9].[0-9].[0-9]']) - tags += stdout.decode('utf-8').split() - return tags - -# https://stackoverflow.com/a/19711609/2132223 -def sha1_of_file(filepath): - with open(filepath, 'rb') as f: - return hashlib.sha1(f.read()).hexdigest() - -if __name__ == '__main__': - error_code = 0 - base_dir = os.getcwd() + '/..' # /path/to/lz4 - tmp_dir = base_dir + '/' + tmp_dir_name # /path/to/lz4/tests/versionsTest - clone_dir = tmp_dir + '/' + 'lz4' # /path/to/lz4/tests/versionsTest/lz4 - programs_dir = base_dir + '/programs' # /path/to/lz4/programs - os.makedirs(tmp_dir, exist_ok=True) - - # since Travis clones limited depth, we should clone full repository - if not os.path.isdir(clone_dir): - git(['clone', repo_url, clone_dir]) - - shutil.copy2(base_dir + '/' + test_dat_src, tmp_dir + '/' + test_dat) - - # Retrieve all release tags - print('Retrieve all release tags :') - os.chdir(clone_dir) - tags = [head] + get_git_tags() - print(tags); - - # Build all release lz4c and lz4c32 - for tag in tags: - os.chdir(base_dir) - dst_lz4c = '{}/lz4c.{}' .format(tmp_dir, tag) # /path/to/lz4/test/lz4test/lz4c. - dst_lz4c32 = '{}/lz4c32.{}'.format(tmp_dir, tag) # /path/to/lz4/test/lz4test/lz4c32. - if not os.path.isfile(dst_lz4c) or not os.path.isfile(dst_lz4c32) or tag == head: - if tag != head: - r_dir = '{}/{}'.format(tmp_dir, tag) # /path/to/lz4/test/lz4test/ - os.makedirs(r_dir, exist_ok=True) - os.chdir(clone_dir) - git(['--work-tree=' + r_dir, 'checkout', tag, '--', '.'], False) - os.chdir(r_dir + '/programs') # /path/to/lz4/lz4test//programs - else: - os.chdir(programs_dir) - make(['clean', 'lz4c'], False) - shutil.copy2('lz4c', dst_lz4c) - make(['clean', 'lz4c32'], False) - shutil.copy2('lz4c32', dst_lz4c32) - - # Compress test.dat by all released lz4c and lz4c32 - print('Compress test.dat by all released lz4c and lz4c32') - os.chdir(tmp_dir) - for lz4 in glob.glob("*.lz4"): - os.remove(lz4) - for tag in tags: - proc(['./lz4c.' + tag, '-1fz', test_dat, test_dat + '_1_64_' + tag + '.lz4']) - proc(['./lz4c.' + tag, '-9fz', test_dat, test_dat + '_9_64_' + tag + '.lz4']) - proc(['./lz4c32.' + tag, '-1fz', test_dat, test_dat + '_1_32_' + tag + '.lz4']) - proc(['./lz4c32.' + tag, '-9fz', test_dat, test_dat + '_9_32_' + tag + '.lz4']) - - print('Full list of compressed files') - lz4s = sorted(glob.glob('*.lz4')) - for lz4 in lz4s: - print(lz4 + ' : ' + repr(os.path.getsize(lz4))) - - # Remove duplicated .lz4 files - print('') - print('Duplicated files') - lz4s = sorted(glob.glob('*.lz4')) - for i, lz4 in enumerate(lz4s): - if not os.path.isfile(lz4): - continue - for j in range(i+1, len(lz4s)): - lz4t = lz4s[j] - if not os.path.isfile(lz4t): - continue - if filecmp.cmp(lz4, lz4t): - os.remove(lz4t) - print('{} == {}'.format(lz4, lz4t)) - - print('Enumerate only different compressed files') - lz4s = sorted(glob.glob('*.lz4')) - for lz4 in lz4s: - print(lz4 + ' : ' + repr(os.path.getsize(lz4)) + ', ' + sha1_of_file(lz4)) - - # Decompress remained .lz4 files by all released lz4c and lz4c32 - print('Decompression tests and verifications') - lz4s = sorted(glob.glob('*.lz4')) - for dec in glob.glob("*.dec"): - os.remove(dec) - for lz4 in lz4s: - print(lz4, end=" ") - for tag in tags: - print(tag, end=" ") - proc(['./lz4c.' + tag, '-df', lz4, lz4 + '_d64_' + tag + '.dec']) - proc(['./lz4c32.' + tag, '-df', lz4, lz4 + '_d32_' + tag + '.dec']) - print(' OK') # well, here, decompression has worked; but file is not yet verified - - # Compare all '.dec' files with test_dat - decs = glob.glob('*.dec') - for dec in decs: - if not filecmp.cmp(dec, test_dat): - print('ERR : ' + dec) - error_code = 1 - else: - print('OK : ' + dec) - os.remove(dec) - - if error_code != 0: - print('ERROR') - - sys.exit(error_code) diff --git a/ta6ob/lz4/tests/test_custom_block_sizes.sh b/ta6ob/lz4/tests/test_custom_block_sizes.sh deleted file mode 100755 index aba6733..0000000 --- a/ta6ob/lz4/tests/test_custom_block_sizes.sh +++ /dev/null @@ -1,72 +0,0 @@ -#/usr/bin/env sh -set -e - -LZ4=../lz4 -CHECKFRAME=./checkFrame -DATAGEN=./datagen - -failures="" - -TMPFILE=/tmp/test_custom_block_sizes.$$ -TMPFILE1=/tmp/test_custom_block_sizes1.$$ -TMPFILE2=/tmp/test_custom_block_sizes2.$$ -$DATAGEN -g12345678 > $TMPFILE1 -$DATAGEN -g12345678 > $TMPFILE2 - -echo Testing -B31 -$LZ4 -f -B31 $TMPFILE1 && failures="31 (should fail) " - -for blocksize in 32 65535 65536 -do - echo Testing -B$blocksize - $LZ4 -f -B$blocksize $TMPFILE1 - $LZ4 -f -B$blocksize $TMPFILE2 - cat $TMPFILE1.lz4 $TMPFILE2.lz4 > $TMPFILE.lz4 - $CHECKFRAME -B$blocksize -b4 $TMPFILE.lz4 || failures="$failures $blocksize " -done - -for blocksize in 65537 262143 262144 -do - echo Testing -B$blocksize - $LZ4 -f -B$blocksize $TMPFILE1 - $LZ4 -f -B$blocksize $TMPFILE2 - cat $TMPFILE1.lz4 $TMPFILE2.lz4 > $TMPFILE.lz4 - $CHECKFRAME -B$blocksize -b5 $TMPFILE.lz4 || failures="$failures $blocksize " -done - -for blocksize in 262145 1048575 1048576 -do - echo Testing -B$blocksize - $LZ4 -f -B$blocksize $TMPFILE1 - $LZ4 -f -B$blocksize $TMPFILE2 - cat $TMPFILE1.lz4 $TMPFILE2.lz4 > $TMPFILE.lz4 - $CHECKFRAME -B$blocksize -b6 $TMPFILE.lz4 || failures="$failures $blocksize " -done - -for blocksize in 1048577 4194303 4194304 -do - echo Testing -B$blocksize - $LZ4 -f -B$blocksize $TMPFILE1 - $LZ4 -f -B$blocksize $TMPFILE2 - cat $TMPFILE1.lz4 $TMPFILE2.lz4 > $TMPFILE.lz4 - $CHECKFRAME -B$blocksize -b7 $TMPFILE.lz4 || failures="$failures $blocksize " -done - -for blocksize in 4194305 10485760 -do - echo Testing -B$blocksize - $LZ4 -f -B$blocksize $TMPFILE1 - $LZ4 -f -B$blocksize $TMPFILE2 - cat $TMPFILE1.lz4 $TMPFILE2.lz4 > $TMPFILE.lz4 - $CHECKFRAME -B4194304 -b7 $TMPFILE.lz4 || failures="$failures $blocksize " -done - -rm $TMPFILE.lz4 $TMPFILE1 $TMPFILE1.lz4 $TMPFILE2 $TMPFILE2.lz4 -if [ "$failures" == "" ] -then - echo ---- All tests passed - exit 0 -else - echo ---- The following tests had failures: $failures - exit 1 -fi diff --git a/ta6ob/lz4/tests/test_install.sh b/ta6ob/lz4/tests/test_install.sh deleted file mode 100755 index 122bac5..0000000 --- a/ta6ob/lz4/tests/test_install.sh +++ /dev/null @@ -1,28 +0,0 @@ -#/usr/bin/env sh -set -e - - -make="make -C $lz4_root" -unamestr=$(uname) -if [ "$unamestr" = 'Linux' ]; then - make="make -C $lz4_root" -elif [ "$unamestr" = 'FreeBSD' -o "$unamestr" = 'OpenBSD' ]; then - make="gmake -C $lz4_root" -fi - -for cmd in install uninstall; do - for upper in DUMMY PREFIX EXEC_PREFIX LIBDIR INCLUDEDIR PKGCONFIGDIR BINDIR MANDIR MAN1DIR ; do - lower=$(echo $upper | tr '[:upper:]' '[:lower:]') - tmp_lower="$(pwd)/tmp-lower-$lower/" - tmp_upper="$(pwd)/tmp-upper-$lower/" - echo $make $cmd DESTDIR="$tmp_upper" $upper="test" - $make $cmd DESTDIR="$tmp_upper" $upper="test" >/dev/null - echo $make $cmd DESTDIR="$tmp_lower" $lower="test" - $make $cmd DESTDIR="$tmp_lower" $lower="test" >/dev/null - command diff -r "$tmp_lower" "$tmp_upper" && echo "SAME!" || false - if [ "x$cmd" = "xuninstall" ]; then - test -z "$(find "$tmp_lower" -type f)" && echo "EMPTY!" || false - rm -rf "$tmp_upper" "$tmp_lower" - fi - done -done diff --git a/ta6ob/lz4/tmp b/ta6ob/lz4/tmp deleted file mode 100644 index c97c12f..0000000 Binary files a/ta6ob/lz4/tmp and /dev/null differ diff --git a/ta6ob/lz4/tmpsparse b/ta6ob/lz4/tmpsparse deleted file mode 100644 index c97c12f..0000000 Binary files a/ta6ob/lz4/tmpsparse and /dev/null differ diff --git a/ta6ob/mats/Makefile b/ta6ob/mats/Makefile deleted file mode 100644 index 8f25aed..0000000 --- a/ta6ob/mats/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# Mf-ta6ob -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -m = ta6ob - -fsrc = foreign1.c foreign2.c foreign3.c foreign4.c -fobj = foreign1.so - -include Mf-base - -foreign1.so: ${fsrc} ../boot/$m/scheme.h - $(CC) -pthread -fPIC -shared -I${Include} -o foreign1.so ${fsrc} - -cat_flush: cat_flush.c - $(CC) -o cat_flush cat_flush.c diff --git a/ta6ob/mats/Mf-base b/ta6ob/mats/Mf-base deleted file mode 100644 index e072c4c..0000000 --- a/ta6ob/mats/Mf-base +++ /dev/null @@ -1,545 +0,0 @@ -# Mf-base -# Copyright 1984-2021 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Assumes recursive makes inherit command-line settings as in GNU make - -# Running "make" or "make all" in this directory runs the mats (test -# programs) and produces a report of bugs and errors. Unless you make -# changes to the mats or to the system, the report file report-$(conf) -# (where $(conf) is set below) will be output in the $(outdir) directory. - -# If an error or bug report occurs, refer to the offending ".mo" file -# produced by the mats and mentioned in the bug or error report to -# determine what failed. - -# Running "make allx" runs a set of mats with various settings. "make -# bullyx" runs a different, more stressful set. These targets allow make -# to run the various configurations in parallel (if so configured, e.g. -# with the -j flag). Most output from each parallel execution is directed -# to (separate) files, with status printed to stdout when testing of each -# different configuration begins and ends. In addition, each target -# concatenates the summary file from all configurations run into "summary" -# in the current directory. - -# Running make with the argument "clean" removes the .so files, .mo -# files, report files, and temporary files generated by the mats. - -# The variables below may be changed to affect how the mats are run. -# For example, "make o=2 cp0=t ctb=8192" causes the mats to be run at -# optimize level 2 with cp0 enabled and collect-trip-bytes set to 8192. - -MatsDir = $(abspath .) - -ifeq (${OS},Windows_NT) - dirsep = ; -else - dirsep = : -endif - -# Explicit ".exe" needed for WSL -ifeq ($(OS),Windows_NT) - ExeSuffix = .exe -else - ExeSuffix = -endif - -include ../c/Mf-config - -# Scheme is the scheme executable to test, SCHEMEHEAPDIRS tells -# it where to find its boot files, and CHEZSCHEMELIBDIRS tells -# it where to find libraries. -Scheme = $(abspath ../bin/$m/scheme${ExeSuffix}) -export SCHEMEHEAPDIRS=.${dirsep}$(abspath ../boot)/%m -export CHEZSCHEMELIBDIRS=. - -# Include is the directory holding scheme.h. -Include = ../boot/$m - -# patchfile is the name of a patch to be loaded while running the mats. -patchfile = - -# o is the optimize level at which the mats should be run. -o = 0 - -# p determines whether profiling is enabled: f for false, t for true. -defaultp = f -p = $(defaultp) - -# pdhtml determines whether profile-dump-html is called at end of a run: f for false, t for true. -# NB: beware of lost profile information due to mats that call profile-clear -defaultpdhtml = f -pdhtml = $(defaultpdhtml) - -# cp0 determines whether cp0 is run: f for no, t for yes -defaultcp0 = f -cp0 = $(defaultcp0) - -# eval is the evaluator to use. -defaulteval = compile -eval = $(defaulteval) - -# ctb is the value to which collect-trip-bytes is set. -defaultctb = (collect-trip-bytes) -ctb = $(defaultctb) - -# cn defines the value to which collect-notify is set: f for #f, t for #t -defaultcn = f -cn = $(defaultcn) - -# cgr is the value to which collect-generation-radix is set. -defaultcgr = (collect-generation-radix) -cgr = $(defaultcgr) - -# cmg is the value to which collect-maximum-generation is set. -defaultcmg = (collect-maximum-generation) -cmg = $(defaultcmg) - -# rmg is the value to which release-minimum-generation is set. -defaultrmg = (release-minimum-generation) -rmg = $(defaultrmg) - -# cis defines the value to which compile-interpret-simple is set: f for -# #f, t for #t -defaultcis = f -cis = $(defaultcis) - -# spi defines the value to which suppress-primitive-inlining is set: -# f for #f, t for #t -defaultspi = f -spi = $(defaultspi) - -# hci defines the value to which heap-check-interval (mat.ss) is set: -# 0 to disable, > 0 to enable -defaulthci = 0 -hci = $(defaulthci) - -# eoc determines whether object counts are enabled -defaulteoc = t -eoc = $(defaulteoc) - -# cl determines the commonization level -defaultcl = (commonization-level) -cl = $(defaultcl) - -# ecpf determines whether the compiler checks prelex flags -defaultecpf = t -ecpf = $(defaultecpf) - -# c determines whether mat coverage (.covout) files are created -defaultc = f -c = $(defaultc) - -# set of coverage files to load -coverage-files = $(abspath ../boot/$m/petite.covin ../boot/$m/scheme.covin) - -# set of mats to run -mats = primvars 3 4 5_1 5_2 5_3 5_4 5_5 bytevector thread profile\ - misc cp0 5_6 5_7 5_8 6 io format 7 record hash enum 8 fx fl cfl foreign\ - ftype unix windows examples ieee date exceptions oop - -Examples = $(abspath ../examples) - -MAKEFLAGS += --no-print-directory - -# directory where (most) output for this run will be written -outdir=output - -conf = $(eval)-$o-$(spi)-$(cp0)-$(cis) -objdir=output-$(conf) -objname = $(mats:%=%.mo) -obj = $(objname:%=$(objdir)/%) -src = $(mats:%=%.ms) - -# prettysrc is src to use for pretty-print test; we leave out mat files -# with cycles, e.g., primvars.ms, misc.ms, 4.ms, 5_1.ms, hash.ms -prettysrc = 3.ms 5_3.ms 5_4.ms 5_5.ms bytevector.ms thread.ms profile.ms\ - 5_6.ms 5_7.ms 5_8.ms 6.ms io.ms format.ms 7.ms record.ms enum.ms 8.ms\ - fx.ms fl.ms cfl.ms foreign.ms unix.ms windows.ms examples.ms ieee.ms date.ms\ - exceptions.ms - -define conf-scheme-code - '(optimize-level $o)'\ - '(#%$$suppress-primitive-inlining #${spi})'\ - '(heap-check-interval ${hci})'\ - '(#%$$enable-check-prelex-flags #${ecpf})'\ - '(compile-profile #$p)'\ - '(collect-notify #${cn})'\ - '(collect-trip-bytes ${ctb})'\ - '(collect-generation-radix ${cgr})'\ - '(collect-maximum-generation ${cmg})'\ - '(enable-object-counts #${eoc})'\ - '(commonization-level ${cl})'\ - '(release-minimum-generation ${rmg})'\ - '(compile-interpret-simple #${cis})'\ - '(set! *examples-directory* "${Examples}")'\ - '(enable-cp0 #${cp0})'\ - '(set! *scheme* "${Scheme}")'\ - '(set! *mats-dir* "${MatsDir}")'\ - '(set! $$cat_flush "${MatsDir}/cat_flush${ExeSuffix}")'\ - '(current-eval ${eval})'\ - '(when #$c (coverage-table (load-coverage-files ${coverage-files:%="%"})))' -endef - -$(objdir)/%.mo : %.ms mat.so - echo $(conf-scheme-code)\ - '(time ((mat-file "$(objdir)") "$*"))'\ - '(unless (= (#%$$check-heap-errors) 0)'\ - ' (fprintf (console-error-port) "check heap detected errors---grep standard output for !!!\n")'\ - ' (abort))'\ - | ${Scheme} -q mat.so ${patchfile} - -# same as above except puts the .mo file in . -%.mo : %.ms mat.so - echo $(conf-scheme-code)\ - '(time ((mat-file ".") "$*"))'\ - '(parameterize ([source-directories (quote ("." "../s"))]) (when #${pdhtml} (profile-dump-html)))'\ - '(unless (= (#%$$check-heap-errors) 0)'\ - ' (fprintf (console-error-port) "check heap detected errors---grep standard output for !!!\n")'\ - ' (abort))'\ - | ${Scheme} -q mat.so ${patchfile} - -%.so : %.ss - echo '(reset-handler abort) (time (compile-file "$*"))' | ${Scheme} -q ${patchfile} - -report: $(outdir)/report-$(conf) - -experr: experr-$(conf) - -$(outdir)/report-$(conf): $(outdir)/errors-$(conf) - $(MAKE) doreport - -doreport: experr-$(conf) - rm -f $(outdir)/report-$(conf) - -diff experr-$(conf) $(outdir)/errors-$(conf) > $(outdir)/report-$(conf) 2>&1 - -maybe-doreport: - -if [ -f $(outdir)/errors-$(conf) ] ; then\ - $(MAKE) doreport ;\ - fi - -$(outdir)/errors-$(conf): ${obj} - $(MAKE) doerrors - -doerrors: $(outdir) - rm -f $(outdir)/errors-$(conf) - -(cd $(objdir); grep '^Error' $(objname)) > $(outdir)/errors-$(conf) - -(cd $(objdir); grep '^Bug' $(objname)) >> $(outdir)/errors-$(conf) - -(cd $(objdir); grep '^Warning' $(objname)) >> $(outdir)/errors-$(conf) - -(cd $(objdir); grep '^Expected' $(objname))\ - >> $(outdir)/errors-$(conf) - -fastreport: - $(MAKE) doerrors - $(MAKE) doreport - -docoverage: mat.so - if [ "$c" = "t" ] ; then\ - echo '(reset-handler abort) (combine-coverage-files "$(objdir)/all.covout" (quote ($(mats:%="$(objdir)/%.covout"))))' | ${Scheme} -q ${patchfile} mat.so ;\ - echo '(reset-handler abort) (coverage-percent "$(objdir)/all.covout" ${coverage-files:%="%"})' | ${Scheme} -q ${patchfile} mat.so ;\ - echo '(reset-handler abort) (coverage-percent "$(objdir)/run.covout" ${coverage-files:%="%"})' | ${Scheme} -q ${patchfile} mat.so ;\ - fi - -doallcoverage: mat.so - if [ "$c" = "t" ] ; then\ - echo '(reset-handler abort) (combine-coverage-files "all.covout" (map symbol->string (quote ($(shell echo */all.covout)))))' | ${Scheme} -q ${patchfile} mat.so ;\ - echo '(reset-handler abort) (coverage-percent "all.covout" ${coverage-files:%="%"})' | ${Scheme} -q ${patchfile} mat.so ;\ - echo '(reset-handler abort) (combine-coverage-files "run.covout" (map symbol->string (quote ($(shell echo */run.covout)))))' | ${Scheme} -q ${patchfile} mat.so ;\ - echo '(reset-handler abort) (coverage-percent "run.covout" ${coverage-files:%="%"})' | ${Scheme} -q ${patchfile} mat.so ;\ - fi - -define parallel-config-template -parallel$(1)-0: - -@$$(MAKE) allxphelp outdir=output-$(1)-0 objdir=output-$(1)-0 o=0 $(2) -parallel$(1)-3: - -@$$(MAKE) allxphelp outdir=output-$(1)-3 objdir=output-$(1)-3 o=3 $(2) -endef - -#configs from partialx and allx -$(eval $(call parallel-config-template,1,)) -$(eval $(call parallel-config-template,2,cp0=t)) -$(eval $(call parallel-config-template,3,cp0=t cl=3)) -$(eval $(call parallel-config-template,4,spi=t rmg=2 p=t)) -$(eval $(call parallel-config-template,5,eval=interpret cl=6)) -$(eval $(call parallel-config-template,6,eval=interpret cp0=t rmg=2)) -$(eval $(call parallel-config-template,7,eoc=f hci=101 cl=9)) -$(eval $(call parallel-config-template,8,eval=interpret hci=101 rmg=2)) - -#configs from bullyx -$(eval $(call parallel-config-template,b1,allxphelp-target=allxhelpnotall spi=t cp0=f)) -$(eval $(call parallel-config-template,b2,spi=f cp0=f cl=9 ctb='(/ (collect-trip-bytes) 64)' hci=503)) -$(eval $(call parallel-config-template,b3,spi=t cp0=f cis=t cmg=1)) -$(eval $(call parallel-config-template,b4,spi=f cp0=f cis=t cmg=6 hci=101)) -$(eval $(call parallel-config-template,b5,spi=t cp0=t ctb='(/ (collect-trip-bytes) 64)' cgr=6)) -$(eval $(call parallel-config-template,b6,spi=t cp0=f p=t eoc=f hci=101)) -$(eval $(call parallel-config-template,b7,spi=f cp0=t cl=9 p=t hci=101)) -$(eval $(call parallel-config-template,b8,eval=interpret spi=f cp0=f)) -$(eval $(call parallel-config-template,b9,eval=interpret spi=f cp0=t)) -$(eval $(call parallel-config-template,b10,eval=interpret spi=t cp0=f ctb='(/ (collect-trip-bytes) 64)' hci=503)) -$(eval $(call parallel-config-template,b11,eval=interpret spi=t cp0=t cgr=2 hci=101 p=t)) - - -partialx-confs = 1-0 1-3 2-3 6-3 - -allx-confs = 1-0 1-3 3-0 3-3 4-0 4-3 5-0 5-3 6-0 6-3 7-0 8-3 - -bullyx-confs = $(foreach n,1 2 3 4 5 6 7 8 9 10 11,b$(n)-0 b$(n)-3) - -define parallel-target-template -$(1)-targets: $($(1)-confs:%=parallel%) -$(1): prettyclean - @echo building prereqs with output to Make.out - @$$(MAKE) parallel-prereqs > Make.out 2>&1 - @$$(MAKE) $(1)-targets - $(if $(2),@$$(MAKE) $(2)) - cat $($(1)-confs:%=output-%/summary) > summary && cat summary -endef - -$(eval $(call parallel-target-template,partialx)) -$(eval $(call parallel-target-template,allx,doallcoverage)) -$(eval $(call parallel-target-template,bullyx,doallcoverage)) - - -just-reports: - for EVAL in compile interpret ; do\ - for O in 0 2 3 ; do\ - for SPI in f t ; do\ - for CP0 in f t ; do\ - for CIS in f t ; do\ - $(MAKE) maybe-doreport eval=$$EVAL o=$$O spi=$$SPI cp0=$$CP0 cis=$$CIS ;\ - done\ - done\ - done\ - done\ - done - - -allxhelp: - $(MAKE) doheader - -$(MAKE) all - $(MAKE) dosummary - -config-vars = spi hci ecpf cp0 cis p eval ctb cgr cmg eoc cl rmg -full-config-str = $(strip o=$(o) $(foreach var, $(config-vars),$(if $(filter-out $($(var:%=default%)),$($(var))),$(var)=$($(var)))) $(hdrmsg)) - -allxphelp-target = allxhelp -allxphelp: $(outdir) - @echo "matting configuration ($(full-config-str)) with output to $(outdir)/Make.out" - @$(MAKE) $(allxphelp-target) > "$(outdir)/Make.out" 2>&1 - @echo "finished matting configuration $(full-config-str)" - -summary-file=$(outdir)/summary - -$(outdir): - @mkdir -p "$(outdir)" - -doheader: $(outdir) - printf "%s" "-------- o=$o" >> $(summary-file) - if [ "$(spi)" != "$(defaultspi)" ] ; then printf " spi=$(spi)" >> $(summary-file) ; fi - if [ "$(hci)" != "$(defaulthci)" ] ; then printf " hci=$(hci)" >> $(summary-file) ; fi - if [ "$(ecpf)" != "$(defaultecpf)" ] ; then printf " ecpf(ecpf)" >> $(summary-file) ; fi - if [ "$(cp0)" != "$(defaultcp0)" ] ; then printf " cp0=$(cp0)" >> $(summary-file) ; fi - if [ "$(cis)" != "$(defaultcis)" ] ; then printf " cis=$(cis)" >> $(summary-file) ; fi - if [ "$p" != "$(defaultp)" ] ; then printf " p=$p" >> $(summary-file) ; fi - if [ "$(eval)" != "$(defaulteval)" ] ; then printf " eval=$(eval)" >> $(summary-file) ; fi - if [ "$(ctb)" != "$(defaultctb)" ] ; then printf " ctb=$(ctb)" >> $(summary-file) ; fi - if [ "$(cgr)" != "$(defaultcgr)" ] ; then printf " cgr=$(cgr)" >> $(summary-file) ; fi - if [ "$(cmg)" != "$(defaultcmg)" ] ; then printf " cmg=$(cmg)" >> $(summary-file) ; fi - if [ "$(eoc)" != "$(defaulteoc)" ] ; then printf " eoc=$(eoc)" >> $(summary-file) ; fi - if [ "$(cl)" != "$(defaultcl)" ] ; then printf " cl=$(cl)" >> $(summary-file) ; fi - if [ "$(rmg)" != "$(defaultrmg)" ] ; then printf " rmg=$(rmg)" >> $(summary-file) ; fi - if [ "$(hdrmsg)" != "" ] ; then printf " $(hdrmsg)" >> $(summary-file) ; fi - -dosummary: - printf " --------\n" >> $(summary-file) - if [ -f $(outdir)/report-$(conf) ] ; then\ - cat $(outdir)/report-$(conf) >> $(summary-file) ;\ - else \ - printf 'NO REPORT\n' >> $(summary-file) ;\ - fi - -allxhelpnotall: - rm -f mat.so - $(MAKE) doheader hdrmsg="not all" - -$(MAKE) - $(MAKE) dosummary - $(MAKE) docoverage - -all0: ; $(MAKE) all o=0 -all1: ; $(MAKE) all o=1 -all2: ; $(MAKE) all o=2 -all3: ; $(MAKE) all o=3 - -parallel-prereqs: $(src) oop.ss ht.ss mat.so cat_flush${ExeSuffix} ${fobj} m4test.in m4test.out prettytest.ss ftype.h freq.in freq.out ${patchfile} build-examples - -all: $(outdir) $(outdir)/script.all $(src) oop.ss ht.ss mat.so cat_flush${ExeSuffix} ${fobj} m4test.in m4test.out prettytest.ss ftype.h freq.in freq.out ${patchfile} build-examples - ${Scheme} --verbose -q mat.so ${patchfile} < $(outdir)/script.all - $(MAKE) doerrors - $(MAKE) doreport - $(MAKE) docoverage - -$(outdir)/script.all: Mf-base $(outdir) - -$(outdir)/script.all makescript$o: - echo $(conf-scheme-code)\ - '(record-run-coverage "$(objdir)/run.covout"'\ - ' (lambda ()'\ - ' (time (for-each (lambda (x) (time ((mat-file "$(objdir)") x)))'\ - ' (quote ($(mats:%="%")))))'\ - ' (parameterize ([source-directories (quote ("." "../s"))]) (when #${pdhtml} (profile-dump-html)))'\ - ' (unless (= (#%$$check-heap-errors) 0)'\ - ' (fprintf (console-error-port) "check heap detected errors---grep standard output for !!!\n")'\ - ' (abort))))'\ - > $(outdir)/script.all - -source: - $(MAKE) source0 o=0 - $(MAKE) source2 o=2 - $(MAKE) source3 o=3 - -source$o: ${src} mat.ss oop.ss ht.ss cat_flush.c ${fsrc} freq.in freq.out m4test.in m4test.out $(outdir)/script.all prettytest.ss ftype.h - -rootsrc = $(shell cd ../../mats; echo *) -${rootsrc}: -ifeq ($(OS),Windows_NT) - cp -p ../../mats/$@ $@ -else - ln -s ../../mats/$@ $@ -endif - -prettytest.ss: - rm -f prettytest.ss - $(MAKE) ${prettysrc} - cat ${prettysrc} > prettytest.ss - -bullyprettytest.ss: ${src} - (cd ../s; make source) - cat ${src} ../s/*.ss > prettytest.ss - -mat.so: ${patchfile} -foreign.mo ${objdir}/foreign.mo: ${fobj} -thread.mo ${objdir}/thread.mo: ${fobj} -examples.mo ${objdir}/examples.mo: m4test.in m4test.out freq.in freq.out build-examples -6.mo ${objdir}/6.mo: prettytest.ss -bytevector.mo ${objdir}/bytevector.mo: prettytest.ss -io.mo ${objdir}/io.mo: prettytest.ss -unix.mo ${objdir}/unix.mo io.mo ${objdir}/io.mo 6.mo ${objdir}/6.mo: cat_flush${ExeSuffix} -oop.mo ${objdir}/oop.mo: oop.ss -ftype.mo ${objdir}/ftype.mo: ftype.h -hash.mo ${objdir}/hash.mo: ht.ss - -build-examples: - ( cd ../examples && ${MAKE} Scheme=${Scheme} ) - touch build-examples - -prettyclean: - rm -f *.o ${mdclean} *.so *.mo *.covout experr* errors* report* summary testfile* testscript\ - ${fobj} prettytest.ss cat_flush${ExeSuffix} so_locations\ - build-examples script.all? *.html experr*.rej experr*.orig - rm -rf testdir* - rm -rf output output-* patches-work-dir - ( cd ../examples && ${MAKE} Scheme=${Scheme} clean ) - -clean: prettyclean - rm -f Make.out - - -### rules for generating various experr files - -# everything starts with the root experr files with default -# settings for the various parameters -experr-compile-$o-f-f-f: root-experr-compile-$o-f-f-f - cp root-experr-compile-$o-f-f-f experr-compile-$o-f-f-f - -root-experr: # don't list dependencies! - rm -f root-experr-compile-$o-f-f-f - # use the shell glob mechanism to find the file in any output* dir - err_file=(output*/errors-compile-$o-f-f-f); cp $${err_file[0]} root-experr-compile-$o-f-f-f - -root-experrs: # don't list dependencies! - $(MAKE) root-experr o=0 - $(MAKE) root-experr o=3 - -# derive spi=t experr files by patching spi=f experr files -# cp first in case patch is empty, since patch produces an empty output -# file rather than a copy of the input file if the patch file is empty -experr-compile-$o-t-f-f: experr-compile-$o-f-f-f patch-compile-$o-t-f-f - cp experr-compile-$o-f-f-f experr-compile-$o-t-f-f - -patch experr-compile-$o-t-f-f patch-compile-$o-t-f-f - -# derive cp0=t experr files by patching cp0=f experr files -experr-compile-$o-$(spi)-t-f: experr-compile-$o-$(spi)-f-f patch-compile-$o-$(spi)-t-f - cp experr-compile-$o-$(spi)-f-f experr-compile-$o-$(spi)-t-f - -patch experr-compile-$o-$(spi)-t-f patch-compile-$o-$(spi)-t-f - -# derive cis=t experr files by patching cis=f experr files -experr-compile-$o-$(spi)-$(cp0)-t: experr-compile-$o-$(spi)-$(cp0)-f patch-compile-$o-$(spi)-$(cp0)-t - cp experr-compile-$o-$(spi)-$(cp0)-f experr-compile-$o-$(spi)-$(cp0)-t - -patch experr-compile-$o-$(spi)-$(cp0)-t patch-compile-$o-$(spi)-$(cp0)-t - -# derive eval=interpret experr files by patching eval=compile experr files -# (with cis=f, since compile-interpret-simple does not affect interpret) -experr-interpret-$o-$(spi)-$(cp0)-$(cis): experr-compile-$o-$(spi)-$(cp0)-f patch-interpret-$o-$(spi)-$(cp0)-f - cp experr-compile-$o-$(spi)-$(cp0)-f experr-interpret-$o-$(spi)-$(cp0)-$(cis) - -patch experr-interpret-$o-$(spi)-$(cp0)-$(cis) patch-interpret-$o-$(spi)-$(cp0)-f - - -### rebuilding patch files - -patches: - rm -rf patches-work-dir - mkdir patches-work-dir - shopt -s nullglob; cp output*/errors-compile* output*/errors-interpret* patches-work-dir - for O in 0 2 3 ; do\ - if [ -f patches-work-dir/errors-compile-$$O-f-f-f -a -e patches-work-dir/errors-compile-$$O-t-f-f ] ; then \ - $(MAKE) xpatch-compile-$$O-t-f-f o=$$O spi=t ; \ - fi ;\ - for SPI in f t ; do\ - if [ -f patches-work-dir/errors-compile-$$O-$$SPI-f-f -a -e patches-work-dir/errors-compile-$$O-$$SPI-t-f ] ; then \ - $(MAKE) xpatch-compile-$$O-$$SPI-t-f o=$$O spi=$$SPI cp0=t ;\ - fi ;\ - for CP0 in f t ; do\ - if [ -f patches-work-dir/errors-compile-$$O-$$SPI-$$CP0-f -a -e patches-work-dir/errors-compile-$$O-$$SPI-$$CP0-t ] ; then \ - $(MAKE) xpatch-compile-$$O-$$SPI-$$CP0-t o=$$O spi=$$SPI cp0=$$CP0 cis=t ;\ - fi ;\ - if [ -f patches-work-dir/errors-compile-$$O-$$SPI-$$CP0-f -a -e patches-work-dir/errors-interpret-$$O-$$SPI-$$CP0-f ] ; then \ - $(MAKE) xpatch-interpret-$$O-$$SPI-$$CP0-f o=$$O spi=$$SPI cp0=$$CP0 ;\ - fi\ - done\ - done\ - done - -xpatch-compile-$o-t-f-f: # don't list dependencies! - rm -f patch-compile-$o-t-f-f - -diff --context patches-work-dir/errors-compile-$o-f-f-f\ - patches-work-dir/errors-compile-$o-t-f-f\ - > patch-compile-$o-t-f-f - -xpatch-compile-$o-$(spi)-t-f: # don't list dependencies! - rm -f patch-compile-$o-$(spi)-t-f - -diff --context patches-work-dir/errors-compile-$o-$(spi)-f-f\ - patches-work-dir/errors-compile-$o-$(spi)-t-f\ - > patch-compile-$o-$(spi)-t-f - -xpatch-compile-$o-$(spi)-$(cp0)-t: # don't list dependencies! - rm -f patch-compile-$o-$(spi)-$(cp0)-t - -diff --context patches-work-dir/errors-compile-$o-$(spi)-$(cp0)-f\ - patches-work-dir/errors-compile-$o-$(spi)-$(cp0)-t\ - > patch-compile-$o-$(spi)-$(cp0)-t - -xpatch-interpret-$o-$(spi)-$(cp0)-f: # don't list dependencies! - rm -f patch-interpret-$o-$(spi)-$(cp0)-f - -diff --context patches-work-dir/errors-compile-$o-$(spi)-$(cp0)-f\ - patches-work-dir/errors-interpret-$o-$(spi)-$(cp0)-f\ - > patch-interpret-$o-$(spi)-$(cp0)-f diff --git a/ta6ob/mats/Mf-ta6ob b/ta6ob/mats/Mf-ta6ob deleted file mode 100644 index 8f25aed..0000000 --- a/ta6ob/mats/Mf-ta6ob +++ /dev/null @@ -1,27 +0,0 @@ -# Mf-ta6ob -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -m = ta6ob - -fsrc = foreign1.c foreign2.c foreign3.c foreign4.c -fobj = foreign1.so - -include Mf-base - -foreign1.so: ${fsrc} ../boot/$m/scheme.h - $(CC) -pthread -fPIC -shared -I${Include} -o foreign1.so ${fsrc} - -cat_flush: cat_flush.c - $(CC) -o cat_flush cat_flush.c diff --git a/ta6ob/nanopass/.gitignore b/ta6ob/nanopass/.gitignore deleted file mode 100644 index e8bd18b..0000000 --- a/ta6ob/nanopass/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.sw? -.*.sw? diff --git a/ta6ob/nanopass/.travis.yml b/ta6ob/nanopass/.travis.yml deleted file mode 100644 index c20ab6a..0000000 --- a/ta6ob/nanopass/.travis.yml +++ /dev/null @@ -1,53 +0,0 @@ -language: c -sudo: required -env: - global: - - PKG_CONFIG_PATH="/usr/local/opt/libffi/lib/pkgconfig:$PKG_CONFIG_PATH" -matrix: - include: - - os: osx - env: SCHEME=chez - - os: osx - env: SCHEME=ikarus - before_script: - - brew update - - brew install libffi - - brew install bzr - - os: osx - env: SCHEME=ironscheme - - os: linux - env: SCHEME=chez - addons: - apt: - packages: - - libncurses5-dev - - libgmp-dev - - libffi-dev - - os: linux - env: SCHEME=ikarus - addons: - apt: - packages: - - libncurses5-dev - - libgmp-dev - - libffi-dev - - os: linux - env: SCHEME=vicare - addons: - apt: - packages: - - libncurses5-dev - - libgmp-dev - - libffi-dev - - os: linux - env: SCHEME=ironscheme -# - os: windows -# env: SCHEME=chez -# before_script: -# - rm .git/index; git reset --hard -# - choco install make -y -# - choco install sudo -y -dist: bionic -script: - - .travis/install_scheme - - .travis/run_tests diff --git a/ta6ob/nanopass/.travis/install_scheme b/ta6ob/nanopass/.travis/install_scheme deleted file mode 100755 index d9b81f3..0000000 --- a/ta6ob/nanopass/.travis/install_scheme +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/bash -e - -OS=$(uname) -ARCH=$(uname -m) - -function retrieve_file { - URL=$1 - FN=$2 - GET=`which wget` - if test $? -eq 0 ; then - echo wget -O $FN $URL - wget -O $FN $URL - else - GET=`which curl` - if test $? -eq 0 ; then - echo curl -o $FN $URL - curl -o $FN $URL - echo "install requires curl or wget to pull tools" - fi - fi -} - -function install_vicare { - VICARE_BASE="https://bitbucket.org/marcomaggi/vicare-scheme/downloads" - VICARE_VERSION="0.4.1-devel.3" - VICARE_FILE="vicare-scheme-${VICARE_VERSION}.tar.xz" - VICARE_URL="${VICARE_BASE}/${VICARE_FILE}" - - case $OS in - Linux) ;; - *) echo "unexpected operating system $OS" ; exit 1 ;; - esac - - retrieve_file ${VICARE_URL} ${VICARE_FILE} - - xzcat ${VICARE_FILE} | tar xf - - - pushd "vicare-scheme-${VICARE_VERSION}" - - ./configure --enable-posix --with-libffi - make - sudo make install - popd # vicare-scheme-${VICARE_VERSION} -} - -function install_ikarus { - case $ARCH in - i386|i686) BITS=32 ;; - x86_64|amd64) BITS=64 ;; - *) echo "unexpected architecture $ARCH" ; exit 1 ;; - esac - - case $OS in - Linux) PREFIX="/usr" ;; - Darwin) PREFIX="/usr/local" ;; - *) echo "unexpected operating system $OS" ; exit 1 ;; - esac - - bzr branch lp:ikarus - pushd ikarus - ./configure --prefix=$PREFIX \ - CFLAGS="-m${BITS} `pkg-config --cflags libffi` -I/usr/local/opt/gmp/include" \ - LDFLAGS="-m${BITS} `pkg-config --libs libffi` -L/usr/local/opt/gmp/lib" - make - sudo make install - popd # ikarus -} - -function install_chez { - BASE_URL="https://github.com/cisco/ChezScheme/releases" - CHEZ_VERSION="9.5.2" - CHEZ_TGZ="csv${CHEZ_VERSION}.tar.gz" - CHEZ_EXE="ChezScheme${CHEZ_VERSION}.exe" - - case $ARCH in - i386|i686) ARCH_MT="i3" ;; - x86_64|amd64) ARCH_MT="a6" ;; - *) echo "unexpected architecture $ARCH" ; exit 1 ;; - esac - - case $OS in - Linux) OS_MT="le" ;; - Darwin) OS_MT="osx" ;; - Windows*|MSYS_NT*) OS_MT="nt" ;; - *) echo "unexpected operating system $OS" ; exit 1 ;; - esac - - MT="${ARCH_MT}${OS_MT}" - - case $OS_MT in - le|osx) - retrieve_file "${BASE_URL}/download/v${CHEZ_VERSION}/${CHEZ_TGZ}" ${CHEZ_TGZ} - tar zxf $CHEZ_TGZ - pushd "csv${CHEZ_VERSION}" - ./configure -m="${ARCH_MT}${OS_MT}" - make - sudo make install - popd # "csv${CHEZ_VERSION}" - ;; - nt) - retrieve_file "${BASE_URL}/download/v${CHEZ_VERSION}/${CHEZ_EXE}" ${CHEZ_EXE} - ./${CHEZ_EXE} /install /quiet - export PATH=/c/Program\ Files/Chez\ Scheme\ ${CHEZ_VERSION}/bin/${MT}:$PATH - echo "(scheme-version)" | scheme -q - ;; - *) echo "unrecognized OS_MT: ${OS_MT}" ; exit 1 ;; - esac -} - -function install_ironscheme { - DOTNET_FILE="dotnet-install.sh" - DOTNET_URL="https://dot.net/v1/$DOTNET_FILE" - retrieve_file $DOTNET_URL $DOTNET_FILE - chmod +x $DOTNET_FILE - # install .NET - "./$DOTNET_FILE" --channel Current --runtime dotnet - export -p PATH="$HOME/.dotnet:$PATH" - - BASE_URL="https://github.com/IronScheme/IronScheme/releases/download" - IRONSCHEME_VERSION=1.0.239 - IRONSCHEME_GIT_VERSION=671ea21 - IRONSCHEME_URL="${BASE_URL}/${IRONSCHEME_VERSION}/IronScheme-${IRONSCHEME_VERSION}-${IRONSCHEME_GIT_VERSION}.zip" - IRONSCHEME_FILE="IronScheme.zip" - retrieve_file $IRONSCHEME_URL $IRONSCHEME_FILE - unzip $IRONSCHEME_FILE - alias ironscheme="dotnet IronScheme.ConsoleCore.dll" -} - -case $SCHEME in - vicare) install_vicare ;; - ikarus) install_ikarus ;; - chez) install_chez ;; - ironscheme) install_ironscheme ;; - *) echo "Please set the SCHEME environment variable to one of: vicare, ikarus, or chez before running" ; exit 1;; -esac diff --git a/ta6ob/nanopass/.travis/run_tests b/ta6ob/nanopass/.travis/run_tests deleted file mode 100755 index 74f6ab0..0000000 --- a/ta6ob/nanopass/.travis/run_tests +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -case $SCHEME in - vicare) vicare --more-file-extensions --source-path "." --r6rs-script test-all.ss ;; - ikarus) ikarus --r6rs-script test-all.ss ;; - chez) scheme --program test-all.ss ;; - ironscheme) - export -p PATH="$HOME/.dotnet:$PATH" - dotnet ./IronScheme/IronScheme.ConsoleCore.dll -- test-all.ss - ;; - *) echo "unexpected scheme implementation $SCHEME" ; exit 1 ;; -esac diff --git a/ta6ob/nanopass/Acknowledgements b/ta6ob/nanopass/Acknowledgements deleted file mode 100644 index 5f30cf4..0000000 --- a/ta6ob/nanopass/Acknowledgements +++ /dev/null @@ -1,7 +0,0 @@ -Acknowledgements - -The development of this software has been supported by Indiana University, -Cadence Research Systems, Cisco Systems, and a gift from Microsoft Research. -Jordon Johnson implemented an early version of the infrastructure. The "cata" -syntax and quasiquote extension to handle ellipses is patterned after Erik -Hilsdale's match.ss, an early version of which was written by Dan Friedman. diff --git a/ta6ob/nanopass/Copyright b/ta6ob/nanopass/Copyright deleted file mode 100644 index be319d8..0000000 --- a/ta6ob/nanopass/Copyright +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/ta6ob/nanopass/LOG b/ta6ob/nanopass/LOG deleted file mode 100644 index 16d5224..0000000 --- a/ta6ob/nanopass/LOG +++ /dev/null @@ -1,832 +0,0 @@ -2008-09-25 18:51:12 - 4865e596edc0ea8a68be26943c1463b9a9b3b6ab - * initial import of Dipa Sarkar's code - alltests.ss, compiler.ss, define-language.ss, define-pass.ss, driver.ss, - helpers.ss, match.ss, meta-parser.ss, meta-syntax-dispatch.ss, - nano-syntax-dispatch.ss, nano.ss, nanohelpers.ss, nanotest.ss, parser.ss, - preprocess.ss, records.ss, synforms.ss, syntaxconvert.ss, term.ss, - unparser.ss -2008-10-03 19:28:03 - d0a9aa5cfe8463a0a7d52a8fc9e03283b5f86078 - * added copyright notice - + Copyright.txt - * removed match, it was used to do initial parsing of sexp - - match.ss, nanotest.ss - * added first comment in trying to decode define-language - define-language.ss - * moved back to optimize-level 2 to give debugging information - nanotest.ss -2008-10-06 09:40:52 - 1fd736e52b3ca305f56aaeac049176ddd6f5eb71 - * removed execution bit from files, since they were unneeded - compiler.ss, define-language.ss, define-pass.ss, meta-parser.ss, - meta-syntax-dispatch.ss, nano-syntax-dispatch.ss, nano.ss, - nanohelpers.ss, parser.ss, records.ss, syntaxconvert.ss, term.ss, - unparser.ss -2008-10-06 09:48:17 - e06164bd5a6bf2437a833a2b8009e7dc8c7629a2 - * reorganized code to move library source into src directory - moved: define-language.ss, define-pass.ss, meta-parser.ss, - meta-syntax-dispatch.ss, nano-syntax-dispatch.ss, nano.ss, - nanohelpers.ss, parser.ss, records.ss, syntaxconvert.ss, terms.ss, and - unparser.ss to src directory -2008-10-06 09:49:43 - d72c88e555b24a6bc8738162c98d194b1069503f - * reorganized code to move testing source into tests directory - moved: alltests.ss, compiler.ss, driver.ss, helpers.ss, nanotest.ss, - preprocess.ss, and synforms.ss to tests directory -2008-10-09 21:29:41 - a1b2dd8408b6f1282cfc9a962d38f0647dc32409 - * accidentally changed (define-syntax define-langauge ... to - (define-language ... - * changed tests to support reorganized directories - tests/nanotest.ss - * began working to identify (and remove) unused code, along with code - reading to understand where and how functions are used. Also changed - to use consistent function definition syntax and line-wrap. - src/define-language.ss, src/define-pass.ss - * removed code after #!eof to be put in chaff file. - src/define-language.ss, src/define-pass.ss - * lifted duplicated common functions from make-processor-clause and - do-define-pass - src/define-pass.ss -2008-10-09 21:43:19 - d43213f91181deee413f86126fc3a0a56bfdf53e - * lifted make-incontext-transformer and make-quasiquote-transformer to - commonize these functions - src/define-pass.ss - * fixed (define-syntax define-language ... typo - src/define-language.ss -2008-10-09 22:23:42 - 29d2029f0213605732712c2be60f586e02c27677 - * commented out some of the lifted fields - src/define-pass.ss -2008-10-09 22:23:42 - d14c0b3ed8e254991baddd15317a6a9e31dcf30c - * uncommented and generally reworked code for defining passes - src/define-pass.ss -2008-10-10 11:18:17 - 4f7840c069d47d7cd68357c67cd5b805a98886de - * cleanup of language->s-expression code - src/define-language.ss - * more code reformating and moving of common functions into the helpers.ss - src/nanohelpers.ss, src/define-pass.ss, src/meta-parser.ss, - src/meta-syntax-dispatch.ss, src/nano-syntax-dispatch.ss, src/parser.ss, - src/records.ss, src/syntaxconvert.ss, src/unparser.ss -2008-10-24 18:13:23 - d1dff8cb77922342f52a10ed36a89497f8df5f6b - * added external TODO list moved from other files - TODO.txt, src/define-language.ss - * added load-all.ss file to load the parts from the src and tests directories - load-all.ss - * moved spare code to scrap file - scraps.ss - * curried the rec-member? call to reuse the code in all of the member? - functions - src/define-language.ss - * removed alt-union, alt-difference, and tspec-union functions - src/define-language.ss - * reorganized deeply nested if statements into conds - src/define-language.ss, src/define-pass.ss -2008-10-25 14:25:18 - 21451b92b0bd1a140b35cc375eda365530edfcc0 - * removed calls to eval that were used for looking up the meta-parser by - changing the meta-parser from a meta define to a procedure stored in the - compile time environment (procedure is then passed around in define-pass). - src/define-pass.ss, src/define-language.ss -2008-10-26 21:17:58 - 1284b9818ffb015f16d81e407aab94bfeaa59098 - * R6RSification: changed syntax-object->datum => syntax->datum, - list* => cons*, datum->syntax-object => datum->syntax, - (sub1 ,x) => (- ,x 1), (add1 ,x) => (+ ,x 1), partition => partition-syn - src/define-language.ss, src/define-pass.ss, src/meta-parser.ss, - src/nanohelpers.ss, src/records.ss, src/syntaxconvert.ss, src/unparser.ss - * removed unused, useless, or duplicated procedure definitions: show-decls, - show-tspecs, show-productions, lookup-any, split-decls, any, every, choose, - assp, remp, memp, filter, fold, reduce, empty-set, singleton-set, - add-element, member?, empty?, union, intersection, difference - src/nanohelpers.ss - * moved lookup-alt from nanohelpers.ss to meta-parser.ss - src/nanohelpers, src/meta-parser.ss - * removed module wrappers as part of r6rsification - src/unparser.ss, src/parser.ss, src/meta-parser.ss - * changed null syntax () to #'() in generation of field patterns - src/syntaxconvert.ss, - * added more to scraps from the tail end of unparser - src/scraps.ss -2008-10-26 21:20:07 - dc1e9b02e6964ec0c36772380660a462cf8e73d6 - * created R6RS libraries to wrap around existing code base - nanopass.ss, nanopass/helpers.ss, nanopass/language.ss, - nanopass/meta-parser.ss, nanopass/parser.ss, nanopass/pass.ss, - nanopass/r6rs-helpers.ss, nanopass/records.ss, nanopass/unparser.ss, - * added R6RS compatibililty wrappers for define-record, syntax-error, - literal-identifier=?, warning, and fx= - nanopass/r6rs-helpers.ss - * accidentally added swap file: nanopass/.records.ss.swp - nanopass/.records.ss.swp -2008-10-26 22:15:18 - 871b67ad1d4e2dafabe71536f15a6ec6d364c2ec - * added test-all script wrapper to ease testing - test-all.ss -2008-11-09 01:50:07 - 806ef5378ca0259b9a2a1bf3f1766e18a14ac227 - * removed accidentally added swap files: nanopass/.records.ss.swp - nanopass/.records.ss.swp - * cleaned up imports as more code is changed to comply with R6RS - nanopass/helpers.ss, nanopass/language.ss, nanpoass/meta-parser.ss, - nanopass/parser.ss, nanopass/pass.ss, nanopass/r6rs-helpers.ss, - nanopass/records.ss, nanopass/syntaxconvert.ss, nanopass/unparser.ss - * continued to press an Chez -> R6RS compatibility macro for define-record - nanopass/r6rs-helpers.ss - * also introduced my-syntax-violation to push for syntax-error compatibility - nanopass/r6rs-helpers.ss - * committed some debugging source (trace-define of parse-language) - nanopass/define-language.ss, - * added R6RS version of test-all - test-all-r6rs.ss - * code reformatting (removed spaces, changed to consistent coding standard) - nanopass/r6rs-helpers.ss, tests/r6rs-compiler.ss - * added implementation-helpers to abstract away some of the implementation - specific code - nanopass/syntaxconvert.ss, nanopass/unparser.ss - * moved iota from tests/compiler.ss to tests/helpers.ss - nanopass/compiler.ss - * create r6rs copy of the test compiler - tests/r6rs-compiler.ss, tests/r6rs-helper.ss, tests/r6rs-nanotest.ss -2008-11-09 01:59:07 - 118a0a36a308f49c25c58c3b67539ce4e384d46d - * added the implementation helpers files to the repositor, one for - Chez Scheme and one for Ikarus Scheme - nanopass/implementation-helpers.ikarus.ss, - nanopass/implementation-helpers.ss -2008-11-24 20:30:17 - 6e88caf2af091aac629fddb896651fcca92512a2 - * removed parse-language trace-define - src/define-language.ss - * commented out assert, since the R6RS one stands in fine - src/nanohelpers.ss -2008-11-24 20:39:20 - afe583a450a94aa25f9884902a7ce1032d5b48d7 - * resolving conflicts between two wroking copies, assert => syn-assert - src/nanohelpers.ss -2008-11-24 20:50:04 - 370bd11afdfc8a0233cf82b9f3d7f3c9e2f3db80 - * exported all of the internal exports from the main nanopass library - nanopass.ss - * more exports to allow this to run on Ikarus Scheme: added meta-define, - and a hack to support meta-define - nanopass/implementation-helpers.ikarus.ss, nanopass/term.ss - * exported more features of meta-parser: parse-cata, lookup-alt - nanopass/meta-parser.ss - * created library for meta-syntax-dispatch - nanopass/meta-syntax-dispatch.ss - * moved to more formal make-compile-time-value definition for - putting things into the compile-time environment to support ikarus. - src/define-language.ss - * more cleanup and R6RSification of meta-parser.ss - src/meta-parser.ss - * removed module tag from meta-syntax-dispatch - src/meta-syntax-dispatch.ss - * R6RSification of src/parser.ss: syntax-object->datum => syntax->datum, - assert => syn-assert - src/parser.ss, src/records.ss - * excluded datum from the R6RS compiler nanopss import - tests/r6rs-compiler.ss -2008-11-22 11:05:22 - 61feff78ee11abef5624b2de493e2bdb09851ffe - * same changes as previous version on a differnt machine. - nanopass.ss, nanopass/helpers.ss, nanopass/meta-parser.ss - nanopass/implementation-helpers.ikarus.ss, src/define-language.ss, - src/meta-parser.ss, src/meta-syntax-dispatch.ss, src/nanohelpers.ss, - src/records.ss, tests/r6rs-compiler.ss -2008-11-22 14:13:59 - 6b61d840e4e1b86eeacd1a489431a241023cf962 - * finished copying changes from previous commit in different working copy - nanopass/meta-syntax-dispatch.ss, nanopass/term.ss -2008-11-24 20:50:28 - 31d49c16511376b46781a3e5e737cb705b8f9609 - * merged two working copies -2008-11-24 22:36:14 - cbc2955a6fd540f482290fc92a39eaa4168d057b - * added trace-define-syntax and printf to the implementation-helpers to - support debugging - nanopass/implementation-helpers.ikarus.ss - * imported meta-syntax-dispatch into the meta-parser - nanopass/meta-parser.ss - * committed debugging code in the language definition - src/define-language.ss -2008-11-24 20:27:30 - f79bcb8b4aab5e804246a4030d2061edcf560e8d - * added meta-define and make-compilet-time-value macros for Chez to expand - into the appropriate meta define and cons - load-all.ss - * reformatted the exports in the nanopass top-level - nanopass.ss - * exported more helper procedures - nanopass/helpers.ss, nanopass/implementation-helpers.ss - * created auxiliaary keywords to export from the libraries to ensure they - will be free-identifier=? when used as keywords outside the library with - macros defined within the library - nanopass/language.ss, nanopas/meta-parser.ss - * created nano-syntax-dispatch library based on the syntax dispatcher from - the original code. - nanopass/nano-syntax-dispatch.ss - * added inclusing of nanopass/nano-syntax-dispatch.ss to parser.ss - nanopass/parsers.ss - * small formatting changes and removed debugging code. - nanopass/language.ss, src/define-language.ss, src/define-pass.ss, - src/parser.ss, src/unparser.ss, tests/r6rs-compiler.ss - * pulled make-double-collector-over-list and map2 into helpers - nanopass/helpers.ss - * small changes to deal with chez style records (record-type-name => - chez-record-type-name, record-type-descriptor => - chez-record-type-descriptor - src/unparser.ss - * added procedure definitions for compose, disjoin, any, every, choose, - reverse-filter, fold, reduce, partition, constant? keyword?, - list-of-user-primitives, list-of-system-primitives, user-primitive?, - system-primitive? primitive? predicate-primitive? value-primitive?, - effect-primitive? effect-free-primitive? gen-label, gen-symbol-seed, - reset-seed, gen-symbol, set? iota, with-values, mvlet, empty-set, - singleton-set, add-element, member?, empty?, union, intersection, and - difference to tests version of r6rs-helpers - tests/r6rs-helpers.ss - * created tiny testing library for looking at a single language definition - tests/r6rs-tiny.ss, tests/tiny.ss -2008-11-24 22:37:23 - 6f68e61e97d091ebad305b4406f7352e3cc14a6e - * no changes? looks like a merge node. -2008-12-11 09:06:34 - 65049181072cd5a748e732d454617083814b724e - * re-added auxiliary keywords for $tspec, $metas, $production, and $alt - nanopass.ss - * added code to push wraps down into syntax to support Ikarus. current - code makes extended use of car, cdr, etc. to decompose syntax rather than - syntax-case. eventually more of this needs to be dropped. - nanopass/helpers.ss - * added more implementation specific helpers to the Ikarus specific code. - some of these are to support things like format, printf, etc. - nanopass/implementation-helpers.ikarus.ss, - nanopass/implementation-helpers.ss - * moved auxiliary keywords: $tspec, $metas, $production, $alt, in, where, - over, extends, definitions, and entry into aux-keywords library - nanopass/language.ss, nanopassrecords.ss, (nanopass/aux-keywords.ss?) - * added helper syntax for map to print out what is being mapped over - for debugging purposes - nanopass/pass.ss - * fixing syntax around null (replacing #'() with '()) - nanopass/r6rs-helpers.ss - * tspec?, gramelt-metas, tspec-terminal, nonterminal-name, alt=?, and - define-language now use an eq? comparison to match aux-keywords rather - then relying on the auxiliary keyword facility - nanopass/define-language.ss - * general code cleanup (reformatting, removing debugging in places, etc.) - nanopass/define-language.ss -LATEST - * reformatted a couple places where there was some odd indenting - tests/compiler-test.ss - * updated compiler passes to make use of the new pass syntax. with this - change passes that utilized the automatic combining code needed to be - rewritten to explicitly do the combining themselves (this was usually - append or union). these passes now thread a varaible through and - perform a cheaper update when possible. - tests/compiler.ss, tests/unit-tests.ss - * added set-cons for adding individual items to a set (instead of using - union everywhere - tests/helpers.ss, test/compiler.ss - * worked a little on a new test compiler, but did not make much progress - tests/new-compiler.ss - * fixed error handling in the test driver so that we are no longer getting - a non-continuable error raised when there is an exception in a pass - tests/test-driver.ss -2011-04-09 - - * added todo to investigate the handling of tspec=? down the road we may want - to investigate the syntax for extending languages again and drop the - definitions section (or at least rename it) - nanopass/language.ss - * fixed the cata syntax to support cata to a Processor that returns - zero values. as part of this fix also improved support for mapping - over processors that return multiple values. originally this was - limited to just mapping over processors with one or two values, but - now it supports zero or more. (zero return value is special-cased to - use for-each, one return value is special-cased to use map, and a loop - is built on the fly to support two or more return values.) - nanopass/meta-parser.ss, nanopass/pass.ss - * improved error message when a processor meta-variable cannot be found in - the parser and unparser. - nanopass/parser.ss, nanopass/meta-parser.ss -2011-04-25 - - * merged changes from work with some in progress changes here. - * updated tests to work with new meta-variable only nonterminal alternatives -2011-05-13 - - * added nanopass-case macro to allow for local matching of nanopass - syntax. currently this expands into a directly applied define-pass - and is restricted to returning a single, non-checked value. - nanopass/pass.ss - * extended the meta parser to allow more then statement in the body of - in-context and with-output-language transformers. - nanopass/meta-parser.ss - * fixed issue with processor internal definitions not being properly - recognized and placed definitions within a with-output-language so - that quasiquotes will be transformed into nanopass language-records - similar to the processor right-hand-sides. - nanopass/pass.ss - * fixed bug with define-pass that was causing it to return a single value - when a user provided body was checked for an appropriate language value. - the check now happens to the first return value and the extra returned - values are returned as is. - nanopass/pass.ss - * fixed bug in how extend pred-all checks were being generated so that - a call to the ntspec's pred is being generated instead of just the a - reference to the pred itself. - nanopass/records.ss - * fixed bug in the unparser that was causing non-terminal productions to - be handled through a recursively generated form rather then using the - existing pred-all for the non-terminal. - nanopass/unparser.ss - * improved error message when searching for procs fails, so that we know - the syntax we were trying to process (and hence whether it was a body, - auto-generated ntspec production, auto-generated cata, or cata call - that generated the problem). - nanopass/pass.ss - * changed a debugging pretty-print - nanopass/language.ss -2011-05-17 - * improved error message when a field cannot be autogenerated in an - autogenerated clause to a processor - nanopass/pass.ss - * changed from call-with-values to let-values in code produced in - body of a processor (now that the error message doesn't hold onto - the 3D code we were generating) - nanopass/pass.ss -2011-05-22 - * removed the syn-map, map2, make-double-collector, and find-matching-clause - since they were no longer being used. - nanopass/helpers.ss, tests/helpers.ss - * changed references to prod and production to ntspec - nanopass/languages.ss, nanopass/meta-parser.ss, nanopass/parser.ss, - nanopass/unparser.ss, nanopass/records.ss - * rewrote code for handling user clauses in order to support nonterminals on - the left-hand-side of a clause. clauses are now matched in the order they - appear, with additional clauses autogenerated after user clauses have been - added. the code supports the current (limited) testing but has not yet been - tested with the new compiler code. it also does not yet support terminal - or nonterminal catas. - nanopass/meta-parser.ss, nanopass/pass.ss -2011-05-22 - * fixed the processor builder by adding the input identifier from a cata to - the list of formal arguments (when it would not be otherwise shadowed). - note: the order is not necessarily maintained, but since these values will - be set by the let* that binds them, there does not seem to be a need of - ordering. also fixed the else thunk to be a thunk. - nanopass/pass.ss - * incorporated changes to nanopass-case that Kent Dybvig made. when an - identifier is used in as the expression to be matched the identifier is - rebound with the new value when the cata is called. - nanopass/pass.ss - * incorporated changes to meta-language quasiquote syntax from Kent Dybvig. - this change allows things like `(locals (,(reverse xnfv*) ...) ---) which - would previously have raised an error since ellispis expected to find an - identifier in its body. to support this a quote form was also added to - make sure this feature does no cause automatically quoted items in the body - of an input, like booleans, symbols, and other constants. - nanopass/records.ss, nanopass/meta-parser.ss, nanopass/pass.ss -2011-05-25 - * fixed the error message for the output processor so that it would have the - preformatted name rather then the syntax I had inadvertently dropped in - (fix thanks to Kent Dybvig). - nanopass/meta-parser.ss -2011-05-25 - * setup the output process to leave quasiquote in the correct context - when an output expression is unquoted. this should allow us to avoid - many of the in-context specifiers needed in the current np-compiler. - nanopass/meta-parser.ss -2011-09-23 - * removed definitions form from define-language. added a todo for a better - solution to the problem of unparsing languages into a runnable s-expression - syntax. also removed empty let wrapper from unparser output, since it is - no longer needed with the definitions support gone. - nanopass/language.ss, nanopass/record.ss, nanopass/unparser.ss - * added feature to gather up information about the syntax being passed to - a record constructor so that we can provide a slightly better error message - when the value passed for one of the fields is invalid. this is done - using the source-annotation functionality, and produces a single message - for each fld (even though multiple syntax objects might have contributed, - e.g. in the case of a list field). when the identifier is known, it will - report that the problem occurred at the given syntax item and when it is - not it will report that the problem ocurred near the given syntax item. - nanopass/records.ss, nanopass/meta-parser.ss, nanopass/parser.ss - * parser and unparser are now defined with define-who so that they can report - which parser or unparser went belly up when an error occurs. - nanopass/language.ss, nanopass/parser.ss - * added check in nano-meta->fml* to raise an error when a quoted terminal - is found in the list of formals. this is just a more specific message - than the "unrecognized nano-rec" in the else case. - nanopass/pass.ss - * at optimize-level 3, the "checking" version of the pair-alt record - constructor is now a syntax definitions that washes down to a call to - the normal record constructor, so that the output of the checked and - unchecked cases will be the same. - nanopass/records.ss -2011-09-24 - * moved the preprocessor code into the tests/compiler.ss file and changed - it to use with-output-language, rather than the s-expression quasiquote. - tests/compiler.ss, tests/compiler-tests.ss, tests/preprocess.ss (removed) - * updated the synforms library to not require a quasiquoted expression. - also changed to use ... in place of dots or .. by using the Chez extended - syntax-rules (which allow for a general guard expression). also got rid of - top level quoted item, probably should have also made unquote legal as - start of pattern. - tests/synforms.ss - * now exporting define-who from tests/helpers.ss to allow for more convenient - error calls in the rename-var/verify-scheme function. - tests/helpers.ss, tests/compiler.ss -2011-09-29 - * added a (maybe x) form to language definitions to allow language defintions - to contain fields that can be occupied by either a non-terminal or #f. - this means it is now possible to have a production like: - (define-language L - (terminals - (integer (int)) - ---) - (Exp (e) - (Foo int (maybe e)) - ---)) - and the e field in Foo maybe either be an Exp or #f. also added ? as a valid - character to put on a meta-variable to allow e? for those fields that are - maybe fields. - nanopass/helpers.ss, nanopass/meta-parser.ss, nanopass/pass.ss, - nanopass/records.ss, nanopass/syntaxconvert.ss, nanopass/unparser.ss - test-all.ss, tests/unit-test-helpers.ss, tests/unit-tests.ss - * Fixed variable overlap bug when a pattern and the langauge formal to a processor - share the same name. For example: - (Exp : Exp (e1) -> Exp () - [(Foo ,e1 ,e2) ---] - ---) - this now produces the expected code and shadowing, instead of re-binding e1 - before e2 has a chance to be extracted from e1. - nanopass/pass.ss - * Fixed bug when handling output expressions that can end in a terminal in the - meta-parser. This means if you have: - (define-language L - (terminals - (integer (int)) - (boolean (bool)) - ---) - (Exp (e) - (Foo int e-or-bool) - ---) - (Exp-or-Bool (e-or-bool) - bool - e)) - then the expression: - (with-output-language (L Exp) `(Foo 4 #f)) - it should now work properly. - nanopass/meta-parser.ss - * Added indirect-export of record constructors, predicates, and accessors - created when defining a language, so that if the language is exported, - these will be exported as well. - nanopass/records.ss - * convert-pattern now returns fields and levels as separate list return - values along with a list of maybes. it also parses the (maybe e) syntax - (see note above) - nanopass/syntaxconvert.ss - * Fixed some tests that were still expecting the (let () ---) wrapper - around the output of language unparsers. also cleaned up the output - to make it a little more obvious what was going on with these. - tests/unit-tests.ss, tests/unit-test-helpers.ss -2011-09-09 - * The nanopass library is now built as a library group to ease testing in - Chez Scheme 8.9.1 (which includes a built in copy of the nanopass framework - that will be used in place of the library if it is not carefully loaded). - nanopass.ss - * Cleaned up unique names so that they now have a single number added to them - rather then several, and the names are divided by : in stead of being - divided by . - nanopass/helpers.ss - * Small changes to error messages that report bad meta-variables, these now - report if they are from the parser or meta-parser. - nanopass/meta-parser.ss, nanopass/parser.ss - * First step at moving to record variants with case dispatch. This version - includes the potential for some extra record checks, sometimes even when - they are not needed. However the basic dispatch is there now. - nanopass/pass.ss, nanopass/records.ss -2011-09-10 - * Moved calculation of ntspec sub-terminal predicate and ntspec full tags - into the same code that calculates the all-pred for the ntspec. This - has the added benefit that when the else is used we only put in the - nanopass-record check when there is a possibility that it could be a - terminal. - nanopass/records.ss, nanopass/pass.ss ----- -2011-12-26 - * Small fix to echo message for echoing passes (now includes newline) - nanopass/pass.ss - * Added basic support for nanopass records as terminals. This support is - incomplete, since it doesn't have a syntax that fully supports the - define-record-type syntax, but should be able to. - nanopass/pass.ss, nanopass/records.ss, nanopass/language.ss, - nanopass/meta-parser.ss - * Fixed (slightly) handling of mapping over input terms. Now if there is - not an expression to map, it does not build a call to map. - nanopass/pass.ss ----- -2012-12-17 - 949d59d57739e3a29cce020b244c81d049f73e5b - * Moved project to public github. - all files -2013-01-30 - 41f14e679b5fb9c2a8eaabe6f908905c3f329fe1 - * removed list-tail definition from helpers and turned it into an import in - implementation helpers. (thanks to Kent Dybvig, who made the change and - submitted a bug report). - nanopass/helpers.ss, nanopass/implementation-helpers.ss - * there is no longer an additional (duplicate) count for traversing into a - sub-nonterminal. counts for terminal elements of a wrapping nonterminal - have also been removed (not sure if this was a good change or not). - nanopass/language-node-counter.ss - * changed how the "trace" keyword determines when it should use an input or - output unparser. this is now determined by both checking that there is an - input (or output) language and an input (or output) nonterminal in the - transformer being traced. - nanopass/pass.ss - * changed the autogenerated clauses to call the checking record maker instead - of the non-checking version, because a recursive call could potentially hit - a compiler writer supplied terminal or nonterminal transformer that builds - an invalid item. - nanopass/pass.ss -2013-01-30 - 65d35a107fcdd4e7091af6c159867215d8da0971 - * Updated copyright information in all the files. - Copyright, nanopass.ss, nanopass/helpers.ss, - nanopass/implementation-helpers.chezscheme.ss, - nanopass/implementation-helpers.ikarus.ss, - nanopass/implementation-helpers.ss, nanopass/language-node-counter.ss, - nanopass/language.ss, nanopass/meta-parser.ss, - nanopass/meta-syntax-dispatch.ss, nanopass/nano-syntax-dispatch.ss, - nanopass/parser.ss, nanopass/pass.ss, nanopass/random-util.sls, - nanopass/records.ss, nanopass/syntax-handler.sls, - nanopass/syntaxconvert.ss, nanopass/unparser.ss, test-all.ss, - tests/alltests.ss, tests/compiler-test.ss, tests/compiler.ss, - tests/helpers.ss, tests/implementation-helpers.ikarus.ss, - tests/implementation-helpers.ss, tests/new-compiler.ss, - tests/synforms.ss, tests/test-driver.ss, - tests/unit-test-helpers-implementation.chezscheme.sls, - tests/unit-test-helpers.ss, tests/unit-tests.ss -2013-07-18 - 097f7c428a1573af14556e76619fab323f7d42b8 - * Merged typo fix in error message (courtesy of Eric Holk) - nanopass/pass.ss -2013-07-18 - 79e0e644d5c490a2ea71418834228a429b97d581 - * Merged another typo fix in another error message (courtesy of Eric Holk) - nanopass/records.ss -2013-08-03 - ce94b43cfc1a6ef1dd7de5bd65d37c165902918d - * INCOMPATIBLE CHANGE: Extended languages now use the base languages's entry - point as the entry point for the language instead of the first listed - nonterminal. In general, this seems like the behavior you want, though it - may break some existing libraries, so upgrade with caution. - nanopass/languages.ss, tests/compiler.ss - * Added a prune-language form that, when given a language, starts traversing - the language from the entry nontermainal and determines if there are any - dead nonterminals or terminals in the language, prunes them, and returns an - S-expression representing only the reachable parts of the language. - nanopass/language.ss, nanopass.ss -2013-09-03 - f8fc318d2bc644357c02cef5e897702efa2d1675 - * Added binaries of the nanopass framework for OS X - ReadMe, ReadMe.md, lib/ReadMe.md, lib/csv8.4/{,t}{a6,i3}osx/nanopass.so -2013-09-03 - b13b070e578d960c895c45aafba616175d4c5782 - * Added binaries ot the nanopass framework for Linux - lib/csv8.4/{,t}{a6,i3}le/nanopasss.so -2013-09-16 - ad7ff9b1eba29bffc474fc94cb4fc0ab431fa3ab - * Fixed a bug with the parser that caused bare boolean terminals to fail to - parse. Specifically, since #f was used to indicate a failed parse, - parsing the bare boolean #f was raising an error. - nanopass/parse.ss, tests/unit-tests.ss -2013-10-01 - af34af0544292872a5f1de4a8f92c1caca5e51b2 - * changed unique-id to unique-symbol, since we are now building the - unique-symbol and using it directly instead of generating the id to use in - output syntax. also exporting make-list to make generating accessors - easier. - nanopass/helpers.ss, nanopass/implementation-helpers.chezscheme.ss, - nanopass/implementation-helpers.ss - * fixed language->s-expression to no longer output the nongenerative id of - an ntspec, since it is no longer necessary to specify for each ntspec - nanopass/language.ss - * small cleanup of the meta-parser. removed extra (unused) argument to a - couple of procedures. - nanopass/meta-parsers.ss, nanopass/parser.ss, nanopass/unparser.ss - * removed differentiation between checking and non-checking maker, since we - are no longer using the non-checking maker. - nanopass/meta-parsers.ss, nanopass/records.ss, nanopass/parser.ss, - nanopass/pass.ss - * improved checking of meta-variables so that if the wrong meta-variable is - used, it will report it to the user, rather than doing a check that will - always fail we now report that an invalid meta-variable was used at expand - time. also did some general cleanup and improved error messages around - using quoted items in a pattern match. - nanopass/pass.ss, nanopass/records.ss - * changed record creation code to skip the define-record-type macro and - instead we are creating the records directly using the procedural - interface. this (hopefully) helps the memory usage and speed of expanding - language definitions. - nanopass/records.ss -2013-10-02 - 3dd941537379b2a2a1a139daf8107a24ce919346 - * added bin directory to automate the process of building binaries across Mac - OS X and Linux. these scripts require a setup with multiple versions of - the Chez Scheme compiler installed. - bin/build-shared-objects, bin/compile-file-to-lib-dir -2013-10-02 - 3dd941537379b2a2a1a139daf8107a24ce919346 - * added a define-pruned-language form that prunes a language and then defines - it with a new name. also changed diff-languages to output code that is - appropriate for the current implemntation of language extensions in the - nanopass framework. - nanopass.ss, nanopass/languages.ss -2013-10-04 - 9cd67d5ee048370ca253b7fd3b942151921858fd - * added checking for mutually recursive nonterminals so that we now report - an error to the user. this was a simple change, and if we want to support - this in the future, there is probably a way to do so, we just need to be - careful about pass generation. - nanopass/records.ss -2013-10-04 - 1aa2c01274137066aa3de75f966ce7c11374d20f, - c38ba0f9fea350ca403f8d0892765aebbb80890b - * fixed a small bug in the error reporting code for the stricter checking of - nanopass meta-variables. - nanopass/pass.ss -2013-10-15 - 47c580d5ee361d6aa209189baa3489c067e18248, - 3c7b2c6eff3e0e724291063cddce46ad9a447d47 - * added support for Vicare Scheme through the implementation helper files. - removed use of define-property, since it is not supported on other - Scheme platforms. - nanopass.ss, nanopass/helpers.ss, nanopass/language-node-counter.ss, - nanopass/language.ss, nanopass/meta-parser.ss, - nanopass/meta-syntax-dispatch.ss, nanopass/parser.ss, nanopass/pass.ss, - nanopass/record.ss, nanopass/unparser.ss, nanopass/synforms.ss, - nanopass.chezscheme.sls (new), - nanopass/implementation-helpers.chezscheme.sls - (renamed, was nanopass/implementation-helpers.chezscheme.ss), - nanopass/implementation-helpers.ss (removed), - nanopass/implementation-helpers.vicare.sls (new), - tests/implementation-helpers.chezscheme.sls (new), - tests/implementation-helpers.vicare.sls (new), - tests/unit-test-helpers-implementation.vicare.sls (new) - * moved language pruning code into a separate library to remove duplicated - code for prune-language and define-pruned-language. - nanopass/language-helpers.ss (new), nanopass/language.ss - * added a gitignore file so that I won't accidentally commit vim swap files. - .gitignore -2013-10-16 - d7f3c8a71a99f2cc88a3a5f8c28b780dcf07c41d - * added support for Ikarus Scheme (which is a little easier to install on Mac - OS X). moved more Chez specific code to the implementation specific - libraries. - nanopass/helpers.ss, implementation-helpers.chezscheme.sls, - implementation-helpers.ikarus.ss, implementation-helpers.vicare.sls, - nanopass/meta-parser.ss, nanopass/parser.ss, nanopass/pass.ss, - nanopass/records.ss, nanopass/unparser.ss, tests/compiler.ss, - tests/unit-test-helpers-implementation.ikarus.sls (new) - * test-all now prints output when running under Vicare Scheme. - tests/unit-test-helpers-implementation.vicare.sls - * started cleaning up code that is no longer used. - nanopass/helpers.ss, nanopass/random-util.sls (removed), - nanopass/syntax-handler.sls (removed) -2013-10-17 - 31bdcd721d5685ca78c1f43974ffb0ea890ad8b2 - * code cleanup. removed more no longer used code. - nanopass/helpers.ss, nanopass/implementation-helpers.chezscheme.sls, - test-all.ss -2013-10-17 - - * updated documentation and logs - LOG, TODO, ReadMe.md, CHANGES (removed), Notes (removed), - ReadMe (removed) - * updated binary build script and built updated binaries - bin/build-shared-objects, bin/compile-file-to-dir, - lib/csv8.4/{,t}{a6,i3}{le,osx}/nanopass.so -2013-10-24 - - * fixed support for using improper lists in language productions. this - addresses issue 7 from the github issues list. it is now possible to - use an improper list as the top-level pattern for a production and - improper lists can now be matched in a pass without raising an invalid - pattern syntax error in the pass. also added regression tests. - nanopass/language.ss, nanopass/meta-syntax-dispatch.ss, - tests/unit-tests.ss, test-all.ss, - lib/csv8.4/a6le/nanopass.so, lib/csv8.4/a6osx/nanopass.so, - lib/csv8.4/i3le/nanopass.so, lib/csv8.4/i3osx/nanopass.so, - lib/csv8.4/ta6le/nanopass.so, lib/csv8.4/ta6osx/nanopass.so, - lib/csv8.4/ti3le/nanopass.so, lib/csv8.4/ti3osx/nanopass.so -2013-12-05 - - * added a with-r6rs-quasiquote and a with-extended-quasiquote forms. the - r6rs version provides the normal quasiquote, while the extended version - includes support for ellipsis in the template (the extended quasiquote is - now needed for the pretty output forms). - nanopass.ss, nanopass/helpers.ss, nanopass/unparser.ss - * added a second pretty form (->) for writing procedural unparsing of - nonterminal productions. - nanopass/language.ss, nanopass/helpers.ss, nanopass.ss, nanopass/records.ss, - nanopass/unparser.ss - * changed how trace-define-pass and traced transformers work, so that the - tracing now outputs the raw S-expressions syntax, rather than the unparsed - S-expression syntax. - nanopass/unparser.ss - * fixed how the unparser handles terminals, so that they will be unparsed - using the pretty unparser, even when they are unparsed at the top level, if - they are not using the raw unparsing. - nanopass/unparser.ss - * fixed a bug in how the meta-parser generates catas so that it will now put - the correct type in for terminal specs. - nanopass/meta-parser.ss - * fixed a bug in how the transformer syntax is parsed when there is no input - language, or when there is no output language. (the code used to assume - that the language would be present, leading to unhelpful error messages.) - nanopass/pass.ss -2013-12-05 - - * fixed a bug with how errors are reported when a language production gets - the wrong the value. (Thanks to Eric Holk for pointing out the bug (and - the different handling of formats in Vicare). - nanopass/records.ss - * built csv8.4 binaries with the current updates. - lib/csv8.4/a6le/nanopass.so, lib/csv8.4/a6osx/nanopass.so, - lib/csv8.4/i3le/nanopass.so, lib/csv8.4/i3osx/nanopass.so, - lib/csv8.4/ta6le/nanopass.so, lib/csv8.4/ta6osx/nanopass.so, - lib/csv8.4/ti3le/nanopass.so, lib/csv8.4/ti3osx/nanopass.so -2013-12-09 - - * fixed a bug with the unparsing of maybe fields, with an added test to make - sure that we don't wreck the handling of maybe fields again. - nanopass/unparser.ss, test-all.ss, tests/unit-tests.ss - * built csv8.4 binaries with the current updates. - lib/csv8.4/a6le/nanopass.so, lib/csv8.4/a6osx/nanopass.so, - lib/csv8.4/i3le/nanopass.so, lib/csv8.4/i3osx/nanopass.so, - lib/csv8.4/ta6le/nanopass.so, lib/csv8.4/ta6osx/nanopass.so, - lib/csv8.4/ti3le/nanopass.so, lib/csv8.4/ti3osx/nanopass.so -2017-11-09 - - * fixed bug in handling of extra arguments for terminal subtypes, nonterminal - subtypes, and pass bodies. Previously all three of these cases simply - looked for a processor that did not require more extra arguments than we - had available, and supplied them in positional order, instead of using - names like the cata-morphism or normal pair-alt production processing. - nanopass/pass.ss, tests/unit-test.ss, test-all.ss -2017-11-10 - - * fixed a bug introduced by the last bug check that was leading to an - erroneous change in generation of terminal and nonterminal subtype calls - when there were additional return values. Also fixed a bug with the - handling of terminal subtype calls (these originally looked for a processor - that could return multiple values and then produced a values return that - added effectively had a multi-valued first element (which would have lead - to run time errors). - nanopass/pass.ss -2017-11-17 - - * fixed error message generated by nanopass constructors with list fields so - that it reports that it expected a list of (or list of list of ... etc.) - the type instead of failing because we are calling for-each. (bad error - message reported by Jamie Taylor---thanks!) - nanopass/records.ss, test-all.ss, tests/unit-tests.ss - * fixed assert-error so that it will work, now that there are tests that - need to make use of it. - tests/unit-test-helpers.ss -2018-09-05 - - * remove outdated information and add links to papers - ReadMe.md - * fixed Travis CI fails caused by inaccurate vicare-scheme version - .travis/install_scheme -2018-09-16 - - * fixed tests to work with recent version of vicare (0.4d1) - nanopass/implementation-helpers.vicare.sls, nanopass/language.ss, - nanopass/pass.ss, nanopass/records.ss, - tests/implementation-helpers.vicare.sls, tests/test-driver.ss -2018-09-30 - - * implemented define-property for ikarus and vicare - nanopass/syntactic-property.sls (new), - nanopass/implementation-helpers.ikarus.ss, - nanopass/implementation-helpers.vicare.sls, - nanopass/implementation-helpers.chezscheme.ss, nanopass/helpers.ss - * added pass-input-parser and pass-output-unparser to allow the class - compiler driver to determine the parser and unparser for passes used in the - compiler so that we can trace and start at intermediate points in the - compiler without having to specify it in each case. - nanopass.ss, nanopass/pass.ss, test-all.ss, tests/unit-tests.ss, - tests/unit-test-helpers.ss - * updated to the most recent vicare release - .travis/install_scheme -2018-10-04 - - * Updated the way we store the pass input and output languages, so that we - can differentiate between a pass that does not have an input language or - output language and an identifier that is not for a pass. These macros now - expand into code for the language unparser/parser (when there is an input - or output language), a procedure that takes one or more arguments and - returns the first one (when there is no input or output language), or #f - (when the identifier is not for a pass, or the pass info property has been - somehow lost). Also added procedures for looking up the input and outpuot - language with an identifier and the compile time environment, and - determining if an identifier has related pass information. - nanopass.ss, nanopass/pass.ss nanopass/records.ss -2019-11-27 - - * Small fix to correct with-r6rs-quasiquote, which was previously not - restoring the normal R6RS quasiquote within a scope where a nanopass - quasiquote handler was bound. - nanopass/helpers.ss - * Whitespace cleanup. - nanopass/pass.ss -2019-12-07 - - * Small fix to make the unit tests exit with a non-zero exit code when one of - the unit test fails. Along with this fixed formatting around the error - messages so that it should be consistent across platforms. This required a - bit of hackery to get the filename that will be used by Chez, Ikarus, and - Vicare, along with exposing a version of format that sets the print - parameters necessary to get it to match display-condition (in Chez, this is - just format in Ikarus and Vicare). Finally, exposed some of the underlying - source information extracting functions. - test-all.ss, nanopass/helpers.ss, - tests/unit-test-helpers-implementation.chezscheme.sls, - tests/unit-test-helpers-implementation.ikarus.sls, - tests/unit-test-helpers-implementation.vicare.sls, - tests/unit-test-helpers.ss, tests/unit-tests.ss - * Corrected (embarrassing) misspelling of received. - nanopass/records.ss -2020-01-31 - - * Small changes: added trace-define-who, slightly improved error message for - quoted terminals in patterns, and a little code and comment cleanup. - nanopass/helpers.ss, nanopass/meta-syntax-dispatch.ss, nanopass/pass.ss, - nanopass/records.ss -2020-10-11 - - * Changed the nano-syntax-dispatch into a macro so that compilers using - define-parser do not have a run-time dependency on the (nanopass - nano-syntax-dispatch) library. With this change the pattern no longer - needs to be quoted in the output of define-parser. - nanopass/nano-syntax-dispatch.ss, nanopass/parser.ss -2020-10-18 - - * Removed np-parse-fail-token as a run-time dependency by making it a macro. - The whole parser really needs to be revisited, but this should make it - possible to generate compilers with intermediate language parser that do - not have a run-time dependency on the nanopass framework. - nanopass/parser.ss, nanopass/helpers.ss, - nanopass/implementation-helpers.chezscheme.sls, - nanopass/implementation-helpers.ikarus.ss, - nanopass/implementation-helpers.ironscheme.sls, - nanopass/implementation-helpers.vicare.sls diff --git a/ta6ob/nanopass/ReadMe.md b/ta6ob/nanopass/ReadMe.md deleted file mode 100644 index dad9f65..0000000 --- a/ta6ob/nanopass/ReadMe.md +++ /dev/null @@ -1,46 +0,0 @@ -Nanopass Compiler Library -========================== -[![Build Status](https://travis-ci.org/nanopass/nanopass-framework-scheme.svg?branch=master)](https://travis-ci.org/nanopass/nanopass-framework-scheme) - -This repositiory contains an R6RS version of the Nanopass Compiler Infrastructure -described in \[1, 2, 3, 4\], along with the beginnings of a test compiler for the -library and the rough start to a users guide. The nanopass framework currently -supports Chez Scheme, Vicare Scheme, and Ikarus Scheme. - -Files -====== - - ReadMe.md -- this readme file - Acknowledgements -- thanks to those who have supported the work - Copyright -- copyright information - TODO -- the head of the infinite todo list - LOG -- change log for the nanopass framework - test-all.ss -- is a simple wrapper for importing the compiler and - performing a testing run of all of the tests. - nanopass.ss -- the main interface to the nanopass compiler library - nanopass/ -- contains the parts that nanopass.ss aggregates - tests/ -- contains a testing compiler along with tests for that - compiler and a driver for running the tests - doc/ -- contains a user guide and developer guide along with a - makefile for generating their pdfs with pdflatex -References -=========== - -[[1]](https://dl.acm.org/citation.cfm?id=2500618) - A. Keep and R. K. Dybvig. A Nanopass Compiler for Commercial Compiler - Development. In ICFP ’13: Proceedings of the 18th ACM SIGPLAN International - Conference on Functional Programming, New York, NY, USA, 2013. ACM. - -[2] A. Keep. A Nanopass Framework for Commercial Compiler Development. - Doctoral dissertation, Indiana University, - Bloomington, Indiana, USA, Feb. 2013. - -[3] D. Sarkar. Nanopass Compiler Infrastructure. - Doctoral dissertation, Indiana University, - Bloomington, Indiana, USA, 2008. - -[[4]](https://dl.acm.org/citation.cfm?id=1016878) - D. Sarkar, O. Waddell, and R. K. Dybvig. A nanopass infrastructure for - compiler education. In ICFP ’04: Proceedings of the ninth ACM SIGPLAN - International Conference on Functional Programming, pages 201–212, - New York, NY, USA, 2004. ACM. diff --git a/ta6ob/nanopass/TODO b/ta6ob/nanopass/TODO deleted file mode 100644 index ce17100..0000000 --- a/ta6ob/nanopass/TODO +++ /dev/null @@ -1,48 +0,0 @@ -TODO - -Support: - -1. Create Racket version of the nanopass framework - -2. Extended to more R6RS libraries (at least if they support some form of - compile time environment). - -Nanopass Annoyances: - -1. Removal of patterns is too strict matching EXACTLY the variable names (see - above example) This may not be bad, but without the error is a very rough - edge. - -2. Output forms need to match original language forms very closely, e.g. if we - have: - (define-language L - over - --- - where - (e in Expr - (begin e0 ... e1) - ---) - ---) - we cannot create the constructor: - `(begin (set! ,x0 (var ,tmp*)) ...) - - because it sees this as a single form instead of a list. Being able to - create a make-begin helper for this situation is helpful, but ultimately - we'd like it to match broader forms and complain at compilation time if it - cannot prove they are safe itself. The contortion we are instead forced to - perform is: - - (let* ([expr* (map (lambda (x tmp) `(set! ,x (var ,tmp))) x0 tmp*)] - [rexpr* (reverse expr*)] - [last-expr (car rexpr*)] - [expr* (reverse (cdr expr*))]) - `(begin ,expr* ... ,last-expr)) - -Features to add down the road: - -1. Pass fusing with deforestation of the intermediate passes. - -Error Handling/Loosening restrictions: - -1. Fix parser to use positional information to report errors on the syntax - error, in addition to reporting the error. diff --git a/ta6ob/nanopass/doc/Makefile b/ta6ob/nanopass/doc/Makefile deleted file mode 100644 index 886afde..0000000 --- a/ta6ob/nanopass/doc/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# define default document pathname here - -Scheme=scheme -STEXLIB=${HOME}/stex -# override on command line with 'make x=newdoc' -x = user-guide - -# define latex processor: latex or pdflatex -latex = pdflatex - -# define stex macro files here -stexmacrofiles = - -# list bibliography files here -bib = user-guide.bib - -# define index if an index is to be generated -# index=yes - -doit: $x.pdf - -include ~/stex/Mf-stex - -# define or override suffixes here - -# define any additional targets here - -# define any dependencies here - -# define cleanup targets here: - -$(x).clean: - -$(x).reallyclean: - -$(x).reallyreallyclean: - diff --git a/ta6ob/nanopass/doc/language-api.ss b/ta6ob/nanopass/doc/language-api.ss deleted file mode 100644 index 59beb22..0000000 --- a/ta6ob/nanopass/doc/language-api.ss +++ /dev/null @@ -1,77 +0,0 @@ -(define-language Lannotated - (entry Defn) - (terminals - (record-constructor-descriptor (rcd)) - (record-type-descriptor (rtd)) - (exact-integer (tag level tag-mask)) - (datum (handler record-name pred all-pred all-term-pred - accessor maker)) - (box (b)) - (syntax (stx)) - (identifier (id)) - (dots (dots)) - (null (null))) - (Defn (def) - (define-language id ref (maybe id0) rtd rcd tag-mask - (term* ...) nt* ...)) - (Terminal (term) - (id (id* ...) b (maybe handler) pred)) - (Nonterminal (nt) - (id (id* ...) b rtd rcd tag pred all-pred all-term-pred - prod* ...)) - (Production (prod) - (production pattern (maybe pretty-prod) rtd tag pred maker field* ...) - (terminal ref (maybe pretty-prod)) - (nonterminal ref (maybe pretty-prod))) - (Pattern (pattern) - id - ref - null - (maybe ref) - (pattern dots) - (pattern0 dots pattern1 ... . pattern2) - (pattern0 . pattern1)) - (PrettyProduction (pretty-prod) - (procedure handler) - (pretty pattern)) - (Field (field) - (ref level accessor) - (optional ref level accessor)) - (Reference (ref) - (reference id0 id1 b))) - -(define-language Llanguage - (entry Defn) - (terminals - (box (b)) - (syntax (stx)) - (identifier (id)) - (datum (handler)) - (dots (dots)) - (null (null))) - (Defn (def) - (define-language id cl* ...)) - (Clause (cl) - (entry ref) - (nongenerative-id id) - (terminals term* ...) - (id (id* ...) b prod* ...)) - (Terminal (term) - simple-term - (=> simple-term handler)) - (SimpleTerminal (simple-term) - (id (id* ...) b)) - (Production (prod) - pattern - (=> pattern0 pattern1) - (-> pattern handler)) - (Pattern (pattern) - id - ref - null - (maybe ref) - (pattern dots) - (pattern0 dots pattern1 ... . pattern2) - (pattern0 . pattern1)) - (Reference (ref) - (reference id0 id1 b))) diff --git a/ta6ob/nanopass/doc/user-guide.bib b/ta6ob/nanopass/doc/user-guide.bib deleted file mode 100644 index 5edade9..0000000 --- a/ta6ob/nanopass/doc/user-guide.bib +++ /dev/null @@ -1,67 +0,0 @@ -@phdthesis{keep-phdthesis-2013, - author = {Keep, Andrew W.}, - title = {{A Nanopass Framework for Commercial Compiler Development}}, - school = {Indiana University}, - year = {2013}, - month = feb, - url = {https://pqdtopen.proquest.com/pubnum/3560746.html} -} - -@inproceedings{Meijer:1991:FPB:645420.652535, - author = {Meijer, Erik and Fokkinga, Maarten M. and Paterson, Ross}, - title = {{Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire}}, - booktitle = {Proc. 5th ACM Conference on Functional Programming Languages and Computer Architecture}, - year = {1991}, - isbn = {3-540-54396-1}, - pages = {124--144}, - numpages = {21}, - url = {http://dl.acm.org/citation.cfm?id=645420.652535}, - acmid = {652535}, - publisher = {Springer-Verlag}, - address = {London, UK}, -} - -@inproceedings{Sarkar:2004:NIC:1016850.1016878, - author = {Sarkar, Dipanwita and Waddell, Oscar and Dybvig, R. Kent}, - title = {{A Nanopass Infrastructure for Compiler Education}}, - booktitle = {Proc. 9th ACM SIGPLAN International Conference on Functional Programming}, - series = {ICFP '04}, - year = {2004}, - location = {Snow Bird, UT, USA}, - pages = {201--212}, - numpages = {12}, - url = {http://doi.acm.org/10.1145/1016850.1016878}, - acmid = {1016878}, - publisher = {ACM}, - address = {New York}, - keywords = {compiler writing tools, domain-specific languages, nanopass compilers, syntactic abstraction}, -} - -@book{Dybvig:csug8, - author = {R. Kent Dybvig}, - title = {{Chez Scheme Version 8 User's Guide}}, - publisher = {Cadence Research Systems}, - year = 2009, - texturl = "http://www.scheme.com/csug8/", - biburl = "http://www.cs.indiana.edu/{\textasciitilde}dyb/pubs/csug8.bib", - annote = {User's guide and reference manual for Chez Scheme Version 8. Complements \cite{Dybvig:tspl4}.} -} - -@book{Dybvig:csug9, - author = {R. Kent Dybvig}, - title = {{Chez Scheme Version 9 User's Guide}}, - publisher = {Cisco Systems, Inc.}, - year = 2019, - url = "http://cisco.github.io/ChezScheme/csug9.5/csug.html", - annote = {User's guide and reference manual for Chez Scheme Version 9.5 Complements \cite{Dybvig:tspl4}.} -} - -@book{Dybvig:tspl4, - author = {R. Kent Dybvig}, - title = {The {Scheme} Programming Language}, - publisher = {{MIT} Press}, - edition = {Fourth}, - year = 2009, - texturl = "http://www.scheme.com/tspl4/", - annote = {Introduction and reference manual for R6RS Scheme with numerous short and extended examples and exercises.} -} diff --git a/ta6ob/nanopass/doc/user-guide.pdf b/ta6ob/nanopass/doc/user-guide.pdf deleted file mode 100644 index 62785dd..0000000 Binary files a/ta6ob/nanopass/doc/user-guide.pdf and /dev/null differ diff --git a/ta6ob/nanopass/doc/user-guide.stex b/ta6ob/nanopass/doc/user-guide.stex deleted file mode 100644 index 15679f7..0000000 --- a/ta6ob/nanopass/doc/user-guide.stex +++ /dev/null @@ -1,2752 +0,0 @@ -\documentclass[letterpaper,10pt,oneside]{book} -\usepackage{fullpage} -\usepackage{scheme} -\usepackage[pdftitle="Nanopass Framework Users Guide", - pdfauthor="Andrew W. Keep", - pdfdisplaydoctitle]{hyperref} - -\title{Nanopass Framework Users Guide\thanks{This documentation is largely -extracted from Chapter 2 of my dissertation~\cite{keep-phdthesis-2013}. -The user guide has been updated to reflect recent updates the nanopass -framework. -Several example passes and languages have also been replaced with a more -recent, publicly available example compiler.}} -\author{Andrew W. Keep} - -\def\TODO#1{{\textcolor{red}{#1}}} -\newcommand{\dash}[1][1em]{\raise.5ex\hbox to #1{\leaders\hrule\hfil}} -\mathchardef\mhyphen="2D -\parskip 6pt -\parindent 0pt -\begin{document} -\maketitle - -\chapter{Introduction} % 2.1 -The nanopass framework is an embedded DSL for writing compilers. -The framework provides two main syntactic forms: \scheme{define-language} and -\scheme{define-pass}. -The \scheme{define-language} form specifies the grammar of an intermediate -language. -The \scheme{define-pass} form specifies a pass that operates over an input -language and produces another, possibly different, output language. - -\section{A Little Nanopass Framework History} -The idea of writing a compiler as a series of small, single-purpose passes -grew out of a course on compiler construction taught by Dan -Friedman in 1999 at Indiana University. -The following year, R. Kent Dybvig and Oscar Waddell joined Friedman -to refine the idea of the {\it micropass compiler} into a set of assignments -that could be used in a single semester to construct a compiler for a subset of -Scheme. -The micropass compiler uses an S-expression pattern matcher -developed by Friedman to simplify the matching and rebuilding of language terms. -Erik Hilsdale added a support for -catamorphisms~\cite{Meijer:1991:FPB:645420.652535} that provides a more -succinct syntax for recurring -into sub-terms of the language, which further simplified pass development. - -Passes in a micropass compiler are easy to understand, as each pass is -responsible for just one transformation. -The compiler is easier to debug when compared with a traditional compiler -composed of a few, multi-task passes. -The output from each pass can be inspected to ensure that it meets grammatical and -extra-grammatical constraints. -The output from each pass can also be tested in the host Scheme system to ensure -that the output of each pass evaluates to the value of the initial expression. -This makes it easier to isolate broken passes and identify bugs. -The compiler is more flexible than a compiler composed of a few, multi-task passes. -New passes can easily be added between existing passes, which allows -experimentation with new optimizations. -In an academic setting, writing compilers composed of many, single-task passes -is useful for assigning extra compiler passes to -advanced students who take the course. - -Micropass compilers are not without drawbacks. -First, efficiency can be a problem due to pattern-matching overhead and the -need to rebuild large S-expressions. -Second, passes often contain boilerplate code to recur through otherwise -unchanging language forms. -For instance, in a pass to remove one-armed \scheme{if} expressions, where only -the \scheme{if} form changes, other forms in the language must be -handled explicitly to locate embedded \scheme{if} expressions. -Third, the representation lacks formal structure. -The grammar of each intermediate language can be documented in comments, but -the structure is not enforced. - -The \scheme{define-language} and \scheme{define-pass} syntactic forms are used -by the nanopass framework to address these problems. -A \scheme{define-language} form formally specifies the grammar of an -intermediate language. -A \scheme{define-pass} form defines a pass that operates on one language and -produces output in a possibly different language. -Formally specifying the grammar of an intermediate language and writing passes -based on these intermediate languages -allows the nanopass framework to use a record-based -representation of language terms that is more efficient than the S-expression -representation, autogenerate boilerplate code to recur -through otherwise unchanging language forms, and generate checks to verify that -the output of each pass adheres to the output-language grammar. - -The summer after Dybvig, Waddell, and Friedman taught their course, Jordan -Johnson implemented an initial prototype of the nanopass framework to support -the construction of micropass compilers. -In 2004, Dipanwita Sarkar, Oscar Waddell, and R. Kent Dybvig developed a -more complete prototype nanopass framework for compiler construction and -submitted a paper on it to ICFP~\cite{Sarkar:2004:NIC:1016850.1016878}. -The initial paper focused on the nanopass framework as a tool capable of -developing both academic and commercial quality compilers. -The paper was accepted but on the condition that it be refocused only on academic -uses. -The reviewers were not convinced that the framework or nanopass construction method -was capable of supporting a commercial compiler. -In retrospect, the reviewers were right. -Sarkar implemented only a few of the passes from the compiler used in the -course on compilers. -This implementation showed that the nanopass framework was viable, but it did -not support the claim -that the nanopass framework could be used for a commercial compiler. -In fact, because the class compiler was started but never completed, it is -unclear whether the prototype was even up to the task of writing the full class -compiler. - -The nanopass framework described in this guide improves on the prototype -developed by Sarkar. -In this framework, language definitions are no longer restricted to -top-level definitions. -Additionally, passes can accept more than one argument and return zero or -more values. -Passes can be defined that operate on a subset of a language instead of being -restricted to starting from the entry-point nonterminal of the language. -Passes can also autogenerate nonterminal transformers not supplied by the -compiler writer. -The new nanopass framework also defines two new syntactic forms, -\scheme{nanopass-case} and \scheme{with-output-language}, that allow language -terms to be matched and constructed outside the context of a pass. - -\section{The Nanopass Framework Today} -% TODO: Update this line count to reflect the current size of -% the nanopass framework -Although the nanopass framework defines just two primary syntactic forms, the -macros that implement them are complex, with approximately 4600 lines of code. -In both the prototype and the new version of the nanopass framework, the -\scheme{define-language} macro parses a language definition and stores a -representation of it in the compile-time environment. -This representation can be used to guide the definition of derived languages -and the construction of passes. -Both also create a set of record types used to represent language terms at run -time, along with an unparser for translating the record representation to an -S-expression representation. -Finally, both create meta-parsers to parse S-expression patterns and templates. -An S-expression to record-form parser can also be created from the language -using \scheme{define-parser}.\footnote{In the prototype, this was part of -the functionality of \scheme{define-language}, but in a commercial compiler -we do not frequently need an S-expression parser, so we no longer -autogenerate one.} - -The \scheme{define-pass} form, in both versions of the framework, operates -over an input-language term and produces an output-language term. -The input-language meta-parser generates code to match the specified pattern as -records, as well as a set of bindings for the variables named in the pattern. -The output-language meta-parser generates record constructors and -grammar-checking code. -Within a pass definition, a transformer is used to define a translation from an -input nonterminal to an output nonterminal. -Each transformer has a set of clauses that match an input-language term and -construct an output-language term. -The pattern matching also supports -catamorphisms~\cite{Meijer:1991:FPB:645420.652535} for recurring into language -sub-terms. - -\section{Examples using the Nanopass Framework} -There are two, publicly available examples of the nanopass framework. -The first is in the {\tt tests} sub-directory of the nanopass framework git -repository at -\href{https://github.com/akeep/nanopass-framework/}{github.com/akeep/nanopass-framework}. -This is part of a student compiler, originally included with the prototype -nanopass framework developed by Sarkar et al.\ and updated to conform with the -changes that have been made in the updated nanopass framework. - -The second example is available in the -\href{https://github.com/akeep/scheme-to-c/}{github.com/akeep/scheme-to-c} -repository. -This compiler is better documented and provides a complete compiler -example targeting fairly low-level C from a simplified Scheme dialect. -It was developed to be presented at -\href{https://clojure-conj.org}{Clojure Conj 2013}, just -days before the Conj started, and compiles a small subset of Scheme to C. -It is similar to the included example, but has the advantage of being a -complete end-to-end compiler that can be run from a Scheme REPL. -It uses {\tt gcc}, targeting a 64-bit platform as the back-end, but I hope can -be modified to target other platforms without too much trouble, or even moved -off of C to target JavaScript, LLVM, or other back ends. - -\section{Other Uses of the Nanopass Frameowrk} -The nanopass framework was used to replace the original Chez Scheme -compiler~\cite{dybvig:csug9} with a nanopass version of the compiler. -The nanopass version has officially been released as Chez Scheme version 9.0. -Chez Scheme is a closed-source commercial compiler. - -The nanopass framework is also being used as part of the -\href{https://github.com/eholk/harlan}{Harlan} compiler. -Harlan is a general purpose language for developing programs for running on -the GPU. -Harlan uses an S-expression format that is compiled into C++ using OpenCL to -run computational kernels on the GPU. -The source code for Harlan is publicly available at -\href{https://github.com/eholk/harlan}{github.com/eholk/harlan}. - -\chapter{Defining Languages and Passes} % old 2.4, new 2.3 - -The nanopass framework builds on the prototype, originally developed by -Sarkar et al. -The examples in this section are pulled from the Scheme to C compiler available -at \href{https://github.com/akeep/scheme-to-c}{github.com/akeep/scheme-to-c}. - -\section{Defining languages} - -The nanopass framework operates over a set of compiler-writer-defined -languages. -Languages defined in this way are similar to context-free grammars, in that -they are composed of a set of terminals, a set of nonterminal symbols, a set of -productions for each nonterminal, and a start symbol from the set of -nonterminal symbols. -We refer to the start symbol as the entry nonterminal of the language. -An intermediate language definition for a simple variant of the Scheme -programming language, post macro expansion, might look like: - -{\small -\schemedisplay -(define-language Lsrc - (terminals - (symbol (x)) - (primitive (pr)) - (constant (c)) - (datum (d))) - (Expr (e body) - pr - x - c - (quote d) - (if e0 e1) - (if e0 e1 e2) - (or e* ...) - (and e* ...) - (not e) - (begin e* ... e) - (lambda (x* ...) body* ... body) - (let ([x* e*] ...) body* ... body) - (letrec ([x* e*] ...) body* ... body) - (set! x e) - (e e* ...))) -\endschemedisplay -} - -\noindent - -The \scheme{Lsrc} language defines a subset of Scheme suitable for our -example compiler. -It is the output language of a more general ``parser'' that -parses S-expressions into \scheme{Lsrc} language forms. -The \scheme{Lsrc} language consists of a set of terminals (listed in the -\scheme{terminals} form) and a single nonterminal \scheme{Expr}. -The terminals of the language are -\begin{itemize} - \item \scheme{symbol} (for variables), - \item \scheme{primitive} (for the subset of Scheme primitives support - by this language), - \item \scheme{constant} (for the subset of Scheme constants, and - \item \scheme{datum} (for the subset of Scheme datum supported by this language). -\end{itemize} -The compiler writer must supply a predicate corresponding to each terminal, -lexically visible where the language is defined. -The nanopass framework derives the predicate name from the terminal name by -adding a \scheme{?} to the terminal name. -In this case, the nanopass framework expects \scheme{symbol?}, -\scheme{primitive?}, \scheme{constant?}, and \scheme{datum?} to be -lexically visible where \scheme{Lsrc} is defined. - -Each terminal clause lists one or more meta-variables, used to refer to the -terminal in nonterminal productions. -Here, \scheme{x} refers to a \scheme{symbol}, \scheme{pr} refers to -a \scheme{primitive}, \scheme{c} refers to a \scheme{constant}, -and \scheme{d} refers to a \scheme{datum}. - -For our example compiler, the host Scheme system's \scheme{symbol?} is used -to determine when an item is a variable. - -The example compiler also selects a subset of primitives from Scheme and -represents these primitives as symbols. -A \scheme{primitive?} predicate like the following can be used to specify -this terminal.\footnote{In the example compiler, the primitives are specified -in separate association lists to capture the arity of each primitive and the -place in the compiler is handled as it goes through the compiler process. -This complexity has been eliminated for the dicussion here. -Please reference the source code for a more complete discussion of -primitive handling in the example compiler.} - -{\small -\schemedisplay -(define primitive? - (lambda (x) - (memq x - '(cons make-vector box car cdr vector-ref vector-length unbox - + - * / pair? null? boolean? vector? box? = < <= > >= eq? - vector-set! set-box!)))) -\endschemedisplay -} - -\noindent -Our example compiler also limits the constants that can be expressed to a subset of those allowed by Scheme. -The \scheme{constant?} predicate limits these to booleans (\scheme{#t} and -\scheme{#f}), null (\scheme{()}), and appropriately sized integers -(between $-2^{60}$ and $2^{60} - 1$). - -{\small -\schemedisplay -(define target-fixnum? - (lambda (x) - (and (and (integer? x) (exact? x)) - (<= (- (expt 2 60)) x (- (expt 2 60) 1))))) - -(define constant? - (lambda (x) - (or (target-fixnum? x) (boolean? x) (null? x)))) -\endschemedisplay -} - -\noindent -The example compiler limits the Scheme datum that can be represented to -constants, pairs, vectors, and boxes. -The \scheme{datum?} predicate can be defined as follows: - -{\small -\schemedisplay -(define datum? - (lambda (x) - (or (constant? x) - (and (box? x) (datum? (unbox x))) - (and (pair? x) (datum? (car x)) (datum? (cdr x))) - (and (vector? x) - (let loop ([i (vector-length x)]) - (or (fx=? i 0) - (let ([i (fx- i 1)]) - (and (datum? (vector-ref x i)) - (loop i))))))))) - -\endschemedisplay -} - -\noindent -The \scheme{Lsrc} language also defines the nonterminal \scheme{Expr}. -Nonterminals start with a name, followed by a list of meta-variables and a set -of grammar productions. -In this case, the name is \scheme{Expr}, and two meta-variables, \scheme{e} and -\scheme{body}, are specified. -Just like the meta-variables named in the terminals clause, nonterminal -meta-variables are used to represent the nonterminal in nonterminal -productions. -Each production follows one of three forms. -It is a single meta-variable, an S-expression that starts with a -keyword, or an S-expression that does not start with a keyword (referred to as an -\emph{implicit} production). -The S-expression forms cannot include keywords past the initial starting -keyword. -In \scheme{Lsrc}, the \scheme{x}, \scheme{c}, and \scheme{pr} productions are -the single meta-variable productions and indicate that a stand-alone -\scheme{symbol}, \scheme{constant}, or \scheme{primitive} are valid -\scheme{Expr}s. -The only implicit S-expression production is the \scheme{(e e* ...)} -production, and it indicates a call that takes zero or more -\scheme{Expr}s as arguments. -(The \scheme{*} suffix on \scheme{e} is used by convention to indicate -plurality and does not have any semantic meaning: It is the \scheme{...} that -indicates that the field can take zero or more \scheme{Expr}s.) -The rest of the productions are S-expression productions with keywords that -correspond to the Scheme syntax that they represent. - -In addition to the star, \scheme{*}, suffix mentioned earlier in the call -productions, meta-variable references can also use a -numeric suffix (as in the productions for \scheme{if}), a question mark (\scheme{?}), or a caret (\scheme{^}). -The \scheme{?} suffix is intended for use with \scheme{maybe} meta-variables, -and the \scheme{^} is used when expressing meta-variables with a more -mathematical syntax than the numeric suffixes provide. -Suffixes can also be used in combination. -References to meta-variables in a production must be unique, and the suffixes -allow the same root name to be used more than once. - -Language definitions can also include more than one nonterminal, as the -following language illustrates: - -{\small -\schemedisplay -(define-language L8 - (terminals - (symbol (x a)) - (constant (c)) - (void+primitive (pr))) - (entry Expr) - (Expr (e body) - x - le - (quote c) - (if e0 e1 e2) - (begin e* ... e) - (set! x e) - (let ([x* e*] ...) abody) - (letrec ([x* le*] ...) body) - (primcall pr e* ...) - (e e* ...)) - (AssignedBody (abody) - (assigned (a* ...) body) => body) - (LambdaExpr (le) - (lambda (x* ...) abody))) -\endschemedisplay -} - -\noindent -This language has three nonterminals, \scheme{Expr}, \scheme{AssignedBody}, -and \scheme{LambdaExpr}. -When more than one nonterminal is specified, one must be selected as the entry -point. -In language \scheme{L8}, the \scheme{Expr} nonterminal is selected as the entry -nonterminal by the \scheme{(entry Expr)} clause. -When the entry clause is not specified, the first nonterminal listed is -implicitly selected as the entry point. - -The \scheme{L8} language uses a single terminal meta-variable production, -\scheme{x}, -to indicate that a stand-alone \scheme{symbol} is a valid \scheme{Expr}. -In addition, the \scheme{L8} language uses a single nonterminal meta-variable -production, \scheme{le}, to indicate that any \scheme{LambdaExpr} production is -also a valid \scheme{Expr}. -The \scheme{LambdaExpr} is separated from \scheme{Expr} because the -\scheme{letrec} production is now limited to binding \scheme{symbol}s to -\scheme{LambdaExpr}s. - -The \scheme{assigned} production of the \scheme{AssignedBody} nonterminal -utilizes a the \scheme{=>} syntax to indicate a pretty unparsing form. -This allows the unparser that is automatically produced by -\scheme{define-language} to generate an S-expression that can be evaluated in -the host Scheme system. -In this case, the \scheme{assigned} from is not a valid Scheme form, so we -simply eliminated the \scheme{assigned} wrapper and list of assigned variables -when unparsing.\footnote{Unparsers can also produce the non-pretty from by -passing both the language form to be unparsed and a \scheme{#f} to indicate -the pretty form should not be used.} - -In addition to the nanopass framework providing a syntax for specifying list -structures in a language -production, it is also possible to indicate that a field of a language -production might not contain a (useful) value. -The following language has an example of this: - -{\small -\schemedisplay -(define-language Lopt - (terminals - (uvar (x)) - (label (l)) - (constant (c)) - (primitive (pr))) - (Expr (e body) - x - (quote c) - (begin e* ... e) - (lambda (x* ...) body) - (let ([x* e*] ...) body) - (letrec ([x* le*] ...) body) - (pr e* ...) - (call (maybe l) (maybe e) e* ...)) - (LambdaExpr (le) - (lambda (x* ...) body))) -\endschemedisplay -} - -\noindent -The \scheme{(maybe l)} field indicates that either a label, \scheme{l}, or -\scheme{#f} will be provided. -Here, \scheme{#f} is a stand-in for bottom, indicating that the value is not -specified. -The \scheme{(maybe e)} field indicates that either an \scheme{Expr} or -\scheme{#f} will be provided. - -Instead of using \scheme{(maybe l)} to indicate a label that might be provided, -a \scheme{maybe-label} terminal that serves the same purpose could be added. -It is also possible to eliminate the \scheme{(maybe e)} form, although it -requires the creation of a separate nonterminal that has both an \scheme{e} -production and a production to represent $\bot$, when no \scheme{Expr} is -available. - -\section{Extending languages\label{subsec:extended-define-language}} - -The first ``pass'' of the example compiler is a simple expander that produces -\scheme{Lsrc} language forms from S-expressions. -The next pass takes the \scheme{Lsrc} language and removes the one-armed-if -expressions, replacing them with a two-armed-if that results in the void value -being produced by the expression when the test clause is false. -code appropriate to construct these constants. -The output grammar of this pass changes just one production of the language, -exchanging potentially complex quoted datum with quoted -constants and making explicit the code to build the constant pairs and vectors when the program -begins execution. - -The compiler writer could specify the new language by rewriting the -\scheme{Lsrc} language and replacing the appropriate terminal forms. -Rewriting each language in its full form, however, can result in verbose -source code, particularly in a compiler like the class compiler, which has -nearly 30 different intermediate languages. -Instead, the nanopass framework supports a language extension form. -The output language can be specified as follows: - -{\small -\schemedisplay -(define-language L1 - (extends Lsrc) - (terminals - (- (primitive (pr))) - (+ (void+primitive (pr)))) - (Expr (e body) - (- (if e0 e1)))) -\endschemedisplay -} - -\noindent -The \scheme{L1} language removes the \scheme{primitive} terminal and replaces it -with the \scheme{void+primitive} terminal. -It also removes the \scheme{(if e0 e1)} production. -A language extension form is indicated by including the \scheme{extends} -clause, in this case \scheme{(extends Lsrc)}, that indicates that this is -an extension of the given base language. -In a language extension, the \scheme{terminals} form now contains -subtraction clauses, in -this case \scheme{(- (primitive (pr)))}, and addition clauses, in this case -\scheme{(+ (void+primitive (pr)))}. -These addition and subtraction clauses can contain one or more terminal -specifiers. -The nonterminal syntax is similarly modified, with the subtraction clause, in -this case \scheme{(- (if e0 e1))}, that indicates productions to be removed -and an addition clause that indicates productions to be added, in this case -no productions are added. - -The list of meta-variables indicated for the nonterminal form is also updated -to use the set in the extension language. -It is important to include not only the meta-variables named in the language -extension but also those for terminal and nonterminal forms that will be -maintained from the base language. -Otherwise, these meta-variables will be unbound in the extension language, -leading to errors. - -Nonterminals can be removed in an extended language by removing all of the -productions of the nonterminal. -New nonterminals can be added in an extended language by adding the -productions of the new nonterminal. -For instance, language \scheme{L15} removes the \scheme{x}, \scheme{(qoute c)}, -and \scheme{(label l)} productions from the \scheme{Expr} nonterminal and -adds the \scheme{SimpleExpr} nonterminal. - -{\small -\schemedisplay - (define-language L15 - (extends L14) - (Expr (e body) - (- x - (quote c) - (label l) - (primcall pr e* ...) - (e e* ...)) - (+ se - (primcall pr se* ...) => (pr se* ...) - (se se* ...))) - (SimpleExpr (se) - (+ x - (label l) - (quote c)))) -\endschemedisplay -} - -\subsection{The {\tt define-language} form} - -The \scheme{define-language} syntax has two related forms. -The first form fully specifies a new language. -The second form uses the \scheme{extends} clause to indicate that the language -is an extension of an existing base language. - -Both forms of \scheme{define-language} start with the same basic syntax: - -{\small -\schemedisplay -(define-language \var{language-name} \var{clause} ...) -\endschemedisplay -} - -\noindent -where \var{clause} is an \scheme{extension} clause, an \scheme{entry} clause, a -\scheme{terminals} clause, or a nonterminal clause. - -\noindent -\textbf{Extension clause.} -The extension clause indicates that the new language is an extension of an existing -language. -This clause slightly changes the syntax of the \scheme{define-language} form -and is described in Section~\ref{subsec:extended-define-language}. - -\noindent -\textbf{Entry clause.} -The entry clause specifies which nonterminal is the starting point for this -language. -This information is used when generating passes to determine which nonterminal -should be expected first by the pass. -This default can be overridden in a pass definition, as described in -Section~\ref{sec:pass-syntax}. -The entry clause has the following form: - -{\small -\schemedisplay -(entry \var{nonterminal-name}) -\endschemedisplay -} - -\noindent -where \var{nonterminal-name} corresponds to one of the nonterminals specified -in this language. -Only one entry clause can be specified in a language definition. - -\noindent -\textbf{Terminals clause.} -The terminals clause specifies one or more terminals used by the language. -For instance, in the \scheme{Lsrc} example language, the terminals clause -specifies three terminal types: \scheme{uvar}, \scheme{primitive}, and -\scheme{datum}. -The terminals clause has the following form: - -{\small -\schemedisplay -(terminals \var{terminal-clause} ...) -\endschemedisplay -} - -\noindent -where \var{terminal-clause} has one of the following forms: - -{\small -\schemedisplay -(\var{terminal-name} (\var{meta-var} ...)) -(=> (\var{terminal-name} (\var{meta-var} ...)) \var{prettifier}) -(\var{terminal-name} (\var{meta-var} ...)) => \var{prettifier} -\endschemedisplay -} - -Here, -\partopsep=-\parskip -\begin{itemize} -\item \var{terminal-name} is the name of the terminal, and a corresponding -\scheme{\var{terminal-name}?} predicate function exists to determine whether a -Scheme object is of this type when checking the output of a pass, -\item \var{meta-var} is the name of a meta-variable used for referring to this -terminal type in language and pass definitions, and -\item \var{prettifier} is a procedure expression of one argument used -when the language unparser is called in ``pretty'' mode to produce -a pretty, S-expression representation. -\end{itemize} -The final form is syntactic sugar for the form above it. -When the \var{prettifier} is omitted, no processing is done on the terminal -when the unparser runs. - -\noindent -\textbf{Nonterminal clause.} -A nonterminal clause specifies the valid productions in a language. -Each nonterminal clause has a name, a set of meta-variables, and a set of -productions. -A nonterminal clause has the following form: - -{\small -\schemedisplay -(\var{nonterminal-name} (\var{meta-var} ...) - \var{production-clause} - ...) -\endschemedisplay -} - -\noindent -where \var{nonterminal-name} is an identifier that names the nonterminal, -\var{meta-var} is the name of a meta-variable used when referring to this -nonterminal in language and pass definitions, and \var{production-clause} -has one of the following forms: - -{\small -\schemedisplay -\var{terminal-meta-var} -\var{nonterminal-meta-var} -\var{production-s-expression} -(\var{keyword} . \var{production-s-expression}) -\endschemedisplay -} - -\noindent -Here, -\begin{itemize} -\item \var{terminal-meta-var} is a terminal meta-variable that is a stand-alone -production for this nonterminal, -\item \var{nonterminal-meta-var} is a nonterminal meta-variable that -indicates that any form allowed by the specified nonterminal is also allowed by -this nonterminal, -\item \var{keyword} is an identifier that must be matched exactly when parsing -an S-expression representation, language input pattern, or language output -template, and -\item \var{production-s-expression} is an S-expression that represents a -pattern for production and has the following form: -\end{itemize} - -{\small -\schemedisplay -\var{meta-variable} -(maybe \var{meta-variable}) -(\var{production-s-expression} \var{ellipsis}) -(\var{production-s-expression} \var{ellipsis} \var{production-s-expression} ... . \var{production-s-expression}) -(\var{production-s-expression} . \var{production-s-expression}) -() -\endschemedisplay -} - -\noindent -Here, -\begin{itemize} -\item \var{meta-variable} is any terminal or nonterminal meta-variable -extended with an arbitrary number of digits, followed by an arbitrary -combination of \scheme{*}, \scheme{?}, or \scheme{^} characters; for example, -if the meta-variable is \scheme{e}, then \scheme{e1}, \scheme{e*}, \scheme{e?}, -and \scheme{e4*?} are all valid meta-variable expressions; -\item \scheme{(maybe \var{meta-variable})} indicates that an element in the -production is either of the type of the meta-variable or bottom (represented by -\scheme{#f}); and -\item \var{ellipsis} is the literal \scheme{...} and indicates that a list of -the \var{production-s-expression} that proceeds it is expected. -\end{itemize} -Thus, a Scheme language form such as \scheme{let} can be represented as a -language production as: - -{\small -\schemedisplay -(let ([x* e*] ...) body* ... body) -\endschemedisplay -} - -\noindent -where \scheme{let} is the \var{keyword}, \scheme{x*} is a meta-variable that -indicates a list of variables, \scheme{e*} and \scheme{body*} are -meta-variables that each indicate a list of expressions, and \scheme{body} is a -meta-variable that indicates a single expression. - -Using the \scheme{maybe} form, something similar to the named-let form could -be represented as follows: - -{\small -\schemedisplay -(let (maybe x) ([x* e*] ...) body* ... body) -\endschemedisplay -} - -\noindent -although this would be slightly different from the normal named-let form, in that -the non-named form would then need an explicit \scheme{#f} to indicate that no name -was specified. - -\subsection{Extensions with the {\tt define-language} form\label{subsubsec:extended-define-language}} - -A language defined as an extension of an existing language has a slightly -modified syntax to indicate what should be added to or removed from -the base language to create the new language. -A compiler writer indicates that a language is an extension by using an -extension clause. - -\noindent -\textbf{Extension clause.} -The extension clause has the following form: - -{\small -\schemedisplay -(extends \var{language-name}) -\endschemedisplay -} - -\noindent -where \var{language-name} is the name of an already defined language. -Only one extension clause can be specified in a language definition. - -\noindent -\textbf{Entry clause.} -The entry clause does not change syntactically in an extended language. -It can, however, name a nonterminal from the base language that is retained in -the extended language. - -\noindent -\textbf{Terminals clause.} -When a language derives from a base language, the \scheme{terminals} clause has the following form: - -{\small -\schemedisplay -(terminals \var{extended-terminal-clause} ...) -\endschemedisplay -} - -\noindent -where \var{extended-terminal-clause} has one of the following forms: - -{\small -\schemedisplay -(+ \var{terminal-clause} ...) -(- \var{terminal-clause} ...) -\endschemedisplay -} - -\noindent -where the \var{terminal-clause} uses the syntax for terminals specified in the -non-extended \scheme{terminals} form. -The \scheme{+} form indicates terminals that should be added to the new language. -The \scheme{-} form indicates terminals that should be removed from the list in -the old language when producing the new language. -Terminals not mentioned in a terminals clause will be copied unchanged into the new -language. -Note that adding and removing \var{meta-var}s from a terminal currently -requires removing the terminal type and re-adding it. -This can be done in the same step with a \scheme{terminals} clause, similar to the following: - -{\small -\schemedisplay -(terminals - (- (variable (x))) - (+ (variable (x y)))) -\endschemedisplay -} - -\noindent -\textbf{Nonterminal clause.} -When a language extends from a base language, a nonterminal clause has the -following form: - -{\small -\schemedisplay -(\var{nonterminal-name} (\var{meta-var} ...) - \var{extended-production-clause} - ...) -\endschemedisplay -} - -\noindent -where \var{extended-production-clause} has one of the following forms: - -{\small -\schemedisplay -(+ \var{production-clause} ...) -(- \var{production-clause} ...) -\endschemedisplay -} - -\noindent -The \scheme{+} form indicates nonterminal productions that should be added to -the nonterminal in the new language. -The \scheme{-} form indicates nonterminal productions that should not be -copied from the list of productions for this nonterminal in the base language when -producing the new language. -Productions not mentioned in a nonterminal clause will be copied unchanged into the -nonterminal in the new language. -If a nonterminal has all of its productions removed in a new language, the -nonterminal will be dropped in the new language. -Conversely, new nonterminals can be added by naming the new nonterminal and -using the \scheme{+} form to specify the productions of the new nonterminal. - -\subsection{Products of {\tt define-language}} - -The \scheme{define-language} form produces the following user-visible bindings: -\begin{itemize} -\item a language definition, bound to the specified \var{language-name}; -\item an unparser (named \scheme{unparse-\var{language-name}}) that can be used -to unparse a record-based representation back into an S-expression representation; and -\item a set of predicates that can be used to identify a term of the language -or a term from a specified nonterminal in the language. -\end{itemize} - -It also produces the following internal bindings: -\begin{itemize} -\item a meta-parser that can be used by the \scheme{define-pass} macro to parse -the patterns and templates used in passes and -\item a set of record definitions that will be used to represent the language -forms. -\end{itemize} - -The \scheme{Lsrc} language, for example, will bind the identifier -\scheme{Lsrc} to the language definition, produce an unparser named -\scheme{unparse-Lsrc}, and create two predicates, \scheme{Lsrc?} and -\scheme{Lsrc-Expr?}. -The language definition is used when the \var{language-name} is specified as -the base of a new language definition and in the definition of a pass. - -The \scheme{define-parser} form can also be used to create a simple parser for -parsing S-expressions into language forms as follows: - -{\small -\schemedisplay -(define-parser \var{parser-name} \var{language-name}) -\endschemedisplay -} - -\noindent -The parser does not support backtracking; thus, grammars must be specified, either by specifying a keyword or by having -different length S-expressions so that the productions are unique. - -For instance, the following language definition cannot be parsed because all -four of the \scheme{set!} forms have the same keyword and are S-expressions of -the same length: - -{\small -\schemedisplay -(define-language Lunparsable - (terminals - (variable (x)) - (binop (binop)) - (integer-32 (int32)) - (integer-64 (int64))) - (Program (prog) - (begin stmt* ... stmt)) - (Statement (stmt) - (set! x0 int64) - (set! x0 x1) - (set! x0 (binop x1 int32)) - (set! x0 (binop x1 x2)))) -\endschemedisplay -} - -\noindent -Instead, the \scheme{Statement} nonterminal must be broken into multiple -nonterminals, as in the following language: - -{\small -\schemedisplay -(define-language Lparsable - (terminals - (variable (x)) - (binop (binop)) - (integer-32 (int32)) - (integer-64 (int64))) - (Program (prog) - (begin stmt* ... stmt)) - (Statement (stmt) - (set! x rhs)) - (Rhs (rhs) - x - int64 - (binop x arg)) - (Argument (arg) - x - int32)) -\endschemedisplay -} - -\section{Defining passes\label{sec:define-pass}} - -Passes are used to specify transformations over languages defined by using -\scheme{define-language}. -Before going into the formal details of defining passes, we need to take a look -at a simple pass to convert an input program from the \scheme{Lsrc} -intermediate language to the \scheme{L1} intermediate language. -This pass removes the one-armed-if by making the -result of the \scheme{if} expression explicit when the predicate is false. - -We define a pass called \scheme{remove-one-armed-if} to accomplish this -task, without using any of the -catamorphism~\cite{Meijer:1991:FPB:645420.652535} or -autogeneration features of the nanopass framework. -Below, we can see how this feature helps eliminate boilerplate code. - -{\small -\schemedisplay -(define-pass remove-one-armed-if : Lsrc (e) -> L1 () - (Expr : Expr (e) -> Expr () - [(if ,e0 ,e1) `(if ,(Expr e0) ,(Expr e1) (void))] - [,pr pr] - [,x x] - [,c c] - [(quote ,d) `(quote ,d)] - [(if ,e0 ,e1 ,e2) `(if ,(Expr e0) ,(Expr e1) ,(Expr e2))] - [(or ,e* ...) `(or ,(map Expr e*) ...)] - [(and ,e* ...) `(and ,(map Expr e*) ...)] - [(not ,e) `(not ,(Expr e))] - [(begin ,e* ... ,e) `(begin ,(map Expr e*) ... ,(Expr e))] - [(lambda (,x* ...) ,body* ... ,body) - `(lambda (,x* ...) ,(map Expr body*) ... ,(Expr body))] - [(let ([,x* ,e*] ...) ,body* ... ,body) - `(let ([,x* ,(map Expr e*)] ...) - ,(map Expr body*) ... ,(Expr body))] - [(letrec ([,x* ,e*] ...) ,body* ... body) - `(letrec ([,x* ,(map Expr e*)] ...) - ,(map Expr body*) ... ,(Expr body))] - [(set! ,x ,e) `(set! ,x ,(Expr e))] - [(,e ,e* ...) `(,(Expr e) ,(map Expr e*) ...)]) - (Expr e)) -\endschemedisplay -} - -\noindent -The pass definition starts with a name (in this case, -\scheme{remove-one-armed-if}) -and a signature. -The signature starts with an input-language specifier (e.g. \scheme{Lsrc}), -along with a list of formals. -Here, there is just one formal, \scheme{e}, for the input-language term. -The second part of the signature has an output-language specifier (in this case, -\scheme{L1}), as well as a list of extra return values (in this case, empty). - -Following the name and signature, is an optional definitions clause, not -used in this pass. -The \scheme{definitions} clause can contain any Scheme expression valid in a -definition context. - -Next, a transformer from the input nonterminal \scheme{Expr} to the output -nonterminal \scheme{Expr} is defined. -The transformer is named \scheme{Expr} and has a signature similar to that -of the pass, with an input-language nonterminal and list of formals followed -by the output-language nonterminal and list of extra-return-value expressions. - -The transformer has a clause that processes each production of the \scheme{Expr} -nonterminal. -Each clause consists of an input pattern, an optional \scheme{guard} clause, -and one or more expressions that specify zero or more return values based on the -signature. -The input pattern is derived from the S-expression productions specified -in the input language. -Each variable in the pattern is denoted by unquote (\scheme{,}). -For instance, the clause for the \scheme{set!} production matches the pattern -\scheme{(set! ,x ,e)}, binds \scheme{x} to the \scheme{symbol} specified by the -\scheme{set!} and \scheme{e} to the \scheme{Expr} specified by the -\scheme{set!}. - -% I might do this as an asside, if I could figure out how to bend LaTeX to my -% will enough to do that. -The variable names used in pattern bindings are based on the meta-variables -listed in the language definition. -This allows the pattern to be further restricted. -For instance, if we wanted to match only \scheme{set!} forms that had a -variable reference as the RHS, we could specify our pattern as -\scheme{(set! ,x0 ,x1)}, which would be equivalent of using our original -pattern with the \scheme{guard} clause: \scheme{(guard (symbol? e))}. - -The output-language expression is constructed using the \scheme{`(set! ,x ,(Expr e))} quasiquoted template. -Here, quasiquote, (\scheme{`}), is rebound to a form that can construct language -forms based on the template, and unquote (\scheme{,}), is used to escape back -into Scheme. -The \scheme{,(Expr e)} thus puts the result of the recursive call of -\scheme{Expr} into the output-language \scheme{(set! x e)} form. - -Following the \scheme{Expr} transformer is the body of the pass, which calls -\scheme{Expr} to transform the \scheme{Lsrc} \scheme{Expr} term into an \scheme{L1} -\scheme{Expr} term and wraps the result in a \scheme{let} expression if any -structured quoted datum are found in the program that is being compiled. - -In place of the explicit recursive calls to \scheme{Expr}, the compiler writer -can use the catamorphism syntax to indicate the recurrence, as in the -following version of the pass. - -{\small -\schemedisplay -(define-pass remove-one-armed-if : Lsrc (e) -> L1 () - (Expr : Expr (e) -> Expr () - [(if ,[e0] ,[e1]) `(if ,e0 ,e1 (void))] - [,pr pr] - [,x x] - [,c c] - [(quote ,d) `(quote ,d)] - [(if ,[e0] ,[e1] ,[e2]) `(if ,e0 ,e1 ,e2)] - [(or ,[e*] ...) `(or ,e* ...)] - [(and ,[e*] ...) `(and ,e* ...)] - [(not ,[e]) `(not ,e)] - [(begin ,[e*] ... ,[e]) `(begin ,e* ... ,e)] - [(lambda (,x* ...) ,[body*] ... ,[body]) - `(lambda (,x* ...) ,body* ... ,body)] - [(let ([,x* ,[e*]] ...) ,[body*] ... ,[body]) - `(let ([,x* ,e*] ...) - ,body* ... ,body)] - [(letrec ([,x* ,[e*]] ...) ,[body*] ... ,[body]) - `(letrec ([,x* ,e*] ...) - ,body* ... ,body)] - [(set! ,x ,[e]) `(set! ,x ,e)] - [(,[e] ,[e*] ...) `(,e ,e* ...)]) - (Expr e)) -\endschemedisplay -} - -\noindent -Here, the square brackets that wrap the unquoted variable expression in a -pattern indicate that a catamorphism should be applied. -For instance, in the \scheme{set!} clause, the \scheme{,e} from the previous -pass becomes \scheme{,[e]}. -When the catamorphism is included on an element that is followed by an -ellipsis, \scheme{map} is used to process the elements of the list and to construct -the output list. - -% another place for this to be an aside with a link down to the -% catamorphism section -Using a catamorphism changes, slightly, the meaning of the meta-variables used -in the pattern matcher. -Instead of indicatinng a input language restriction that must be met, it -indicates an output type that is expected. -In the \scheme{set!} clause example, we use \scheme{e} for both, because our -input language and output language both use \scheme{e} to refer to -their \scheme{Expr} nonterminal. -The nanopass framwork uses the input type and the output type, along with any -additional input values and extra expected return values to determine which -transformer should be called. -In some cases, specifically where a single input nonterminal form is -transformed into an equivalent output nonterminal form, these transformers can -be autogenerated by the framework. - -Using catamorphisms helps to make the pass more succinct, but there is still -boilerplate code in the pass that the framework can fill in for the compiler -writer. -Several clauses simply match the input-language production and generate a matching -output-language production (modulo the catamorphisms for nested \scheme{Expr} forms). -Because the input and output languages are defined, the \scheme{define-pass} -macro can automatically generate these clauses. -Thus, the same functionality can be expressed as follows: - - -{\small -\schemedisplay -(define-pass remove-one-armed-if : Lsrc (e) -> L1 () - (Expr : Expr (e) -> Expr () - [(if ,[e0] ,[e1]) `(if ,e0 ,e1 (void))])) -\endschemedisplay -} - -\noindent -In this version of the pass, only the one-armed-\scheme{if} form -is explicitly processed. -The \scheme{define-pass} form automatically generates the other clauses. -Although all three versions of this pass perform the same task, the final form is the -closest to the initial intention of replacing just the one-armed-if form with a two-armed-if. - -In addition to \scheme{define-pass} autogenerating the clauses of a transformer, \scheme{define-pass} can also -autogenerate the transformers for nonterminals that must be traversed but are -otherwise unchanged in a pass. -For instance, one of the passes in the class compiler removes complex -expressions from the right-hand side of the \scheme{set!} form. -At this point in the compiler, the language has several nonterminals: - -{\small -\schemedisplay -(define-language L18 - (entry Program) - (terminals - (integer-64 (i)) - (effect+internal-primitive (epr)) - (non-alloc-value-primitive (vpr)) - (symbol (x l)) - (predicate-primitive (ppr)) - (constant (c))) - (Program (prog) - (labels ([l* le*] ...) l)) - (SimpleExpr (se) - x - (label l) - (quote c)) - (Value (v body) - (alloc i se) - se - (if p0 v1 v2) - (begin e* ... v) - (primcall vpr se* ...) - (se se* ...)) - (Effect (e) - (set! x v) - (nop) - (if p0 e1 e2) - (begin e* ... e) - (primcall epr se* ...) - (se se* ...)) - (Predicate (p) - (true) - (false) - (if p0 p1 p2) - (begin e* ... p) - (primcall ppr se* ...)) - (LocalsBody (lbody) - (locals (x* ...) body)) - (LambdaExpr (le) - (lambda (x* ...) lbody))) -\endschemedisplay -} - -\noindent -The pass, however, is only interested in the \scheme{set!} form and the -\scheme{Value} form in the right-hand-side position of the \scheme{set!} form. -Relying on the autogeneration of transformers, this pass can be written as: - -{\small -\schemedisplay -(define-pass flatten-set! : L18 (e) -> L19 () - (SimpleExpr : SimpleExpr (se) -> SimpleExpr ()) - (Effect : Effect (e) -> Effect () - [(set! ,x ,v) (flatten v x)]) - (flatten : Value (v x) -> Effect () - [,se `(set! ,x ,(SimpleExpr se))] - [(primcall ,vpr ,[se*] ...) `(set! ,x (primcall ,vpr ,se* ...))] - [(alloc ,i ,[se]) `(set! ,x (alloc ,i ,se))] - [(,[se] ,[se*] ...) `(set! ,x (,se ,se* ...))])) -\endschemedisplay -} - -\noindent -Here, the \scheme{Effect} transformer has just one clause for matching the -\scheme{set!} form. -The \scheme{flatten} transformer is called to produce the final \scheme{Effect} -form. -The \scheme{flatten} transformer, in turn, pushes the \scheme{set!} form into -the \scheme{if} and \scheme{begin} forms and processes the contents of these -forms, which produces a final \scheme{Effect} form. -Note that the \scheme{if} and \scheme{begin} forms do not need to be provided -by the compiler writer. -This is because the input and output language provide enough structure that the -nanopass framework can automatically generate the appropriate clauses. -In the case of \scheme{begin} it will push the \scheme{set!} form into the -final, value producing, expression of the \scheme{begin} form. -In the case of the \scheme{if} it will push the \scheme{set!} form into both -the consquent and alternative of the if form, setting the variable at the -final, value producing expression on both possible execution paths. -The \scheme{define-pass} macro autogenerates transformers for \scheme{Program}, -\scheme{LambdaExpr}, \scheme{LocalsBody}, \scheme{Value}, and -\scheme{Predicate} that recur through the input-language forms and produce the -output-language forms. -The \scheme{SimpleExpr} transformer only needs to be written to give a name to -the transformer so that it can be called by \scheme{flatten}. - -It is sometimes necessary to pass more information than just -the language term to a transformer. -The transformer syntax allows extra formals to be named to support passing this information. -For example, in the pass from the scheme to C compiler that converts the -\scheme{closures} form into explicit calls to procedure primitives, the closure -pointer, \scheme{cp}, and the list of free variables, \scheme{free*}, are passed -to the \scheme{Expr} transformer. - -{\small -\schemedisplay -(define-pass expose-closure-prims : L12 (e) -> L13 () - (Expr : Expr (e [cp #f] [free* '()]) -> Expr () - (definitions - (define handle-closure-ref - (lambda (x cp free*) - (let loop ([free* free*] [i 0]) - (cond - [(null? free*) x] - [(eq? x (car free*)) `(primcall closure-ref ,cp (quote ,i))] - [else (loop (cdr free*) (fx+ i 1))])))) - (define build-closure-set* - (lambda (x* l* f** cp free*) - (fold-left - (lambda (e* x l f*) - (let loop ([f* f*] [i 0] [e* e*]) - (if (null? f*) - (cons `(primcall closure-code-set! ,x (label ,l)) e*) - (loop (cdr f*) (fx+ i 1) - (cons `(primcall closure-data-set! ,x (quote ,i) - ,(handle-closure-ref (car f*) cp free*)) - e*))))) - '() - x* l* f**)))) - [(closures ([,x* ,l* ,f** ...] ...) - (labels ([,l2* ,[le*]] ...) ,[body])) - (let ([size* (map length f**)]) - `(let ([,x* (primcall make-closure (quote ,size*))] ...) - (labels ([,l2* ,le*] ...) - (begin - ,(build-closure-set* x* l* f** cp free*) ... - ,body))))] - [,x (handle-closure-ref x cp free*)] - [((label ,l) ,[e*] ...) `((label ,l) ,e* ...)] - [(,[e] ,[e*] ...) `((primcall closure-code ,e) ,e* ...)]) - (LabelsBody : LabelsBody (lbody) -> Expr ()) - (LambdaExpr : LambdaExpr (le) -> LambdaExpr () - [(lambda (,x ,x* ...) (free (,f* ...) ,[body x f* -> body])) - `(lambda (,x ,x* ...) ,body)])) -\endschemedisplay -} - -\noindent -The catamorphism and clause autogeneration facilities are also aware of the extra -formals expected by transformers. -In a catamorphism, this means that extra arguments need not be specified in -the catamorphism, if the formals are available in the transformer. -For instance, in the \scheme{Expr} transformer, -the catamorphism specifies only the binding of the output \scheme{Expr} form, -and \scheme{define-pass} matches the name of the formal to the transformer with the -expected argument. -In the \scheme{LambdaExpr} transformer, the extra arguments need to be -specified, both because they are not available as a formal of the transformer -and because the values change at the \scheme{LambdaExpr} boundary. -Autogenerated clauses in \scheme{Expr} also call the -\scheme{Expr} transformer with the extra arguments from the formals. - -The \scheme{expose-closure-prims} pass also specifies default values for the -extra arguments passed to the \scheme{Expr} transformer. -It defaults the \scheme{cp} variable to \scheme{#f} and the \scheme{free*} -variable to the empty list. -The default values will only be used in calls to the \scheme{Expr} transformer -when the no other value is available. -In this case, this happen only when the \scheme{Expr} transformer is first -called in the body of the pass. -This is consistent with the body of the program, which cannot contain any free -variables and hence does not need a closure pointer. -Once we begin processing within the body of a \scheme{lambda} we then have a -closure pointer, with the list of free variables, if any. - -Sometimes it is also necessary for a pass to return more than one value. -The nanopass framework relies upon Scheme's built-in functionality for dealing -with returning of multiple return values. -To inform the nanopass framework that a given transformer is returning more -than one value, we use the signature to tell the framework both how many values -we are expecting to return, and what the default values should be when a clause -is autogenerated. -For instance, the \scheme{uncover-free} pass returns two values, the language -form and the list of free variables. - -{\small -\schemedisplay -(define-pass uncover-free : L10 (e) -> L11 () - (Expr : Expr (e) -> Expr (free*) - [(quote ,c) (values `(quote ,c) '())] - [,x (values x (list x))] - [(let ([,x* ,[e* free**]] ...) ,[e free*]) - (values `(let ([,x* ,e*] ...) ,e) - (apply union (difference free* x*) free**))] - [(letrec ([,x* ,[le* free**]] ...) ,[body free*]) - (values `(letrec ([,x* ,le*] ...) ,body) - (difference (apply union free* free**) x*))] - [(if ,[e0 free0*] ,[e1 free1*] ,[e2 free2*]) - (values `(if ,e0 ,e1 ,e2) (union free0* free1* free2*))] - [(begin ,[e* free**] ... ,[e free*]) - (values `(begin ,e* ... ,e) (apply union free* free**))] - [(primcall ,pr ,[e* free**]...) - (values `(primcall ,pr ,e* ...) (apply union free**))] - [(,[e free*] ,[e* free**] ...) - (values `(,e ,e* ...) (apply union free* free**))]) - (LambdaExpr : LambdaExpr (le) -> LambdaExpr (free*) - [(lambda (,x* ...) ,[body free*]) - (let ([free* (difference free* x*)]) - (values `(lambda (,x* ...) (free (,free* ...) ,body)) free*))]) - (let-values ([(e free*) (Expr e)]) - (unless (null? free*) (error who "found unbound variables" free*)) - e)) -\endschemedisplay -} - -Transformers can also be written that handle terminals instead of nonterminals. -Because terminals have no structure, the body of such transformers is simply a -Scheme expression. -The Scheme to C compiler does not make use of this feature, but we could -imagine a pass where references to variables are replaced with already -specified locations, such as the following pass: - -{\small -\schemedisplay -(define-pass replace-variable-refereces : L23 (x) -> L24 () - (uvar-reg-fv : symbol (x env) -> location () - (cond [(and (uvar? x) (assq x env)) => cdr] [else x])) - (SimpleExpr : SimpleExpr (x env) -> Triv ()) - (Rhs : Rhs (x env) -> Rhs ()) - (Pred : Pred (x env) -> Pred ()) - (Effect : Effect (x env) -> Effect ()) - (Value : Value (x env) -> Value ()) - (LocalsBody : LocalsBody (x) -> Value () - [(finished ([,x* ,loc*] ...) ,vbody) (Value vbody (map cons x* loc*))])) -\endschemedisplay -} - -\noindent -The two interesting parts of this pass are the \scheme{LocalsBody} transformer -that creates the environment that maps variables to locations and the -\scheme{uvar-reg-fv} transformer that replaces variables with the appropriate -location. -In this pass, transformers cannot be autogenerated because extra arguments are -needed, and the nanopass framework only autogenerates transformers without extra -arguments or return values. -The autogeneration is limited to help reign in some of the unpredictable -behavior that can result from autogenerated transformers. - -Passes can also be written that do not take a language form but that produce a -language form. -The initial parser for the Scheme to C compiler is a good example of this. -It expects an S-expression that conforms to an input grammar for the subset of -Scheme supported by the compiler. - -{\small -\schemedisplay -(define-pass parse-and-rename : * (e) -> Lsrc () - (definitions - (define process-body - (lambda (who env body* f) - (when (null? body*) (error who "invalid empty body")) - (let loop ([body (car body*)] [body* (cdr body*)] [rbody* '()]) - (if (null? body*) - (f (reverse rbody*) (Expr body env)) - (loop (car body*) (cdr body*) - (cons (Expr body env) rbody*)))))) - (define vars-unique? - (lambda (fmls) - (let loop ([fmls fmls]) - (or (null? fmls) - (and (not (memq (car fmls) (cdr fmls))) - (loop (cdr fmls))))))) - (define unique-vars - (lambda (env fmls f) - (unless (vars-unique? fmls) - (error 'unique-vars "invalid formals" fmls)) - (let loop ([fmls fmls] [env env] [rufmls '()]) - (if (null? fmls) - (f env (reverse rufmls)) - (let* ([fml (car fmls)] [ufml (unique-var fml)]) - (loop (cdr fmls) (cons (cons fml ufml) env) - (cons ufml rufmls))))))) - (define process-bindings - (lambda (rec? env bindings f) - (let loop ([bindings bindings] [rfml* '()] [re* '()]) - (if (null? bindings) - (unique-vars env rfml* - (lambda (new-env rufml*) - (let ([env (if rec? new-env env)]) - (let loop ([rufml* rufml*] - [re* re*] - [ufml* '()] - [e* '()]) - (if (null? rufml*) - (f new-env ufml* e*) - (loop (cdr rufml*) (cdr re*) - (cons (car rufml*) ufml*) - (cons (Expr (car re*) env) e*))))))) - (let ([binding (car bindings)]) - (loop (cdr bindings) (cons (car binding) rfml*) - (cons (cadr binding) re*))))))) - (define Expr* - (lambda (e* env) - (map (lambda (e) (Expr e env)) e*))) - (with-output-language (Lsrc Expr) - (define build-primitive - (lambda (as) - (let ([name (car as)] [argc (cdr as)]) - (cons name - (if (< argc 0) - (error who - "primitives with arbitrary counts are not currently supported" - name) - (lambda (env . e*) - (if (= (length e*) argc) - `(,name ,(Expr* e* env) ...) - (error name "invalid argument count" - (cons name e*))))))))) - (define initial-env - (cons* - (cons 'quote (lambda (env d) - (unless (datum? d) - (error 'quote "invalid datum" d)) - `(quote ,d))) - (cons 'if (case-lambda - [(env e0 e1) `(if ,(Expr e0 env) ,(Expr e1 env))] - [(env e0 e1 e2) - `(if ,(Expr e0 env) ,(Expr e1 env) ,(Expr e2 env))] - [x (error 'if (if (< (length x) 3) - "too few arguments" - "too many arguments") - x)])) - (cons 'or (lambda (env . e*) `(or ,(Expr* e* env) ...))) - (cons 'and (lambda (env . e*) `(and ,(Expr* e* env) ...))) - (cons 'not (lambda (env e) `(not ,(Expr e env)))) - (cons 'begin (lambda (env . e*) - (process-body env e* - (lambda (e* e) - `(begin ,e* ... ,e))))) - (cons 'lambda (lambda (env fmls . body*) - (unique-vars env fmls - (lambda (env fmls) - (process-body 'lambda env body* - (lambda (body* body) - `(lambda (,fmls ...) - ,body* ... ,body))))))) - (cons 'let (lambda (env bindings . body*) - (process-bindings #f env bindings - (lambda (env x* e*) - (process-body 'let env body* - (lambda (body* body) - `(let ([,x* ,e*] ...) ,body* ... ,body))))))) - (cons 'letrec (lambda (env bindings . body*) - (process-bindings #t env bindings - (lambda (env x* e*) - (process-body 'letrec env body* - (lambda (body* body) - `(letrec ([,x* ,e*] ...) - ,body* ... ,body))))))) - (cons 'set! (lambda (env x e) - (cond - [(assq x env) => - (lambda (as) - (let ([v (cdr as)]) - (if (symbol? v) - `(set! ,v ,(Expr e env)) - (error 'set! "invalid syntax" - (list 'set! x e)))))] - [else (error 'set! "set to unbound variable" - (list 'set! x e))]))) - (map build-primitive user-prims))) - ;;; App - helper for handling applications. - (define App - (lambda (e env) - (let ([e (car e)] [e* (cdr e)]) - `(,(Expr e env) ,(Expr* e* env) ...)))))) - (Expr : * (e env) -> Expr () - (cond - [(pair? e) - (cond - [(assq (car e) env) => - (lambda (as) - (let ([v (cdr as)]) - (if (procedure? v) - (apply v env (cdr e)) - (App e env))))] - [else (App e env)])] - [(symbol? e) - (cond - [(assq e env) => - (lambda (as) - (let ([v (cdr as)]) - (cond - [(symbol? v) v] - [(primitive? e) e] - [else (error who "invalid syntax" e)])))] - [else (error who "unbound variable" e)])] - [(constant? e) e] - [else (error who "invalid expression" e)])) - (Expr e initial-env)) -\endschemedisplay -} - -\noindent -The \scheme{parse-and-rename} pass is structured similarly to a simple expander with -keywords and primitives.\footnote{It could easily be extended to handle simple macros, in this case, just the fixed \scheme{and} macro, -\scheme{or} macro, and \scheme{not} macro would be available.} -It also performs syntax checking to ensure that the input grammar conforms to -the expected input grammar. -Finally, it produces an \scheme{Lsrc} language term that represents the Scheme -program to be compiled. - -In the pass syntax, the \scheme{*} in place of the input-language name indicates -that no input-language term should be expected. -The \scheme{Expr} and \scheme{Application} transformers do not have pattern -matching clauses, as the input could be of any form. -The quasiquote is, however, rebound because an output language is specified. - -It can also be useful to create passes without an output language. -The final pass of the Scheme to C compiler is the code generator that emits C -code. - -{\small -\schemedisplay -(define-pass generate-c : L22 (e) -> * () - (definitions - (define string-join - (lambda (str* jstr) - (cond - [(null? str*) ""] - [(null? (cdr str*)) (car str*)] - [else (string-append (car str*) jstr (string-join (cdr str*) jstr))]))) - (define symbol->c-id - (lambda (sym) - (let ([ls (string->list (symbol->string sym))]) - (if (null? ls) - "_" - (let ([fst (car ls)]) - (list->string - (cons - (if (char-alphabetic? fst) fst #\_) - (map (lambda (c) - (if (or (char-alphabetic? c) - (char-numeric? c)) - c - #\_)) - (cdr ls))))))))) - (define format-function-header - (lambda (l x*) - (format "ptr ~a(~a)" l - (string-join - (map - (lambda (x) - (format "ptr ~a" (symbol->c-id x))) - x*) - ", ")))) - (define format-label-call - (lambda (l se*) - (format " ~a(~a)" (symbol->c-id l) - (string-join - (map (lambda (se) - (format "(ptr)~a" (format-simple-expr se))) - se*) - ", ")))) - (define format-general-call - (lambda (se se*) - (format "((ptr (*)(~a))~a)(~a)" - (string-join (make-list (length se*) "ptr") ", ") - (format-simple-expr se) - (string-join - (map (lambda (se) - (format "(ptr)~a" (format-simple-expr se))) - se*) - ", ")))) - (define format-binop - (lambda (op se0 se1) - (format "((long)~a ~a (long)~a)" - (format-simple-expr se0) - op - (format-simple-expr se1)))) - (define format-set! - (lambda (x rhs) - (format "~a = (ptr)~a" (symbol->c-id x) (format-rhs rhs))))) - (emit-function-decl : LambdaExpr (le l) -> * () - [(lambda (,x* ...) ,lbody) - (printf "~a;~%" (format-function-header l x*))]) - (emit-function-def : LambdaExpr (le l) -> * () - [(lambda (,x* ...) ,lbody) - (printf "~a {~%" (format-function-header l x*)) - (emit-function-body lbody) - (printf "}~%~%")]) - (emit-function-body : LocalsBody (lbody) -> * () - [(locals (,x* ...) ,body) - (for-each (lambda (x) (printf " ptr ~a;~%" (symbol->c-id x))) x*) - (emit-value body x*)]) - (emit-value : Value (v locals*) -> * () - [(if ,p0 ,v1 ,v2) - (printf " if (~a) {~%" (format-predicate p0)) - (emit-value v1 locals*) - (printf " } else {~%") - (emit-value v2 locals*) - (printf " }~%")] - [(begin ,e* ... ,v) - (for-each emit-effect e*) - (emit-value v locals*)] - [,rhs (printf " return (ptr)~a;\n" (format-rhs rhs))]) - (format-predicate : Predicate (p) -> * (str) - [(if ,p0 ,p1 ,p2) - (format "((~a) ? (~a) : (~a))" - (format-predicate p0) - (format-predicate p1) - (format-predicate p2))] - [(<= ,se0 ,se1) (format-binop "<=" se0 se1)] - [(< ,se0 ,se1) (format-binop "<" se0 se1)] - [(= ,se0 ,se1) (format-binop "==" se0 se1)] - [(true) "1"] - [(false) "0"] - [(begin ,e* ... ,p) - (string-join - (fold-right (lambda (e s*) (cons (format-effect e) s*)) - (list (format-predicate p)) e*) - ", ")]) - (format-effect : Effect (e) -> * (str) - [(if ,p0 ,e1 ,e2) - (format "((~a) ? (~a) : (~a))" - (format-predicate p0) - (format-effect e1) - (format-effect e2))] - [((label ,l) ,se* ...) (format-label-call l se*)] - [(,se ,se* ...) (format-general-call se se*)] - [(set! ,x ,rhs) (format-set! x rhs)] - [(nop) "0"] - [(begin ,e* ... ,e) - (string-join - (fold-right (lambda (e s*) (cons (format-effect e) s*)) - (list (format-effect e)) e*) - ", ")] - [(mset! ,se0 ,se1? ,i ,se2) - (if se1? - (format "((*((ptr*)((long)~a + (long)~a + ~d))) = (ptr)~a)" - (format-simple-expr se0) (format-simple-expr se1?) - i (format-simple-expr se2)) - (format "((*((ptr*)((long)~a + ~d))) = (ptr)~a)" - (format-simple-expr se0) i (format-simple-expr se2)))]) - (format-simple-expr : SimpleExpr (se) -> * (str) - [,x (symbol->c-id x)] - [,i (number->string i)] - [(label ,l) (format "(*~a)" (symbol->c-id l))] - [(logand ,se0 ,se1) (format-binop "&" se0 se1)] - [(shift-right ,se0 ,se1) (format-binop ">>" se0 se1)] - [(shift-left ,se0 ,se1) (format-binop "<<" se0 se1)] - [(divide ,se0 ,se1) (format-binop "/" se0 se1)] - [(multiply ,se0 ,se1) (format-binop "*" se0 se1)] - [(subtract ,se0 ,se1) (format-binop "-" se0 se1)] - [(add ,se0 ,se1) (format-binop "+" se0 se1)] - [(mref ,se0 ,se1? ,i) - (if se1? - (format "(*((ptr)((long)~a + (long)~a + ~d)))" - (format-simple-expr se0) - (format-simple-expr se1?) i) - (format "(*((ptr)((long)~a + ~d)))" (format-simple-expr se0) i))]) - ;; prints expressions in effect position into C statements - (emit-effect : Effect (e) -> * () - [(if ,p0 ,e1 ,e2) - (printf " if (~a) {~%" (format-predicate p0)) - (emit-effect e1) - (printf " } else {~%") - (emit-effect e2) - (printf " }~%")] - [((label ,l) ,se* ...) (printf " ~a;\n" (format-label-call l se*))] - [(,se ,se* ...) (printf " ~a;\n" (format-general-call se se*))] - [(set! ,x ,rhs) (printf " ~a;\n" (format-set! x rhs))] - [(nop) (if #f #f)] - [(begin ,e* ... ,e) - (for-each emit-effect e*) - (emit-effect e)] - [(mset! ,se0 ,se1? ,i ,se2) - (if se1? - (printf "(*((ptr*)((long)~a + (long)~a + ~d))) = (ptr)~a;\n" - (format-simple-expr se0) (format-simple-expr se1?) - i (format-simple-expr se2)) - (printf "(*((ptr*)((long)~a + ~d))) = (ptr)~a;\n" - (format-simple-expr se0) i (format-simple-expr se2)))]) - ;; formats the right-hand side of a set! into a C expression - (format-rhs : Rhs (rhs) -> * (str) - [((label ,l) ,se* ...) (format-label-call l se*)] - [(,se ,se* ...) (format-general-call se se*)] - [(alloc ,i ,se) - (if (use-boehm?) - (format "(ptr)((long)GC_MALLOC(~a) + ~dl)" - (format-simple-expr se) i) - (format "(ptr)((long)malloc(~a) + ~dl)" - (format-simple-expr se) i))] - [,se (format-simple-expr se)]) - ;; emits a C program for our progam expression - (Program : Program (p) -> * () - [(labels ([,l* ,le*] ...) ,l) - (let ([l (symbol->c-id l)] [l* (map symbol->c-id l*)]) - (define-syntax emit-include - (syntax-rules () - [(_ name) (printf "#include <~s>\n" 'name)])) - (define-syntax emit-predicate - (syntax-rules () - [(_ PRED_P mask tag) - (emit-c-macro PRED_P (x) "(((long)x & ~d) == ~d)" mask tag)])) - (define-syntax emit-eq-predicate - (syntax-rules () - [(_ PRED_P rep) - (emit-c-macro PRED_P (x) "((long)x == ~d)" rep)])) - (define-syntax emit-c-macro - (lambda (x) - (syntax-case x() - [(_ NAME (x* ...) fmt args ...) - #'(printf "#define ~s(~a) ~a\n" 'NAME - (string-join (map symbol->string '(x* ...)) ", ") - (format fmt args ...))]))) - ;; the following printfs output the tiny C runtime we are using - ;; to wrap the result of our compiled Scheme program. - (emit-include stdio.h) - (if (use-boehm?) - (emit-include gc.h) - (emit-include stdlib.h)) - (emit-predicate FIXNUM_P fixnum-mask fixnum-tag) - (emit-predicate PAIR_P pair-mask pair-tag) - (emit-predicate BOX_P box-mask box-tag) - (emit-predicate VECTOR_P vector-mask vector-tag) - (emit-predicate PROCEDURE_P closure-mask closure-tag) - (emit-eq-predicate TRUE_P true-rep) - (emit-eq-predicate FALSE_P false-rep) - (emit-eq-predicate NULL_P null-rep) - (emit-eq-predicate VOID_P void-rep) - (printf "typedef long* ptr;\n") - (emit-c-macro FIX (x) "((long)x << ~d)" fixnum-shift) - (emit-c-macro UNFIX (x) "((long)x >> ~d)" fixnum-shift) - (emit-c-macro UNBOX (x) "((ptr)*((ptr)((long)x - ~d)))" box-tag) - (emit-c-macro VECTOR_LENGTH_S (x) "((ptr)*((ptr)((long)x - ~d)))" vector-tag) - (emit-c-macro VECTOR_LENGTH_C (x) "UNFIX(VECTOR_LENGTH_S(x))") - (emit-c-macro VECTOR_REF (x i) "((ptr)*((ptr)((long)x - ~d + ((i+1) * ~d))))" - vector-tag word-size) - (emit-c-macro CAR (x) "((ptr)*((ptr)((long)x - ~d)))" pair-tag) - (emit-c-macro CDR (x) "((ptr)*((ptr)((long)x - ~d + ~d)))" pair-tag word-size) - (printf "void print_scheme_value(ptr x) {\n") - (printf " long i, veclen;\n") - (printf " ptr p;\n") - (printf " if (TRUE_P(x)) {\n") - (printf " printf(\"#t\");\n") - (printf " } else if (FALSE_P(x)) {\n") - (printf " printf(\"#f\");\n") - (printf " } else if (NULL_P(x)) {\n") - (printf " printf(\"()\");\n") - (printf " } else if (VOID_P(x)) {\n") - (printf " printf(\"(void)\");\n") - (printf " } else if (FIXNUM_P(x)) {\n") - (printf " printf(\"%ld\", UNFIX(x));\n") - (printf " } else if (PAIR_P(x)) {\n") - (printf " printf(\"(\");\n") - (printf " for (p = x; PAIR_P(p); p = CDR(p)) {\n") - (printf " print_scheme_value(CAR(p));\n") - (printf " if (PAIR_P(CDR(p))) { printf(\" \"); }\n") - (printf " }\n") - (printf " if (NULL_P(p)) {\n") - (printf " printf(\")\");\n") - (printf " } else {\n") - (printf " printf(\" . \");\n") - (printf " print_scheme_value(p);\n") - (printf " printf(\")\");\n") - (printf " }\n") - (printf " } else if (BOX_P(x)) {\n") - (printf " printf(\"#(box \");\n") - (printf " print_scheme_value(UNBOX(x));\n") - (printf " printf(\")\");\n") - (printf " } else if (VECTOR_P(x)) {\n") - (printf " veclen = VECTOR_LENGTH_C(x);\n") - (printf " printf(\"#(\");\n") - (printf " for (i = 0; i < veclen; i += 1) {\n") - (printf " print_scheme_value(VECTOR_REF(x,i));\n") - (printf " if (i < veclen) { printf(\" \"); } \n") - (printf " }\n") - (printf " printf(\")\");\n") - (printf " } else if (PROCEDURE_P(x)) {\n") - (printf " printf(\"#(procedure)\");\n") - (printf " }\n") - (printf "}\n") - (map emit-function-decl le* l*) - (map emit-function-def le* l*) - (printf "int main(int argc, char * argv[]) {\n") - (printf " print_scheme_value(~a());\n" l) - (printf " printf(\"\\n\");\n") - (printf " return 0;\n") - (printf "}\n"))])) -\endschemedisplay -} - -\noindent -Again, a \scheme{*} is used to indicate that there is no language form in this -case for the output language. -The C code is printed to the standard output port. -Thus, there is no need -for any return value from this pass. - -Passes can also return a value that is not a language form. -For instance, we could write the \scheme{simple?} predicate from \scheme{purify-letrec} pass as its own pass, rather than using the \scheme{nanopass-case} form. -It would look something like the following: - -{\small -\schemedisplay -(define-pass simple? : (L8 Expr) (e bound* assigned*) -> * (bool) - (simple? : Expr (e) -> * (bool) - [(quote ,c) #t] - [,x (not (or (memq x bound*) (memq x assigned*)))] - [(primcall ,pr ,e* ...) - (and (effect-free-prim? pr) (for-all simple? e*))] - [(begin ,e* ... ,e) (and (for-all simple? e*) (simple? e))] - [(if ,e0 ,e1 ,e2) (and (simple? e0) (simple? e1) (simple? e2))] - [else #f]) - (simple? e)) -\endschemedisplay -} - -\noindent -Here, the extra return value is indicated as \scheme{bool}. -The \scheme{bool} here is used to indicate to \scheme{define-pass} that an -extra value is being returned. -Any expression can be used in this position. -In this case, the \scheme{bool} identifier will simply be an unbound variable -if it is ever manifested. -It is not manifested in this case, however, because the body is explicitly -specified; thus, no code will be autogenerated for the body of the pass. - -\subsection{The {\tt define-pass} syntactic form\label{sec:pass-syntax}} - -The \scheme{define-pass} form has the following syntax. - -{\small -\schemedisplay -(define-pass \var{name} : \var{lang-specifier} (\var{fml} ...) -> \var{lang-specifier} (\var{extra-return-val-expr} ...) - \var{definitions-clause} - \var{transformer-clause} ... - \var{body-expr} ...) -\endschemedisplay -} - -\noindent -where \var{name} is an identifier to use as the name for the procedure -definition. -The \var{lang-specifier} has one of the following forms: - -{\small -\schemedisplay -* -\var{lang-name} -(\var{lang-name} \var{nonterminal-name}) -\endschemedisplay -} - -\noindent -where -\begin{itemize} -\item \var{lang-name} refers to a language defined with the -\scheme{define-language} form, and -\item \var{nonterminal-name} refers to a nonterminal named within the language -definition. -\end{itemize} -When the \scheme{*} form is used as the input \var{lang-specifier}, it indicates -that the pass does not expect an input-language term. -When there is no input language, the transformers within the pass do not have -clauses with pattern matches because, without an input language, the \scheme{define-pass} macro -does not know what the structure of the input term will be. -When the \scheme{*} form is used as the output \var{lang-specifier}, it -indicates that the pass does not produce an output-language term and should not -be checked. -When there is no output language, the transformers within the pass do not bind -\scheme{quasiquote}, and there are no templates on the right-hand side of the -transformer matches. -It is possible to use the \scheme{*} specifier for both the input and output -\var{lang-specifier}. -This effectively turns the pass, and the transformers contained within it, into an -ordinary Scheme function. - -When the \var{lang-name} form is used as the input \var{lang-specifier}, it -indicates that the pass expects an input-language term that is one of the -productions from the entry nonterminal. -When the \var{lang-name} form is used as the output \var{lang-specifier}, it -indicates that the pass expects that an output-language term will be produced and -checked to be one of the records that represents a production of the entry -nonterminal. - -When the (\var{lang-name} \var{nonterminal-name}) form is used as the -input-language specifier, it indicates that the input-language term will be a -production from the specified nonterminal in the specified input language. -When the (\var{lang-name} \var{nonterminal-name}) form is used as the -output-language specifier, it indicates that the pass will produce an output -production from the specified nonterminal of the specified output language. - -The \var{fml} is a Scheme identifier, and if the input \var{lang-specifier} is -not \scheme{*}, the first \var{fml} refers to the input-language term. - -The \var{extra-return-val-expr} is any valid Scheme expression that is valid in value context. -These expressions are scoped within the binding of the identifiers named as -\var{fml}s. - -The optional \var{definitions-clause} has the following form: - -{\small -\schemedisplay -(definitions \var{scheme-definition} ...) -\endschemedisplay -} - -\noindent -where \var{scheme-definition} is any Scheme expression that can be used in -definition context. -Definitions in the \var{definitions-clause} are in the same lexical scope as -the transformers, which means that procedures and macros defined in the -\var{definitions-clause} can refer to any transformer named in a -\var{transformer-clause}. - -The \var{definitions-clause} is followed by zero or more -\var{transformer-clauses}s of the following form: - -{\small -\schemedisplay -(\var{name} : \var{nt-specifier} (\var{fml-expr} ...) -> \var{nt-specifier} (\var{extra-return-val-expr} ...) - \var{definitions-clause}? - \var{transformer-body}) -\endschemedisplay -} - -\noindent -where \var{name} is a Scheme identifier that can be used to refer to the transformer within the pass. -The input \var{nt-specifier} is one of the following two forms: - -{\small -\schemedisplay -* -\var{nonterminal-name} -\endschemedisplay -} - -\noindent -When the \scheme{*} form is used as the input nonterminal, it indicates that no -input nonterminal form is expected and that the body of the -\var{transformer-body} will not contain pattern matching clauses. -When the \scheme{*} form is used as the output nonterminal, \scheme{quasiquote} -will not be rebound, and no output-language templates are available. -When both the input and output \var{nt-specifier} are \scheme{*}, the -transformer is effectively an ordinary Scheme procedure. - -The \var{fml-expr} has one of the following two forms: - -{\small -\schemedisplay -\var{fml} -[\var{fml} \var{default-val-expr}] -\endschemedisplay -} - -\noindent -where \var{fml} is a Scheme identifier and \var{default-val-expr} is a Scheme -expression. -The \var{default-val-expr} is used when an argument is not specified in a -catamorphism or when a matching \scheme{fml} is not available in the calling -transformer. -All arguments must be explicitly provided when the transformer is called as an -ordinary Scheme procedure. -Using the catamorphism syntax, the arguments can be explicitly supplied, using -the syntax discussed on page~\pageref{cata:syntax}. -It can also be specified implicitly. -Arguments are filled in implicitly in catamorphisms that do not explicitly -provide the arguments and in autogenerated clauses when the nonterminal -elements of a production are processed. -These implicitly supplied formals are handled by looking for a formal in the -calling transformer that has the same name as the formal expected by the target -transformer. -If no matching formal is found, and the target transformer specifies a default -value, the default value will be used in the call; otherwise, another target -transformer must be found, a new transformer must be autogenerated, or an -exception must be raised to indicate that no transformer was found and none can -be autogenerated. - -The \var{extra-return-val-expr} can be any Scheme expression. -These expressions are scoped within the \var{fml}s bound by the transformer. -This allows an input formal to be returned as an extra return value, implicitly -in the autogenerated clauses. -This can be useful for threading values through a transformer. - -The optional \var{definitions-clause} can include any Scheme expression that -can be placed in a definition context. -These definitions are scoped within the transformer. -When an output nonterminal is specified, the \scheme{quasiquote} is also bound -within the body of the \scheme{definitions} clause to allow language term -templates to be included in the body of the definitions. - -When the input \var{nt-specifier} is not \scheme{*}, the -\var{transformer-body} has one of the following forms: - -{\small -\schemedisplay -[\var{pattern} \var{guard-clause} \var{body*} ... \var{body}] -[\var{pattern} \var{body*} ... \var{body}] -[else \var{body*} ... \var{body}] -\endschemedisplay -} - -\noindent -where the \scheme{else} clause must be the last one listed in a transformer and -prevents autogeneration of missing clauses (because the \scheme{else} clause is -used in place of the autogenerated clauses). -The \var{pattern} is an S-expression pattern, based on the S-expression -productions used in the language definition. -Patterns can be arbitrarily nested. -Variables bound by the pattern are preceded by an \scheme{unquote} and are -named based on the meta-variables named in the language definition. -The variable name can be used to restrict the pattern by using a meta-variable -that is more specific than the one specified in the language definition. -The \var{pattern} can also contain catamorphisms that have one of the -following forms: - -{\small -\label{cata:syntax} -\schemedisplay -[\var{Proc-expr} : \var{input-fml} \var{arg} ... -> \var{output-fml} \var{extra-rv-fml} ...] -[\var{Transformer-name} : \var{output-fml} \var{extra-rv-fml} ...] -[\var{input-fml} \var{arg} ... -> \var{output-fml} \var{extra-rv-fml} ...] -[\var{output-fml} \var{extra-rv-fml} ...] -\endschemedisplay -} - -\noindent -In the first form, the \var{Proc-expr} is an explicitly specified procedure -expression, the \var{input-fml} and all arguments to the procedure are explicitly specified, and the results of calling the \var{Proc-expr} are bound by the \var{output-fml} and \var{extra-rv-fml}s. -Note that the \var{Proc-expr} may be a \var{Transformer-name}. -In the second form, the \var{Transformer-name} is an identifier that refers to -a transformer named in this pass. -The \scheme{define-pass} macro determines, based on the signature of the -transformer referred to by the \var{Transformer-name}, what arguments should be -supplied to the transformer. -In the last two forms, the transformer is determined automatically. -In the third form, the nonterminal type associated with the \var{input-fml}, -the \var{arg}s, the output nonterminal type based on the \var{output-fml}, and -the \var{extra-rv-fml}s are used to determine the transformer to call. -In the final form, the nonterminal type for the field within the production, -along with the formals to the calling transformer, the output nonterminal type -based on the \var{output-fml}, and the \var{extra-rv-fml}s are used to -determine the transformer to call. -In the two forms where the transformer is not explicitly named, a new -transformer can be autogenerated when no \var{arg}s and no \var{extra-rv-fml}s -are specified. -This limitation is in place to avoid creating a transformer with extra formals -whose use is unspecified and extra return values with potentially dubious -return-value expressions. - -The \var{input-fml} is a Scheme identifier with a name based on the -meta-variables named in the input-language definition. -The specification of a more restrictive meta-variable name can be used to further -restrict the pattern. -The \var{output-fml} is a Scheme identifier with a name based on the -meta-variables named in the output-language definition. -The \var{extra-rv-fml} is a Scheme identifier. -The \var{input-fml}s named in the fields of a pattern must be unique. -The \var{output-fml}s and \var{extra-rv-fml}s must also be unique, although they -can overlap with the \var{input-fml}s that are shadowed in the body by -the \var{output-fml} or \var{extra-rv-fml} with the same name. - -Only the \var{input-fml}s are visible within the optional \var{guard-clause}. -This is because the \var{guard-clause} is evaluated before the catamorphisms -recur on the fields of a production. -The \var{guard-clause} has the following form: - -{\small -\schemedisplay -(guard \var{guard-expr} ...) -\endschemedisplay -} - -\noindent -where \var{guard-expr} is a Scheme expression. -The \var{guard-clause} has the same semantics as \scheme{and}. - -The \var{body*} and \var{body} are any Scheme expression. -When the output \var{nt-specifier} is not \scheme{*}, -\scheme{quasiquote} is rebound to a macro that interprets \scheme{quasiquote} -expressions as templates for productions in the output nonterminal. -Additionally, \scheme{in-context} is a macro that can be used to rebind -\scheme{quasiquote} to a different nonterminal. -Templates are specified as S-expressions based on the productions specified by -the output language. -In templates, \scheme{unquote} is used to indicate that the expression in the -\scheme{unquote} should be used to fill in the given field of the production. -Within an \scheme{unquote} expression, \scheme{quasiquote} is rebound to the -appropriate nonterminal based on the expected type of the field in the -production. -If the template includes items that are not \scheme{unquote}d where a field -value is expected, the expression found there is automatically quoted. -This allows self-evaluating items such as symbols, booleans, and numbers to be -more easily specified in templates. -A list of items can be specified in a field that expects a list, using an -ellipsis. -%More than one ellipsis can be specified to flatten out a list of lists. - -Although the syntax of a language production is specified as an S-expression, -the record representation used for the language term separates each variable -specified into a separate field. -This means that the template syntax expects a separate value or list of values for -each field in the record. -For instance, in the \scheme{(letrec ([x* e*] ...) body)} production, -a template of the form -\scheme{(letrec (,bindings ...) ,body)} cannot be used -because the nanopass framework will not attempt to break up the -\scheme{bindings} list into its \scheme{x*} and \scheme{e*} component parts. -The template -\scheme{(letrec ([,(map car bindings) ,(map cadr bindings)] ...) ,body)} -accomplishes the same goal, explicitly separating the variables from the expressions. -It is possible that the nanopass framework could be extended to perform the task of -splitting up the \scheme{binding*} list automatically, but it is not done -currently, partially to avoid hiding the cost of deconstructing the -\scheme{binding*} list and constructing the \scheme{x*} and \scheme{e*} lists. - -The \scheme{in-context} expression within the body has the following form: - -{\small -\schemedisplay -(in-context \var{nonterminal-name} \var{body*} ... \var{body}) -\endschemedisplay -} - -The \scheme{in-context} form rebinds the \scheme{quasiquote} to allow -productions from the named nonterminal to be constructed in a context where -they are not otherwise expected. - -\chapter{Working with language forms} - -\section{Constructing language forms outside of a pass} - -In addition to creating language forms using a parser defined with -\scheme{define-parser} or through a pass defined with \scheme{define-pass}, -language forms can also be created using the -\scheme{with-output-language} form. -The \scheme{with-output-language} form binds the \scheme{in-context} -transformer for the language specified and, if a nonterminal is also specified, -binds the \scheme{quasiquote} form. -This allows the same template syntax used in the body of a transformer to be -used outside of the context of a pass. -In a commercial compiler, such as Chez Scheme, it is often convenient to use -functional abstraction to centralize the creation of a language term. - -For instance, in the \scheme{convert-assignments} pass, the -\scheme{with-output-languge} form is wrapped around the \scheme{make-boxes} and -\scheme{build-let} procedures. -This is done so that primitive calls to \scheme{box} along with the \scheme{let} form of the \scheme{L10} language can be constructed with quasiquoted expressions. - -{\small -\schemedisplay -(with-output-language (L10 Expr) - (define make-boxes - (lambda (t*) - (map (lambda (t) `(primcall box ,t)) t*))) - (define build-let - (lambda (x* e* body) - (if (null? x*) - body - `(let ([,x* ,e*] ...) ,body))))) -\endschemedisplay -} - -\noindent -This rebinds both the \scheme{quasiquote} keyword and the \scheme{in-context} keyword. - -The \scheme{with-output-language} form has one of the following forms: - -{\small -\schemedisplay -(with-output-language \var{lang-name} \var{expr*} ... \var{expr}) -(with-output-language (\var{lang-name} \var{nonterminal-name}) \var{expr*} ... \var{expr}) -\endschemedisplay -} - -\noindent -In the first form, the \scheme{in-context} form is bound and can be used to -specify a \var{nonterminal-name}, as described at the end of -Section~\ref{sec:define-pass}. -In the second form, both \scheme{in-context} and \scheme{quasiquote} are bound. -The \scheme{quasiquote} form is bound in the context of the specified -\var{nonterminal-name}, and templates can be defined just as they are on the -right-hand side of a transformer clause. - -The \scheme{with-output-language} form is a splicing form, similar to \scheme{begin} -or \scheme{let-syntax}, allowing multiple definitions or expressions -that are all at the same scoping level as the -\scheme{with-output-language} form to be contained within the form. -This is convenient when writing a set of definitions that all construct some -piece of a language term from the same nonterminal. -This flexibility means that the \scheme{with-output-language} form cannot be -defined as syntactic sugar for the \scheme{define-pass} form. - -\section{Matching language forms outside of a pass} - -In addition to the \scheme{define-pass} form, it is possible to match a -language term using the \scheme{nanopass-case} form. -This can be useful when creating functional abstractions, such as predicates that -ask a question based on matching a language form. -For instance, suppose we write a \scheme{lambda?} predicate for the -\scheme{L8} language as follows: - -{\small -\schemedisplay -(define lambda? - (lambda (e) - (nanopass-case (L8 Expr) e - [(lambda (,x* ...) ,abody) #t] - [else #f]))) -\endschemedisplay -} - -\noindent -The \scheme{nanopass-case} form has the following syntax: - -{\small -\schemedisplay -(nanopass-case (\var{lang-name} \var{nonterminal-name}) \var{expr} - \var{matching-clause} ...) -\endschemedisplay -} - -\noindent -where \var{matching-clause} has one of the following forms: - -{\small -\schemedisplay -[\var{pattern} \var{guard-clause} \var{expr*} ... \var{expr}] -[\var{pattern} \var{expr*} ... \var{expr}] -[else \var{expr*} ... \var{expr}] -\endschemedisplay -} - -\noindent -where the \var{pattern} and \var{guard-clause} forms have the same syntax as in -the \var{transformer-body} of a pass. - -Similar to \scheme{with-output-language}, \scheme{nanopass-case} provides a -more succinct syntax for matching a language form than does the general -\scheme{define-pass} form. -Unlike the \scheme{with-output-language} form, however, the -\scheme{nanopass-case} form can be implemented in terms of the -\scheme{define-pass} form. -For example, the \scheme{lambda?} predicate also could have been written as: - -{\small -\schemedisplay -(define-pass lambda? : (L8 Expr) (e) -> * (bool) - (Expr : Expr (e) -> * (bool) - [(lambda (,x* ...) ,abody) #t] - [else #f]) - (Expr e)) -\endschemedisplay -} - -\noindent -This is, in fact, how the \scheme{nanopass-case} macro is implemented. - -\chapter{Working with languages} - -\section{Displaying languages} - -The \scheme{language->s-expression} form can be used to print the full definition of a language by supplying it the language -name to be printed. -This can be helpful when working with extended languages, such as in the case of -\scheme{L1}: - -{\small -\schemedisplay -(language->s-expression L1) -\endschemedisplay -} - -\noindent -which returns: - -{\small -\schemedisplay -(define-language L1 - (entry Expr) - (terminals - (void+primitive (pr)) - (symbol (x)) - (constant (c)) - (datum (d))) - (Expr (e body) - pr - x - c - (quote d) - (if e0 e1 e2) - (or e* ...) - (and e* ...) - (not e) - (begin e* ... e) - (lambda (x* ...) body* ... body) - (let ([x* e*] ...) body* ... body) - (letrec ([x* e*] ...) body* ... body) - (set! x e) - (e e* ...))) -\endschemedisplay -} - -\section{Differencing languages} - -The extension form can also be derived between any two languages by using the -\scheme{diff-languages} form. -For instance, we can get the differences between the \scheme{Lsrc} and -\scheme{L1} language (giving us back the extension) with: - -{\small -\schemedisplay -(diff-languages Lsrc L1) -\endschemedisplay -} - -\noindent -which returns: - -{\small -\schemedisplay -(define-language L1 - (extends Lsrc) - (entry Expr) - (terminals - (- (primitive (pr))) - (+ (void+primitive (pr)))) - (Expr (e body) - (- (if e0 e1)))) -\endschemedisplay -} - -\section{Viewing the expansion of passes and transformers} - -The \scheme{define-pass} form autogenerates both transformers and clauses -within transformers. -In simple passes, these are generally straightforward to reason about, but in -more complex passes, particularly those that make use of different arguments -for different transformers or include extra return values, it can become more -difficult to determine what code will be generated. -In particular, the experience of developing a full commercial compiler has -shown that the \scheme{define-pass} form can autogenerate transformers that -shadow those defined by the compiler writer. -To help the compiler writer determine what code is being generated, -there is a variation of the \scheme{define-pass} form, called -\scheme{echo-define-pass}, that will echo the expansion of \scheme{define-pass}. - -For instance, we can echo the \scheme{remove-one-armed-if} pass to get the -following: - -{\small -\schemedisplay -(echo-define-pass remove-one-armed-if : Lsrc (e) -> L1 () - (Expr : Expr (e) -> Expr () - [(if ,[e0] ,[e1]) `(if ,e0 ,e1 (void))])) - -;=> - -pass remove-one-armed-if expanded into: -(define remove-one-armed-if - (lambda (e) - (define who 'remove-one-armed-if) - (define-nanopass-record) - (define Expr - (lambda (e) - (let ([g221.159 e]) - (let-syntax ([quasiquote '#] - [in-context '#]) - (begin - (let ([rhs.160 (lambda (e0 e1) `(if ,e0 ,e1 (void)))]) - (cond - [(primitive? g221.159) g221.159] - [(symbol? g221.159) g221.159] - [(constant? g221.159) g221.159] - [else - (let ([tag (nanopass-record-tag g221.159)]) - (cond - [(eqv? tag 4) - (let* ([g222.161 (Lsrc:if:Expr.387-e0 g221.159)] - [g223.162 (Lsrc:if:Expr.387-e1 g221.159)]) - (let-values ([(e0) (Expr g222.161)] - [(e1) (Expr g223.162)]) - (rhs.160 e0 e1)))] - [(eqv? tag 2) - (make-L1:quote:Expr.400 - 'remove-one-armed-if - (Lsrc:quote:Expr.386-d g221.159) - "d")] - [(eqv? tag 6) - (make-L1:if:Expr.401 'remove-one-armed-if - (Expr (Lsrc:if:Expr.388-e0 g221.159)) - (Expr (Lsrc:if:Expr.388-e1 g221.159)) - (Expr (Lsrc:if:Expr.388-e2 g221.159)) "e0" "e1" - "e2")] - [(eqv? tag 8) - (make-L1:or:Expr.402 - 'remove-one-armed-if - (map (lambda (m) (Expr m)) - (Lsrc:or:Expr.389-e* g221.159)) - "e*")] - [(eqv? tag 10) - (make-L1:and:Expr.403 - 'remove-one-armed-if - (map (lambda (m) (Expr m)) - (Lsrc:and:Expr.390-e* g221.159)) - "e*")] - [(eqv? tag 12) - (make-L1:not:Expr.404 - 'remove-one-armed-if - (Expr (Lsrc:not:Expr.391-e g221.159)) - "e")] - [(eqv? tag 14) - (make-L1:begin:Expr.405 'remove-one-armed-if - (map (lambda (m) (Expr m)) - (Lsrc:begin:Expr.392-e* g221.159)) - (Expr (Lsrc:begin:Expr.392-e g221.159)) "e*" - "e")] - [(eqv? tag 16) - (make-L1:lambda:Expr.406 'remove-one-armed-if - (Lsrc:lambda:Expr.393-x* g221.159) - (map (lambda (m) (Expr m)) - (Lsrc:lambda:Expr.393-body* g221.159)) - (Expr (Lsrc:lambda:Expr.393-body g221.159)) "x*" - "body*" "body")] - [(eqv? tag 18) - (make-L1:let:Expr.407 'remove-one-armed-if - (Lsrc:let:Expr.394-x* g221.159) - (map (lambda (m) (Expr m)) - (Lsrc:let:Expr.394-e* g221.159)) - (map (lambda (m) (Expr m)) - (Lsrc:let:Expr.394-body* g221.159)) - (Expr (Lsrc:let:Expr.394-body g221.159)) "x*" - "e*" "body*" "body")] - [(eqv? tag 20) - (make-L1:letrec:Expr.408 'remove-one-armed-if - (Lsrc:letrec:Expr.395-x* g221.159) - (map (lambda (m) (Expr m)) - (Lsrc:letrec:Expr.395-e* g221.159)) - (map (lambda (m) (Expr m)) - (Lsrc:letrec:Expr.395-body* g221.159)) - (Expr (Lsrc:letrec:Expr.395-body g221.159)) "x*" - "e*" "body*" "body")] - [(eqv? tag 22) - (make-L1:set!:Expr.409 'remove-one-armed-if - (Lsrc:set!:Expr.396-x g221.159) - (Expr (Lsrc:set!:Expr.396-e g221.159)) "x" "e")] - [(eqv? tag 24) - (make-L1:e:Expr.410 'remove-one-armed-if - (Expr (Lsrc:e:Expr.397-e g221.159)) - (map (lambda (m) (Expr m)) - (Lsrc:e:Expr.397-e* g221.159)) - "e" "e*")] - [else - (error 'remove-one-armed-if - "unexpected Expr" - g221.159)]))]))))))) - (let ([x (Expr e)]) - (unless ((lambda (x) - (or (L1:Expr.399? x) - (constant? x) - (symbol? x) - (void+primitive? x))) - x) - (error 'remove-one-armed-if - (format "expected ~s but got ~s" 'Expr x))) - x))) -\endschemedisplay -} - -\noindent -This exposes the code generated by \scheme{define-pass} but does not expand -the language form construction templates. -The autogenerated clauses, such as the one that handles \scheme{set!}, have a form like the following: - -{\small -\schemedisplay -[(eqv? tag 7) - (make-L1:set!:Expr.18 - (Lsrc:set!:Expr.8-x g0.14) - (Expr (Lsrc:set!:Expr.8-e g0.14)))] -\endschemedisplay -} - -\noindent -Here, the tag of the record is checked and a new output-language record constructed, -after recurring to the \scheme{Expr} transformer on the \scheme{e} field. - -The body code also changes slightly, so that the output of the pass can be -checked to make sure that it is a valid \scheme{L1} \scheme{Expr}. - -In addition to echoing the output of the entire pass, it is also possible to -echo just the expansion of a single transformer by prefixing the transformer -with the \scheme{echo} keyword. - -{\small -\schemedisplay -(define-pass remove-one-armed-if : Lsrc (e) -> L1 () - (echo Expr : Expr (e) -> Expr () - [(if ,[e0] ,[e1]) `(if ,e0 ,e1 (void))])) - -;=> - -Expr in pass remove-one-armed-if expanded into: -(define Expr - (lambda (e) - (let ([g442.303 e]) - (let-syntax ([quasiquote '#] - [in-context '#]) - (begin - (let ([rhs.304 (lambda (e0 e1) `(if ,e0 ,e1 (void)))]) - (cond - [(primitive? g442.303) g442.303] - [(symbol? g442.303) g442.303] - [(constant? g442.303) g442.303] - [else - (let ([tag (nanopass-record-tag g442.303)]) - (cond - [(eqv? tag 4) - (let* ([g443.305 (Lsrc:if:Expr.770-e0 g442.303)] - [g444.306 (Lsrc:if:Expr.770-e1 g442.303)]) - (let-values ([(e0) (Expr g443.305)] - [(e1) (Expr g444.306)]) - (rhs.304 e0 e1)))] - [(eqv? tag 2) - (make-L1:quote:Expr.783 - 'remove-one-armed-if - (Lsrc:quote:Expr.769-d g442.303) - "d")] - [(eqv? tag 6) - (make-L1:if:Expr.784 'remove-one-armed-if - (Expr (Lsrc:if:Expr.771-e0 g442.303)) - (Expr (Lsrc:if:Expr.771-e1 g442.303)) - (Expr (Lsrc:if:Expr.771-e2 g442.303)) "e0" "e1" - "e2")] - [(eqv? tag 8) - (make-L1:or:Expr.785 - 'remove-one-armed-if - (map (lambda (m) (Expr m)) - (Lsrc:or:Expr.772-e* g442.303)) - "e*")] - [(eqv? tag 10) - (make-L1:and:Expr.786 - 'remove-one-armed-if - (map (lambda (m) (Expr m)) - (Lsrc:and:Expr.773-e* g442.303)) - "e*")] - [(eqv? tag 12) - (make-L1:not:Expr.787 - 'remove-one-armed-if - (Expr (Lsrc:not:Expr.774-e g442.303)) - "e")] - [(eqv? tag 14) - (make-L1:begin:Expr.788 'remove-one-armed-if - (map (lambda (m) (Expr m)) - (Lsrc:begin:Expr.775-e* g442.303)) - (Expr (Lsrc:begin:Expr.775-e g442.303)) "e*" "e")] - [(eqv? tag 16) - (make-L1:lambda:Expr.789 'remove-one-armed-if - (Lsrc:lambda:Expr.776-x* g442.303) - (map (lambda (m) (Expr m)) - (Lsrc:lambda:Expr.776-body* g442.303)) - (Expr (Lsrc:lambda:Expr.776-body g442.303)) "x*" - "body*" "body")] - [(eqv? tag 18) - (make-L1:let:Expr.790 'remove-one-armed-if (Lsrc:let:Expr.777-x* g442.303) - (map (lambda (m) (Expr m)) - (Lsrc:let:Expr.777-e* g442.303)) - (map (lambda (m) (Expr m)) - (Lsrc:let:Expr.777-body* g442.303)) - (Expr (Lsrc:let:Expr.777-body g442.303)) "x*" "e*" - "body*" "body")] - [(eqv? tag 20) - (make-L1:letrec:Expr.791 'remove-one-armed-if - (Lsrc:letrec:Expr.778-x* g442.303) - (map (lambda (m) (Expr m)) - (Lsrc:letrec:Expr.778-e* g442.303)) - (map (lambda (m) (Expr m)) - (Lsrc:letrec:Expr.778-body* g442.303)) - (Expr (Lsrc:letrec:Expr.778-body g442.303)) "x*" "e*" - "body*" "body")] - [(eqv? tag 22) - (make-L1:set!:Expr.792 'remove-one-armed-if (Lsrc:set!:Expr.779-x g442.303) - (Expr (Lsrc:set!:Expr.779-e g442.303)) "x" "e")] - [(eqv? tag 24) - (make-L1:e:Expr.793 'remove-one-armed-if - (Expr (Lsrc:e:Expr.780-e g442.303)) - (map (lambda (m) (Expr m)) - (Lsrc:e:Expr.780-e* g442.303)) - "e" "e*")] - [else - (error 'remove-one-armed-if - "unexpected Expr" - g442.303)]))]))))))) -\endschemedisplay -} - -\section{Tracing passes and transformers} - -Echoing the code generated by \scheme{define-pass} can help compiler writers -to understand what is happening at expansion time, but it does not help in determining -what is happening at run time. -To facilitate this type of debugging, passes and transformers can be -traced at run time. -The tracing system, similar to Chez Scheme's \scheme{trace-define-syntax}, -unparses the input-language term and output-language term of the pass using the language unparsers to -provide the S-expression representation of the language term that is being transformed. - -The \scheme{trace-define-pass} form works just like the \scheme{define-pass} -form but adds tracing for the input-language term and output-language term of the pass. -For instance, if we want to trace the processing of the input: - -{\small -\schemedisplay -(let ([x 10]) - (if (= (* (/ x 2) 2) x) (set! x (/ x 2))) - (* x 3)) -\endschemedisplay -} - -\noindent -the pass can be defined as a tracing pass, as follows: - -{\small -\schemedisplay -(trace-define-pass remove-one-armed-if : Lsrc (e) -> L1 () - (Expr : Expr (e) -> Expr () - [(if ,[e0] ,[e1]) `(if ,e0 ,e1 (void))])) -\endschemedisplay -} - -\noindent -Running the class compiler with \scheme{remove-one-armed-if} traced produces the following: - -{\small -\schemedisplay -> (my-tiny-compile - '(let ([x 10]) - (if (= (* (/ x 2) 2) x) (set! x (/ x 2))) - (* x 3))) -|(remove-one-armed-if - (let ([x.12 10]) - (if (= (* (/ x.12 2) 2) x.12) (set! x.12 (/ x.12 2))) - (* x.12 3))) -|(let ([x.12 10]) - (if (= (* (/ x.12 2) 2) x.12) (set! x.12 (/ x.12 2)) (void)) - (* x.12 3)) -15 -\endschemedisplay -} - -\noindent -The tracer prints the \emph{pretty} (i.e., S-expression) form of the language, -rather than the record representation, to allow the compiler writer to read the -terms more easily. -This does not trace the internal transformations that happen within the -transformers of the pass. -Transformers can be traced by adding the \scheme{trace} keyword in front of the -transformer definition. -We can run the same test with a \scheme{remove-one-armed-if} that traces the -\scheme{Expr} transformer, as follows: - -{\small -\schemedisplay -> (my-tiny-compile - '(let ([x 10]) - (if (= (* (/ x 2) 2) x) (set! x (/ x 2))) - (* x 3))) -|(Expr - (let ([x.0 10]) (if (= (* (/ x.0 2) 2) x.0) (set! x.0 (/ x.0 2))) (* x.0 3))) -| (Expr (* x.0 3)) -| |(Expr x.0) -| |x.0 -| |(Expr 3) -| |3 -| |(Expr *) -| |* -| (* x.0 3) -| (Expr (if (= (* (/ x.0 2) 2) x.0) (set! x.0 (/ x.0 2)))) -| |(Expr (= (* (/ x.0 2) 2) x.0)) -| | (Expr (* (/ x.0 2) 2)) -| | |(Expr (/ x.0 2)) -| | | (Expr x.0) -| | | x.0 -| | | (Expr 2) -| | | 2 -| | | (Expr /) -| | | / -| | |(/ x.0 2) -| | |(Expr 2) -| | |2 -| | |(Expr *) -| | |* -| | (* (/ x.0 2) 2) -| | (Expr x.0) -| | x.0 -| | (Expr =) -| | = -| |(= (* (/ x.0 2) 2) x.0) -| |(Expr (set! x.0 (/ x.0 2))) -| | (Expr (/ x.0 2)) -| | |(Expr x.0) -| | |x.0 -| | |(Expr 2) -| | |2 -| | |(Expr /) -| | |/ -| | (/ x.0 2) -| |(set! x.0 (/ x.0 2)) -| (if (= (* (/ x.0 2) 2) x.0) (set! x.0 (/ x.0 2)) (void)) -| (Expr 10) -| 10 -|(let ([x.0 10]) - (if (= (* (/ x.0 2) 2) x.0) (set! x.0 (/ x.0 2)) (void)) - (* x.0 3)) -15 -\endschemedisplay -} - -\noindent -Here, too, the traced forms are the pretty representation and not -the record representation. - -\bibliographystyle{abbrv} -\bibliography{user-guide} - -\end{document} diff --git a/ta6ob/nanopass/nanopass.ss b/ta6ob/nanopass/nanopass.ss deleted file mode 100644 index 547c0a7..0000000 --- a/ta6ob/nanopass/nanopass.ss +++ /dev/null @@ -1,20 +0,0 @@ -;;; Copyright (c) 2000-2018 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (nanopass) - (export define-language define-parser define-unparser trace-define-parser - trace-define-pass echo-define-pass define-pass with-output-language - nanopass-case language->s-expression extends entry terminals - nongenerative-id maybe #;define-nanopass-record-types diff-languages - define-language-node-counter prune-language define-pruned-language - with-extended-quasiquote with-r6rs-quasiquote pass-input-parser - pass-output-unparser pass-identifier? pass-input-language - pass-output-language) - (import - (nanopass language) - (nanopass parser) - (nanopass unparser) - (nanopass language-node-counter) - (nanopass pass) - (nanopass helpers) - (nanopass records))) diff --git a/ta6ob/nanopass/nanopass/exp-syntax.sls b/ta6ob/nanopass/nanopass/exp-syntax.sls deleted file mode 100644 index f81603e..0000000 --- a/ta6ob/nanopass/nanopass/exp-syntax.sls +++ /dev/null @@ -1,297 +0,0 @@ -(library (nanopass exp-syntax) - (export - define-language-exp - inspect-language lookup-language - Llanguage unparse-Llanguage - Lannotated unparse-Lannotated - language->s-expression-exp - prune-language-exp - define-pruned-language-exp - diff-languages-exp - define-language-node-counter-exp - define-unparser-exp - define-parser-exp - ) - (import (rnrs) (nanopass) (nanopass experimental) (nanopass helpers) - (only (chezscheme) make-compile-time-value trace-define-syntax unbox - optimize-level enumerate with-output-to-string errorf)) - - - (define-syntax define-language-exp - (lambda (x) - (lambda (rho) - (syntax-case x () - [(_ . rest) - (let* ([lang (parse-np-source x 'define-language-exp)] - [lang (handle-language-extension lang 'define-language-exp rho)] - [lang (check-and-finish-language lang)] - [lang-annotated (annotate-language lang)]) - (nanopass-case (Llanguage Defn) lang - [(define-language ,id ,cl* ...) - #`(begin - (define-language . rest) - (define-property #,id experimental-language - (make-language-information '#,lang '#,lang-annotated)) - (define-language-records #,id) - #;(define-language-predicates #,id))]))])))) - - (define-syntax inspect-language - (lambda (x) - (lambda (rho) - (syntax-case x () - [(_ name) - (let ([lang (rho #'name)]) - (if lang - (let ([l (language-information-language lang)] - [a (language-information-annotated-language lang)]) - #`(list - '#,l - '#,(datum->syntax #'* (unparse-Llanguage l)) - '#,a - '#,(datum->syntax #'* (unparse-Lannotated a)))) - (syntax-violation 'inspect-language "no language found" #'name)))])))) - - (define (build-list-of-string level name) - (with-output-to-string - (lambda () - (let loop! ([level level]) - (if (fx=? level 0) - (write name) - (begin (display "list of ") (loop! (fx- level 1)))))))) - - (define-syntax define-language-records - (lambda (x) - (define-pass construct-records : Lannotated (ir) -> * (stx) - (definitions - (define (build-field-check name mv level pred) - #`(lambda (x msg) - (define (squawk level x) - (if msg - (errorf who "expected ~a but received ~s in field ~s from ~a" - (build-list-of-string level '#,name) x '#,mv msg) - (errorf who "expected ~a but received ~s in field ~s" - (build-list-of-string level '#,name) x '#,mv))) - #,(let f ([level level]) - (if (fx=? level 0) - #`(lambda (x) (unless (#,pred x) (squawk #,level x))) - #`(lambda (x) - (let loop ([x x]) - (cond - [(pair? x) (#,(f (fx- level 1)) (car x))] - [(null? x)] - [else (squawk #,level x)])))))))) - (Defn : Defn (ir) -> * (stx) - [(define-language ,id ,ref ,id0? ,rtd ,rcd ,tag-mask (,term* ...) ,[nt*] ...) - #`(begin #,@nt*)]) - (Nonterminal : Nonterminal (ir) -> * (stx) - [(,id (,id* ...) ,b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,prod* ...) - (let ([stx* (map (lambda (prod) (Production prod rcd)) prod*)]) - #`(begin (define #,pred (record-predicate '#,rtd)) #,@stx*))]) - (Production : Production (ir nt-rcd) -> * (stx) - [(production ,pattern ,pretty-prod? ,rtd ,tag ,pred ,maker ,[mv* acc* check*] ...) - (with-syntax ([(mv* ...) mv*] - [(msg* ...) (generate-temporaries mv*)] - [(check* ...) check*] - [(acc* ...) acc*] - [(idx ...) (enumerate acc*)]) - #`(begin - (define #,maker - (let () - (define maker - (record-constructor - (make-record-constructor-descriptor '#,rtd '#,nt-rcd - (lambda (pargs->new) - (lambda (mv* ...) - ((pargs->new #,tag) mv* ...)))))) - (lambda (who mv* ... msg* ...) - #,@(if (fx=? (optimize-level) 3) - '() - #`((check* mv* msg*) ...)) - (maker mv* ...)))) - (define #,pred (record-predicate '#,rtd)) - (define acc* (record-accessor '#,rtd idx)) ...))] - [else #'(begin)]) - (Field : Field (ir) -> * (mv check acc) - [(,[mv name pred] ,level ,accessor) - (values mv accessor (build-field-check name mv level pred))] - [(optional ,[mv name pred] ,level ,accessor) - (values mv accessor - (build-field-check name mv level - #`(lambda (x) (or (eq? x #f) (#,pred x)))))]) - (Reference : Reference (ir) -> * (mv name pred) - [(term-ref ,id0 ,id1 ,b) - (values id0 id1 (TerminalPred (unbox b)))] - [(nt-ref ,id0 ,id1 ,b) - (values id0 id1 (NonterminalPred (unbox b)))]) - (TerminalPred : Terminal (ir) -> * (name pred) - [(,id (,id* ...) ,b ,handler? ,pred) pred]) - (NonterminalPred : Nonterminal (ir) -> * (name pred) - [(,id (,id* ...) ,b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,prod* ...) - all-pred]) - (Defn ir)) - (syntax-case x () - [(_ name) - (lambda (rho) - (let ([lang (lookup-language rho #'name)]) - (construct-records (language-information-annotated-language lang))))]))) - - (define-syntax define-language-predicates - (lambda (x) - (define-pass language-predicates : Lannotated (ir) -> * (stx) - (definitions - (define (set-cons x ls) - (if (memq x ls) - ls - (cons x ls)))) - (Defn : Defn (ir) -> * (stx) - [(define-language ,id ,ref ,id0? ,rtd ,rcd ,tag-mask (,term* ...) ,nt* ...) - (let loop ([nt* nt*] [ntpreddef* '()] [tpred* '()]) - (if (null? nt*) - (with-syntax ([pred (construct-id id id "?")] - [(tpred* ...) tpred*]) - #`(begin - (define pred - (lambda (x) - (or ((record-predicate '#,rtd) x) (tpred* x) ...))) - #,@ntpreddef*)) - (let-values ([(ntpreddef* tpred*) (Nonterminal (car nt*) ntpreddef* tpred*)]) - (loop (cdr nt*) ntpreddef* tpred*))))]) - (Nonterminal : Nonterminal (nt ntpreddef* lang-tpred*) -> * (ntpreddef* lang-tpred*) - [(,id (,id* ...) ,b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,prod* ...) - (let loop ([prod* prod*] [pred* '()] [lang-tpred* lang-tpred*]) - (if (null? prod*) - (values - (cons - (with-syntax ([(pred* ...) pred*]) - #`(define #,all-pred - (lambda (x) - (or ((record-predicate '#,rtd) x) (pred* x) ...)))) - ntpreddef*) - lang-tpred*) - (let-values ([(tpred* lang-tpred*) (Production (car prod*) pred* lang-tpred*)]) - (loop (cdr prod*) tpred* lang-tpred*))))]) - (Production : Production (ir pred* lang-tpred*) -> * (pred* lang-tpred*) - [(terminal (term-ref ,id0 ,id1 ,b) ,pretty-prod?) - (let ([pred (TerminalPred (unbox b))]) - (values (cons pred pred*) (set-cons pred lang-tpred*)))] - [(nonterminal (nt-ref ,id0 ,id1 ,b) ,pretty-prod?) - (values (cons (NonterminalPred (unbox b)) pred*) lang-tpred*)] - [else (values pred* lang-tpred*)]) - (TerminalPred : Terminal (ir) -> * (pred) - [(,id (,id* ...) ,b ,handler? ,pred) pred]) - (NonterminalPred : Nonterminal (ir) -> * (pred) - [(,id (,id* ...) ,b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,prod* ...) all-pred]) - (Defn ir)) - (syntax-case x () - [(_ name) - (lambda (rho) - (let ([lang (lookup-language rho #'name)]) - (language-predicates (language-information-annotated-language lang))))]))) - - (define-syntax language->s-expression-exp - (lambda (x) - (define-pass lang->sexp : Llanguage (ir) -> * (sexp) - (Defn : Defn (ir) -> * (sexp) - [(define-language ,id ,[cl*] ...) - `(define-language ,(syntax->datum id) . ,cl*)]) - (Clause : Clause (ir) -> * (sexp) - [(entry ,[sym]) `(entry ,sym)] - [(nongenerative-id ,id) - `(nongenerative-id ,(syntax->datum id))] - [(terminals ,[term*] ...) - `(terminals . ,term*)] - [(,id (,id* ...) ,b ,[prod*] ...) - `(,(syntax->datum id) ,(map syntax->datum id*) . ,prod*)]) - (Terminal : Terminal (ir) -> * (sexp) - [,simple-term (SimpleTerminal simple-term)] - [(=> ,[simple-term] ,handler) - `(=> ,simple-term ,(syntax->datum handler))]) - (SimpleTerminal : SimpleTerminal (ir) -> * (sexp) - [(,id (,id* ...) ,b) - `(,(syntax->datum id) ,(map syntax->datum id*))]) - (Production : Production (ir) -> * (sexp) - [,pattern (Pattern pattern)] - [(=> ,[pattern0] ,[pattern1]) - `(=> ,pattern0 ,pattern1)] - [(-> ,[pattern] ,handler) - `(-> ,pattern ,(syntax->datum handler))]) - (Pattern : Pattern (ir) -> * (sexp) - [(maybe ,[sym]) `(maybe ,sym)] - [,ref (Reference ref)] - [,id (syntax->datum id)] - [(,[pattern0] ,dots . ,[pattern1]) - `(,pattern0 ... . ,pattern1)] - [(,[pattern0] . ,[pattern1]) - `(,pattern0 . ,pattern1)] - [,null '()]) - (Reference : Reference (ir) -> * (sym) - [(term-ref ,id0 ,id1 ,b) (syntax->datum id0)] - [(nt-ref ,id0 ,id1 ,b) (syntax->datum id0)]) - (Defn ir)) - (syntax-case x () - [(_ name) - (lambda (rho) - (let ([lang (lookup-language rho #'name)]) - #`'#,(datum->syntax #'* - (lang->sexp - (language-information-language lang)))))]))) - - (define-syntax prune-language-exp - (lambda (x) - (syntax-case x () - [(_ name) - (lambda (rho) - (let ([lang (lookup-language rho #'name)]) - (with-syntax ([pl (prune-lang - (language-information-annotated-language lang) - 'prune-language-exp - #f)]) - #'(quote pl))))]))) - - (define-syntax define-pruned-language-exp - (lambda (x) - (syntax-case x () - [(_ name new-name) - (lambda (rho) - (let ([lang (lookup-language rho #'name)]) - (prune-lang - (language-information-annotated-language lang) - 'define-pruned-language-exp - #'new-name)))]))) - - (define-syntax diff-languages-exp - (lambda (x) - (syntax-case x () - [(_ name0 name1) - (lambda (rho) - (let ([lang0 (lookup-language rho #'name0)] - [lang1 (lookup-language rho #'name1)]) - (with-syntax ([diff (diff-langs - (language-information-language lang0) - (language-information-language lang1))]) - #'(quote diff))))]))) - - (define-syntax define-language-node-counter-exp - (lambda (x) - (syntax-case x () - [(_ name lang) - (lambda (rho) - (let ([l (lookup-language rho #'lang)]) - (build-lang-node-counter (language-information-annotated-language l) #'name)))]))) - - (define-syntax define-unparser-exp - (lambda (x) - (syntax-case x () - [(_ name lang) - (lambda (rho) - (let ([l (lookup-language rho #'lang)]) - (build-unparser (language-information-annotated-language l) #'name)))]))) - - (define-syntax define-parser-exp - (lambda (x) - (syntax-case x () - [(_ name lang) - (lambda (rho) - (let ([l (lookup-language rho #'lang)]) - (build-parser (language-information-annotated-language l) #'name)))]))) - ) diff --git a/ta6ob/nanopass/nanopass/experimental.sls b/ta6ob/nanopass/nanopass/experimental.sls deleted file mode 100644 index 6a41b5d..0000000 --- a/ta6ob/nanopass/nanopass/experimental.sls +++ /dev/null @@ -1,1636 +0,0 @@ -(library (nanopass experimental) - (export - experimental-language - datum? dots? maybe? syntax? exact-integer? - Lnp-source unparse-Lnp-source - parse-np-source - Lcomplete unparse-Lcomplete - language-information make-language-information - language-information-language language-information-annotated-language - handle-language-extension - Llanguage unparse-Llanguage - meta-variable-suffix-checker - check-and-finish-language - Lannotated unparse-Lannotated Lannotated? Lannotated-Defn? Lannotated-Terminal? Lannotated-Nonterminal? - annotate-language - star? modifier? - Lpass-src unparse-Lpass-src - lookup-language - prune-lang - diff-langs - build-lang-node-counter - build-unparser - build-parser - parse-pass - Lpass unparse-Lpass) - (import (rnrs) (nanopass) (nanopass helpers) (nanopass prefix-matcher) - (only (chezscheme) box box? set-box! unbox make-parameter - record-constructor-descriptor? eq-hashtable-update!)) - - (define-syntax experimental-language - (lambda (x) (syntax-violation 'experimental-language "misplaced aux keyword" x))) - - (define-nanopass-record) - - (define (datum? x) #t) - (define (dots? x) (eq? (syntax->datum x) '...)) - (define (maybe? x) (eq? (syntax->datum x) 'maybe)) - (define (syntax? x) #t) ;; could be slightly more perscriptive, and check for raw symbols - (define (exact-integer? x) (and (integer? x) (exact? x))) - - (define-language Lnp-source - (terminals - (syntax (stx)) => syntax->datum - (identifier (id)) => syntax->datum - (datum (handler)) - (dots (dots)) - (null (null))) - (Defn (def) - (define-language id cl* ...)) - (Clause (cl) - (extends id) - (entry id) - (nongenerative-id id) - (terminals term* ...) - (id (id* ...) prod prod* ...)) - (Terminal (term) - base-term - (+ base-term* ...) - (- base-term* ...)) - (BaseTerminal (base-term) - simple-term - (=> (=> simple-term handler) - (=> simple-term handler))) - (SimpleTerminal (simple-term) - (id (id* ...))) - (Production (prod) - stx)) - - (define-pass parse-np-source : * (stx who) -> Lnp-source () - (definitions - (define (parse-terminals stx) - (let f ([stx stx]) - (syntax-case stx () - [() '()] - [_ (let-values ([(t stx) (Terminal stx #t)]) - (cons t (f stx)))]))) - (define (parse-base-terminals stx) - (let f ([stx stx]) - (syntax-case stx () - [() '()] - [_ (let-values ([(t stx) (Terminal stx #f)]) - (cons t (f stx)))])))) - (Defn : * (stx) -> Defn () - (syntax-case stx () - [(_ ?id ?cl ...) - (identifier? #'?id) - `(define-language ,#'?id ,(map Clause #'(?cl ...)) ...)] - [_ (syntax-violation who "invalid syntax" stx)])) - (Clause : * (stx) -> Clause () - (syntax-case stx (extends entry terminals nongenerative-id) - [(extends ?id) (identifier? #'?id) `(extends ,#'?id)] - [(entry ?id) (identifier? #'?id) `(entry ,#'?id)] - [(nongenerative-id ?id) (identifier? #'?id) `(nongenerative-id ,#'?id)] - [(terminals ?term* ...) `(terminals ,(parse-terminals #'(?term* ...)) ...)] - [(?id (?id* ...) ?prod ?prod* ...) - (and (identifier? #'?id) (for-all identifier? #'(?id* ...))) - `(,#'?id (,#'(?id* ...) ...) ,#'?prod ,#'(?prod* ...) ...)] - [x (syntax-violation who "unrecognized language clause" stx #'x)])) - (Terminal : * (stx ext-okay?) -> Terminal (stx) - (syntax-case stx () - [((=> (?id (?id* ...)) ?handler) . ?rest) - (and (double-arrow? #'=>) (identifier? #'?id) (for-all identifier? #'(?id* ...))) - (values `(=> (,#'?id (,#'(?id* ...) ...)) ,#'?handler) #'?rest)] - [((?id (?id* ...)) => ?handler . ?rest) - (and (double-arrow? #'=>) (identifier? #'?id) (for-all identifier? #'(?id* ...))) - (values `(=> (,#'?id (,#'(?id* ...) ...)) ,#'?handler) #'?rest)] - [((?id (?id* ...)) . ?rest) - (and (identifier? #'?id) (for-all identifier? #'(?id* ...))) - (values `(,#'?id (,#'(?id* ...) ...)) #'?rest)] - [((+ ?term* ...) . ?rest) - (and ext-okay? (plus? #'+)) - (values `(+ ,(parse-base-terminals #'(?term* ...)) ...) #'?rest)] - [((- ?term* ...) . ?rest) - (and ext-okay? (minus? #'-)) - (values `(- ,(parse-base-terminals #'(?term* ...)) ...) #'?rest)] - [x (syntax-violation who "unrecognized terminal clause" stx #'x)])) - (Defn stx)) - - (define-language Lcomplete - (extends Lnp-source) - (Clause (cl) - (- (extends id) - (id (id* ...) prod prod* ...)) - (+ (id (id* ...) prod* ...))) ;; really the requirement remains, but is enforced in pass - (Terminal (term) - (- base-term - (+ base-term* ...) - (- base-term* ...)) - (+ simple-term - (=> (=> simple-term handler) - (=> simple-term handler)))) - (BaseTerminal (base-term) - (- simple-term - (=> (=> simple-term handler) - (=> simple-term handler)))) - (Production (prod) - (- stx) - (+ pattern - (=> (=> pattern0 pattern1) - (=> pattern0 pattern1)) - (=> (-> pattern handler) - (-> pattern handler)))) - (Pattern (pattern) - (+ id - (maybe id) - (pattern0 dots . pattern1) - (pattern0 . pattern1) - null))) - - (define-record-type language-information - (nongenerative) - (fields language annotated-language)) - - (define-pass handle-language-extension : Lnp-source (lang who rho) -> Lcomplete () - (definitions - (define (language-extension? cl*) - (fold-left (lambda (ext? cl) - (nanopass-case (Lnp-source Clause) cl - [(extends ,id) id] - [else ext?])) - #f cl*)) - (define parse-productions - (case-lambda - [(stx) (parse-productions stx '())] - [(stx prod*) - (let f ([stx stx]) - (syntax-case stx () - [() prod*] - [_ (let-values ([(prod stx) (FinishProd stx)]) - (cons prod (f stx)))]))])) - (define (extend-clauses cl* base-lang) - (nanopass-case (Lannotated Defn) base-lang - [(define-language ,id ,ref ,id? ,rtd ,rcd ,tag-mask (,term* ...) ,nt* ...) - (let loop ([cl* cl*] [term* term*] [nt* nt*] [new-term* '()] [new-cl* '()]) - (if (null? cl*) - (cons - (with-output-language (Lcomplete Clause) - `(terminals - ,(fold-left - (lambda (new-term* term) - (cons (rewrite-annotated-term term) new-term*)) - new-term* term*) - ...)) - (fold-left (lambda (new-cl* nt) (cons (rewrite-annotated-nt nt) new-cl*)) new-cl* nt*)) - (let-values ([(term* nt* new-cl* new-term*) - (ExtendClause (car cl*) term* nt* new-cl* new-term*)]) - (loop (cdr cl*) term* nt* new-term* new-cl*))))])) - (define-pass rewrite-annotated-term : (Lannotated Terminal) (ir) -> (Lcomplete Terminal) () - (Terminal : Terminal (ir) -> Terminal () - [(,id (,id* ...) ,b ,handler? ,pred) - (if handler? - `(=> (,id (,id* ...)) ,handler?) - `(,id (,id* ...)))])) - (define-pass rewrite-production : (Lannotated Production) (ir) -> (Lcomplete Production) () - (Production : Production (ir) -> Production () - (definitions - (define (finish-prod pattern pretty-prod?) - (if pretty-prod? - (nanopass-case (Lannotated PrettyProduction) pretty-prod? - [(procedure ,handler) `(-> ,pattern ,handler)] - [(pretty ,pattern0) `(=> ,pattern ,(Pattern pattern0))]) - pattern))) - [(production ,[pattern] ,pretty-prod? ,rtd ,tag ,pred ,maker ,field* ...) - (finish-prod pattern pretty-prod?)] - [(terminal ,[pattern] ,pretty-prod?) - (finish-prod pattern pretty-prod?)] - [(nonterminal ,[pattern] ,pretty-prod?) - (finish-prod pattern pretty-prod?)] - [else (errorf who "unexpected Production ~s" (unparse-Lannotated ir))]) - (Reference : Reference (ir) -> Pattern () - [(term-ref ,id0 ,id1 ,b) id0] - [(nt-ref ,id0 ,id1 ,b) id0]) - (Pattern : Pattern (ir) -> Pattern () - [,id id] - [,ref (Reference ref)] - [(maybe ,[pattern]) `(maybe ,pattern)] - [(,[pattern0] ,dots . ,[pattern1]) `(,pattern0 ,dots . ,pattern1)] - [(,[pattern0] . ,[pattern1]) `(,pattern0 . ,pattern1)] - [,null null])) - (define-pass rewrite-annotated-nt : (Lannotated Nonterminal) (ir) -> (Lcomplete Clause) () - (Nonterminal : Nonterminal (ir) -> Clause () - [(,id (,id* ...) ,b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,prod* ...) - `(,id (,id* ...) ,(map rewrite-production prod*) ...)])) - (define (extend-terminals term* old-term* new-term*) - (let loop ([term* term*] [old-term* old-term*] [new-term* new-term*]) - (if (null? term*) - (values old-term* new-term*) - (let-values ([(new-term* old-term*) - (ExtendTerminal (car term*) new-term* old-term*)]) - (loop (cdr term*) old-term* new-term*))))) - (define (extend-productions stx* old-prod*) - (with-values - (let f ([stx* stx*]) - (if (null? stx*) - (values '() old-prod*) - (let-values ([(new-prod* old-prod*) (f (cdr stx*))]) - (ExtendProd (car stx*) new-prod* old-prod*)))) - (lambda (prod* old-prod*) - (fold-left - (lambda (prod* old-prod) - (cons (rewrite-production old-prod) prod*)) - prod* old-prod*)))) - (define (remove-productions stx old-prod*) - (let loop ([stx stx] [old-prod* old-prod*]) - (syntax-case stx () - [() old-prod*] - [_ (with-values (RemoveProd stx old-prod*) loop)]))) - (define (remove-terminal id0 id0* old-term*) - (let f ([old-term* old-term*]) - (if (null? old-term*) - (errorf who "could not find terminal matching (~s ~s)" (syntax->datum id0) (map syntax->datum id0*)) - (let ([old-term (car old-term*)] [old-term* (cdr old-term*)]) - (nanopass-case (Lannotated Terminal) old-term - [(,id (,id* ...) ,b ,handler? ,pred) - (if (and (eq? (syntax->datum id) (syntax->datum id0)) - (equal? (syntax->datum id*) (syntax->datum id0*))) - old-term* - (cons old-term (f old-term*)))]))))) - (define-pass syntax-matches? : (Lannotated Production) (pat stx) -> * (boolean?) - (definitions - (define (identifier-matches? id stx) - (and (identifier? stx) - (eq? (syntax->datum id) (syntax->datum stx))))) - (Production : Production (ir stx) -> * (boolean?) - [(production ,[b?] ,pretty-prod? ,rtd ,tag ,pred ,maker ,field* ...) b?] - [(terminal ,[b?] ,pretty-prod?) b?] - [(nonterminal ,[b?] ,pretty-prod?) b?]) - (Reference : Reference (ir stx) -> * (boolean?) - [(term-ref ,id0 ,id1 ,b) (identifier-matches? id0 stx)] - [(nt-ref ,id0 ,id1 ,b) (identifier-matches? id0 stx)]) - (Pattern : Pattern (pat stx) -> * (boolean?) - [,id (identifier-matches? id stx)] - [,ref (Reference ref stx)] - [(maybe ,[b?]) b?] - [(,pattern0 ,dots . ,pattern1) - (syntax-case stx () - [(p0 dots . p1) (dots? #'dots) - (and (Pattern pattern0 #'p0) (Pattern pattern1 #'p1))] - [_ #f])] - [(,pattern0 . ,pattern1) - (syntax-case stx () - [(p0 . p1) (and (Pattern pattern0 #'p0) (Pattern pattern1 #'p1))] - [_ #f])] - [,null - (syntax-case stx () - [() #t] - [_ #f])]) - (Production pat stx)) - (define (remove-prod stx old-prod*) - (let f ([old-prod* old-prod*]) - (if (null? old-prod*) - (syntax-violation who "unable to find matching old production" stx) - (let ([old-prod (car old-prod*)] [old-prod* (cdr old-prod*)]) - (if (syntax-matches? old-prod stx) - old-prod* - (cons old-prod (f old-prod*))))))) - (define (find-matching-nt id old-nt*) - (let f ([old-nt* old-nt*]) - (if (null? old-nt*) - (values '() '()) - (let ([old-nt (car old-nt*)] [old-nt* (cdr old-nt*)]) - (nanopass-case (Lannotated Nonterminal) old-nt - [(,id0 (,id* ...) ,b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,prod* ...) - (if (eq? (syntax->datum id0) (syntax->datum id)) - (values old-nt* prod*) - (let-values ([(old-nt* prod*) (f old-nt*)]) - (values (cons old-nt old-nt*) prod*)))]))))) - ) - (Defn : Defn (def) -> Defn () - [(define-language ,id ,cl* ...) - `(define-language ,id - ,(cond - [(language-extension? cl*) => - (lambda (base-lang-id) - (extend-clauses cl* - (language-information-annotated-language - (lookup-language rho base-lang-id))))] - [else (map FinishClause cl*)]) - ...)]) - (FinishClause : Clause (cl) -> Clause () - [(terminals ,[FinishTerminal : term* -> term*] ...) `(terminals ,term* ...)] - [(,id (,id* ...) ,prod ,prod* ...) - `(,id (,id* ...) ,(parse-productions (cons prod prod*)) ...)]) - (FinishTerminal : Terminal (term) -> Terminal () - [(+ ,base-term* ...) (errorf who "unexpected terminal extension clause ~s" (unparse-Lnp-source term))] - [(- ,base-term* ...) (errorf who "unexpected terminal extension clause ~s" (unparse-Lnp-source term))]) - (FinishProd : syntax (stx) -> Production (stx) - (syntax-case stx () - [(?pattern => ?pretty . ?rest) - (double-arrow? #'=>) - (values `(=> ,(Pattern #'?pattern) ,(Pattern #'?pretty)) #'?rest)] - [((=> ?pattern ?handler) . ?rest) - (double-arrow? #'=>) - (values `(=> ,(Pattern #'?pattern) ,(Pattern #'?pretty)) #'?rest)] - [(?pattern -> ?handler . ?rest) - (arrow? #'->) - (values `(-> ,(Pattern #'?pattern) ,#'?handler) #'?rest)] - [((-> ?pattern ?handler) . ?rest) - (arrow? #'->) - (values `(-> ,(Pattern #'?pattern) ,#'?handler) #'?rest)] - [(?x . ?rest) (values (Pattern #'?x) #'?rest)] - [_ (syntax-violation who "unrecognized productions list" stx)])) - (ExtendClause : Clause (cl old-term* old-nt* cl* new-term*) -> * (old-term* old-nt* cl* new-term*) - [(terminals ,term* ...) - (let-values ([(old-term* new-term*) (extend-terminals term* old-term* new-term*)]) - (values old-term* old-nt* cl* new-term*))] - [(,id (,id* ...) ,prod ,prod* ...) - (let-values ([(old-nt* old-prod*) (find-matching-nt id old-nt*)]) - (let ([prod* (extend-productions (cons prod prod*) old-prod*)]) - (values old-term* old-nt* - (if (null? prod*) - cl* - (cons - (in-context Clause - `(,id (,id* ...) ,prod* ...)) - cl*)) - new-term*)))] - [(extends ,id) (values old-term* old-nt* cl* new-term*)] - [(entry ,id) (values old-term* old-nt* (cons (in-context Clause `(entry ,id)) cl*) new-term*)] - [(nongenerative-id ,id) - (values old-term* old-nt* (cons (in-context Clause `(nongenerative-id ,id)) cl*) new-term*)]) - (ExtendTerminal : Terminal (term new-term* old-term*) -> * (new-term* old-term*) - [(+ ,[term*] ...) - (values (append term* new-term*) old-term*)] - [(- ,base-term* ...) - (values - new-term* - (fold-left - (lambda (old-term* base-term) (RemoveTerminal base-term old-term*)) - old-term* base-term*))] - [,base-term (errorf who "unexpected non-extension terminal in extended language ~s" (unparse-Lnp-source base-term))]) - (RemoveTerminal : BaseTerminal (ir old-term*) -> * (old-term*) - [(,id (,id* ...)) (remove-terminal id id* old-term*)] - [(=> (,id (,id* ...)) ,handler) (remove-terminal id id* old-term*)] - [else (errorf who "unexpected base terminal ~s" (unparse-Lnp-source ir))]) - (BaseTerminal : BaseTerminal (ir) -> Terminal ()) - (ExtendProd : syntax (stx new-prod* old-prod*) -> * (new-prod* old-prod*) - (syntax-case stx () - [(+ ?prod* ...) - (plus? #'+) - (values (parse-productions #'(?prod* ...) new-prod*) old-prod*)] - [(- ?prod* ...) - (minus? #'-) - (values new-prod* (remove-productions #'(?prod* ...) old-prod*))] - [_ (syntax-violation who "unexpected production extension syntax" stx)])) - (RemoveProd : syntax (stx old-prod*) -> * (stx old-prod*) - (let-values ([(pattern rest) - (syntax-case stx () - [(?pattern => ?handler . ?rest) (double-arrow? #'=>) (values #'?pattern #'?rest)] - [((=> ?pattern ?handler) . ?rest) (double-arrow? #'=>) (values #'?pattern #'?rest)] - [(?pattern -> ?pretty . ?rest) (arrow? #'->) (values #'?pattern #'?rest)] - [((-> ?pattern ?pretty) . ?rest) (arrow? #'->) (values #'?pattern #'?rest)] - [(?pattern . ?rest) (values #'?pattern #'?rest)] - [_ (syntax-violation who "unrecognized productions list" stx)])]) - (values rest (remove-prod pattern old-prod*)))) - (Pattern : * (stx) -> Pattern () - (syntax-case stx () - [?id (identifier? #'?id) #'?id] - [(maybe ?id) - (and (maybe? #'maybe) (identifier? #'?id)) - `(maybe ,#'?id)] - [(?pattern0 dots . ?pattern1) - (ellipsis? #'dots) - `(,(Pattern #'?pattern0) ,#'dots . ,(Pattern #'?pattern1))] - [(?pattern0 . ?pattern1) - `(,(Pattern #'?pattern0) . ,(Pattern #'?pattern1))] - [() '()]))) - - (define-language Llanguage - (extends Lcomplete) - (terminals - (+ (box (b)))) - (Clause (cl) - (- (entry id) - (id (id* ...) prod* ...)) - (+ (entry ref) - (id (id* ...) b prod* ...))) - (Reference (ref) - (+ (term-ref id0 id1 b) => id0 - (nt-ref id0 id1 b) => id0)) - (SimpleTerminal (simple-term) - (- (id (id* ...))) - (+ (id (id* ...) b))) - (Pattern (pattern) - (- (maybe id)) - (+ ref - (maybe ref)))) - - (define meta-variable-suffix-checker - (make-parameter - (lambda (str) - (let f ([i (string-length str)]) - (or (fx=? i 0) - (let* ([i (fx- i 1)] - [c (string-ref str i)]) - (cond - [(or (char=? c #\*) (char=? c #\^) (char=? c #\?)) (f i)] - [(char-numeric? c) - (let f ([i i]) - (or (fx=? i 0) - (let ([i (fx- i 1)]) - (and (char-numeric? (string-ref str i)) (f i)))))] - [else #f]))))) - (lambda (x) - (unless (procedure? x) (errorf 'meta-variable-suffix-checker "expected procedure, but got ~s" x)) - x))) - - (define-pass check-and-finish-language : Lcomplete (ir) -> Llanguage () - (definitions - (define (build-and-check-maps cl*) - (let ([ht (make-eq-hashtable)]) - (let ([pt (fold-left (lambda (pt cl) (ExtendMapsClause cl pt ht)) (empty-prefix-tree) cl*)]) - (values pt ht)))) - (define (extract-all-terminals cl* pt ht) - (let f ([cl* cl*]) - (if (null? cl*) - (values '() '()) - (let ([cl (car cl*)]) - (let-values ([(term-out* cl-out*) (f (cdr cl*))]) - (nanopass-case (Lcomplete Clause) cl - [(terminals ,term* ...) - (values - (fold-right - (lambda (term term-out*) (cons (Terminal term ht) term-out*)) - term-out* - term*) - cl-out*)] - [else (values term-out* (cons cl cl-out*))])))))) - (define (extract-all-nonterminals cl* pt ht) - (let f ([cl* cl*]) - (if (null? cl*) - (values '() '()) - (let-values ([(nt* cl-out*) (f (cdr cl*))]) - (let ([cl (car cl*)]) - (nanopass-case (Lcomplete Clause) cl - [(,id (,id* ...) ,prod* ...) - (values (cons (Clause cl pt ht) nt*) cl-out*)] - [else (values nt* (cons cl cl-out*))])))))) - (define (check-and-rewrite-clauses cl* pt ht) - (let*-values ([(term* cl*) (extract-all-terminals cl* pt ht)] - [(nt* cl*) (extract-all-nonterminals cl* pt ht)]) - (fold-left - (lambda (cl* cl) (cons (Clause cl pt ht) cl*)) - (with-output-language (Llanguage Clause) - (cons `(terminals ,term* ...) nt*)) - cl*))) - (define (build-ref terminal? mv id b) - (with-output-language (Llanguage Reference) - (if terminal? - `(term-ref ,mv ,id ,b) - `(nt-ref ,mv ,id ,b)))) - (define ref - (case-lambda - [(ht id) - (let ([sym (syntax->datum id)]) - (or (eq-hashtable-ref ht sym #f) - (let ([b (box #f)]) - (eq-hashtable-set! ht sym b) - b)))] - [(pt ht id) - (let* ([str (symbol->string (syntax->datum id))] - [pr (match-prefix pt str (meta-variable-suffix-checker))] - [terminal? (car pr)] - [raw-id (cdr pr)]) - (unless raw-id (syntax-violation who "unable to find matching metavariable" id)) - (build-ref terminal? id raw-id (ref ht raw-id)))])) - (define (maybe-ref pt ht id) - (let* ([str (symbol->string (syntax->datum id))] - [pr (match-prefix pt str (meta-variable-suffix-checker))]) - (if pr - (let ([terminal? (car pr)] [raw-id (cdr pr)]) - (build-ref terminal? id raw-id (ref ht raw-id))) - id)))) - (Defn : Defn (ir) -> Defn () - [(define-language ,id ,cl* ...) - (let-values ([(pt ht) (build-and-check-maps cl*)]) - (let ([cl* (check-and-rewrite-clauses cl* pt ht)]) - `(define-language ,id ,cl* ...)))]) - (ExtendMapsClause : Clause (cl pt ht) -> * (pt) - [(terminals ,term* ...) (fold-left (lambda (pt term) (ExtendMapsTerminal term pt ht)) pt term*)] - [(,id (,id* ...) ,prod* ...) - ;; should we be using an identifier hashtable? or symbol hashtable? - (eq-hashtable-set! ht (syntax->datum id) (box #f)) - (let ([pr (cons #f id)]) - (fold-left (lambda (pt mv-id) (insert-prefix pt (symbol->string (syntax->datum mv-id)) pr)) pt id*))] - [else pt]) - (ExtendMapsTerminal : Terminal (term pt ht) -> * (pt) - [,simple-term (ExtendMapsSimpleTerminal simple-term pt ht)] - [(=> ,simple-term ,handler) (ExtendMapsSimpleTerminal simple-term pt ht)]) - (ExtendMapsSimpleTerminal : SimpleTerminal (simple-term pt ht) -> * (pt) - [(,id (,id* ...)) - (eq-hashtable-set! ht (syntax->datum id) (box #f)) - (let ([pr (cons #t id)]) - (fold-left (lambda (pt mv-id) (insert-prefix pt (symbol->string (syntax->datum mv-id)) pr)) pt id*))]) - (Terminal : Terminal (term ht) -> Terminal () - [(,id (,id* ...)) - (let* ([b (ref ht id)] - [term `(,id (,id* ...) ,b)]) - (set-box! b term) - term)] - [(=> (,id (,id* ...)) ,handler) - (let* ([b (ref ht id)] - [term `(=> (,id (,id* ...) ,b) ,handler)]) - (set-box! b term) - term)] - [,simple-term (errorf who "unreachable match ,simple-term, reached!")] - [(=> ,simple-term ,handler) (errorf who "unreachable match (=> ,simple-term ,handler), reached!")]) - (Clause : Clause (cl pt ht) -> Clause () - [(entry ,id) `(entry (nt-ref ,id ,id ,(ref ht id)))] - [(nongenerative-id ,id) `(nongenerative-id ,id)] - [(terminals ,term* ...) (errorf who "unexpected terminal clause after terminals were filtered")] - [(,id (,id* ...) ,prod* ...) - (let* ([b (ref ht id)] - [prod* (map (lambda (prod) (Production prod pt ht)) prod*)] - [cl `(,id (,id* ...) ,b ,prod* ...)]) - (set-box! b cl) - cl)]) - (Production : Production (prod pt ht) -> Production () - [,pattern (Pattern pattern pt ht)] - [(=> ,[pattern0] ,[pattern1 (empty-prefix-tree) ht -> pattern1]) `(=> ,pattern0 ,pattern1)] - [(-> ,[pattern] ,handler) `(-> ,pattern ,handler)]) - (Pattern : Pattern (pattern pt ht) -> Pattern () - [,id (maybe-ref pt ht id)] - [(maybe ,id) (ref pt ht id)] - [(,[pattern0] ,dots . ,[pattern1]) `(,pattern0 ,dots . ,pattern1)] - [(,[pattern0] . ,[pattern1]) `(,pattern0 . ,pattern1)] - [,null null]) - ) - - (define-language Lannotated - (extends Llanguage) - (terminals - (- (datum (handler))) - (+ (datum (handler record-name pred all-pred all-term-pred accessor maker)) - (exact-integer (tag level tag-mask)) - (record-type-descriptor (rtd)) - (record-constructor-descriptor (rcd)))) - (Defn (def) - (- (define-language id cl* ...)) - (+ (define-language - id ;; language name - ref ;; reference to entry ntspec - (maybe id0) ;; nongenerative-id - rtd - rcd - tag-mask - (term* ...) - nt* ...))) - (Clause (cl) - (- (entry ref) - (nongenerative-id id) - (terminals term* ...) - (id (id* ...) b prod* ...))) - (Nonterminal (nt) - (+ (id (id* ...) b rtd rcd tag pred all-pred all-term-pred prod* ...) => (id (id* ...) prod* ...))) - (PrettyProduction (pretty-prod) - (+ (procedure handler) - (pretty pattern))) - (Production (prod) - (- pattern - (=> (=> pattern0 pattern1) - (=> pattern0 pattern1)) - (=> (-> pattern handler) - (-> pattern handler))) - (+ (production pattern (maybe pretty-prod) rtd tag pred maker field* ...) - (terminal ref (maybe pretty-prod)) - (nonterminal ref (maybe pretty-prod)))) - (Field (field) - (+ (ref level accessor) - (optional ref level accessor))) - (Terminal (term) - (- simple-term - (=> (=> simple-term handler) - (=> simple-term handler))) - (+ (id (id* ...) b (maybe handler) pred) => (id (id* ...) handler pred))) - (SimpleTerminal (simple-term) - (- (id (id* ...) b)))) - - ;; TODO: fix the entry for language extenions - (define-pass annotate-language : Llanguage (lang) -> Lannotated () - (definitions - (define-pass build-ref : (Llanguage Clause) (cl) -> (Llanguage Reference) () - (build-ref : Clause (cl) -> Reference () - [(,id (,id* ...) ,b ,prod* ...) `(nt-ref ,id ,id ,b)] - [else (errorf who "unexpected clause ~s" (unparse-Llanguage cl))])) - (define (separate-clauses cl*) - (let loop ([cl* cl*] [entry #f] [first-nt #f] [nongen-id #f] [rterm* '()] [rnt* '()] [rb* '()]) - (if (null? cl*) - (values (or entry (build-ref first-nt)) nongen-id (reverse rterm*) (reverse rnt*) rb*) - (with-values - (BinClause (car cl*) entry first-nt nongen-id rterm* rnt* rb*) - (lambda (entry first-nt nongen-id rterm* rnt* rb*) - (loop (cdr cl*) entry first-nt nongen-id rterm* rnt* rb*)))))) - (define (annotate-terminals term*) (map Terminal term*)) - (define (annotate-nonterminals nt* lang-name lang-rtd lang-rcd nongen-id) - (let ([bits (fxlength (length nt*))]) - (let f ([nt* nt*] [tag 0]) - (if (null? nt*) - '() - (cons - (Nonterminal (car nt*) lang-name lang-rtd lang-rcd bits tag nongen-id) - (f (cdr nt*) (fx+ tag 1))))))) - (define (build-production pattern nt-rtd lang-name nt-name tag pretty nongen-id) - (define-pass find-prod-name : (Llanguage Pattern) (pattern) -> * (id) - (Pattern : Pattern (pattern) -> * (id) - [,id id] - [,ref (Reference ref)] - [(maybe ,[id]) id] - [(,[id] ,dots . ,pattern1) id] - [(,[id] . ,pattern1) id] - [else (construct-id #'* "anonymous")]) - (Reference : Reference (ref) -> * (id) - [(term-ref ,id0 ,id1 ,b) id0] - [(nt-ref ,id0 ,id1 ,b) id0]) - (Pattern pattern)) - (let* ([prod-name (find-prod-name pattern)] - [base-name (unique-name lang-name nt-name prod-name)]) - (let-values ([(pattern field* field-name*) (Pattern pattern base-name 0 '() '())]) - (let* ([rtd (make-record-type-descriptor (string->symbol base-name) nt-rtd - (if nongen-id - (regensym nongen-id - (format ":~s:~s" (syntax->datum nt-name) (syntax->datum prod-name)) - (format "-~s" tag)) - (gensym base-name)) - #t #f - (list->vector (map (lambda (fn) `(immutable ,(syntax->datum fn))) field-name*)))] - [pred (construct-id #'* base-name "?")] - [maker (construct-id #'* "make-" base-name)]) - (with-output-language (Lannotated Production) - `(production ,pattern ,pretty ,rtd ,tag ,pred ,maker ,field* ...)))))) - (define (build-accessor record-name id) (construct-id #'* record-name id)) - (with-output-language (Lannotated PrettyProduction) - (define (pretty-pattern pattern) - `(pretty ,(RewritePattern pattern))) - (define (pretty-procedure handler) - `(procedure ,handler))) - ) - (Defn : Defn (def) -> Defn () - [(define-language ,id ,cl* ...) - (let-values ([(entry nongen-id term* nt* b*) (separate-clauses cl*)]) - (let* ([rtd (make-record-type-descriptor (syntax->datum id) - (record-type-descriptor nanopass-record) - (if nongen-id (syntax->datum nongen-id) (gensym (unique-name id))) - #f #f (vector))] - [rcd (make-record-constructor-descriptor rtd - (record-constructor-descriptor nanopass-record) #f)] - [tag-mask (fx- (fxarithmetic-shift-left 1 (fxlength (length nt*))) 1)] - [term* (annotate-terminals term*)] - [nt* (annotate-nonterminals nt* id rtd rcd nongen-id)]) - (let-values ([(ref ref-id) (Reference entry)]) - (for-each (lambda (b) (set-box! b (cdr (unbox b)))) b*) - `(define-language ,id ,ref ,nongen-id ,rtd ,rcd ,tag-mask (,term* ...) ,nt* ...))))]) - (BinClause : Clause (cl entry first-nt nongen-id rterm* rnt* rb*) -> * (entry first-nt nongen-id rterm* rnt* rb*) - [(entry ,ref) - (when entry (errorf who "found more than one entry")) - (values ref first-nt nongen-id rterm* rnt* rb*)] - [(nongenerative-id ,id) - (when nongen-id (syntax-violation who "found more than one nongenerative-id" id)) - (values entry first-nt id rterm* rnt* rb*)] - [(terminals ,term* ...) - (values entry first-nt nongen-id (append term* rterm*) rnt* (fold-right GrabTermBox rb* term*))] - [(,id (,id* ...) ,b ,prod* ...) - (let ([new-b (box #f)]) - (set-box! b (cons new-b (unbox b))) - (values entry (or first-nt cl) nongen-id rterm* (cons cl rnt*) (cons b rb*)))]) - (GrabTermBox : Terminal (term rb*) -> * (rb*) - [(,id (,id* ...) ,b) - (let ([new-b (box #f)]) - (set-box! b (cons new-b (unbox b))) - (cons b rb*))] - [(=> (,id (,id* ...) ,b) ,handler) - (let ([new-b (box #f)]) - (set-box! b (cons new-b (unbox b))) - (cons b rb*))] - ;; unreachable! - [else (errorf who "unreachable")]) - (Terminal : Terminal (term) -> Terminal () - [(,id (,id* ...) ,b) - (let* ([new-b (car (unbox b))] - [term `(,id (,id* ...) ,new-b #f ,(construct-id id id "?"))]) - (set-box! new-b term) - term)] - [(=> (,id (,id* ...) ,b) ,handler) - (let* ([new-b (car (unbox b))] - [term `(,id (,id* ...) ,new-b ,handler ,(construct-id id id "?"))]) - (set-box! new-b term) - term)] - [else (errorf who "unexpected terminal ~s" (unparse-Llanguage term))]) - (Nonterminal : Clause (cl lang-name lang-rtd lang-rcd bits tag nongen-id) -> Nonterminal () - [(,id (,id* ...) ,b ,prod* ...) - (let* ([record-name (unique-name lang-name id)] - [rtd (make-record-type-descriptor - (string->symbol record-name) - lang-rtd - (if nongen-id - (regensym nongen-id - (format ":~s" (syntax->datum id)) - (format "-~d" tag)) - (gensym record-name)) - #f #f (vector))] - [rcd (make-record-constructor-descriptor rtd lang-rcd #f)] - [pred (construct-id #'* record-name "?")] - [all-pred (construct-id lang-name lang-name "-" id "?")] - [all-term-pred (construct-id #'* lang-name "-" id "-terminal?")]) - (let loop ([prod* prod*] [next 1] [rprod* '()]) - (if (null? prod*) - (let* ([new-b (car (unbox b))] - [nt `(,id (,id* ...) ,new-b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,(reverse rprod*) ...)]) - (set-box! new-b nt) - nt) - (let ([prod-tag (fx+ (fxarithmetic-shift-left next bits) tag)]) - (loop - (cdr prod*) - (fx+ next 1) - (cons (Production (car prod*) rtd lang-name id prod-tag nongen-id) rprod*))))))] - [else (errorf who "unexpected clause in Nonterminal ~s" (unparse-Llanguage cl))]) - (Production : Production (prod nt-rtd lang-name nt-name prod-tag nongen-id) -> Production () - [,ref (BaseReference ref #f)] - [(=> ,ref ,pattern1) (BaseReference ref (pretty-pattern pattern1))] - [(-> ,ref ,handler) (BaseReference ref (pretty-procedure handler))] - [,pattern (build-production pattern nt-rtd lang-name nt-name prod-tag #f nongen-id)] - [(=> ,pattern0 ,pattern1) (build-production pattern0 nt-rtd lang-name nt-name prod-tag (pretty-pattern pattern1) nongen-id)] - [(-> ,pattern ,handler) (build-production pattern nt-rtd lang-name nt-name prod-tag (pretty-procedure handler) nongen-id)]) - (BaseReference : Reference (ref maybe-pretty) -> Production () - [(term-ref ,id0 ,id1 ,b) `(terminal (term-ref ,id0 ,id1 ,b) ,maybe-pretty)] - [(nt-ref ,id0 ,id1 ,b) `(nonterminal (nt-ref ,id0 ,id1 ,b) ,maybe-pretty)]) - (RewritePattern : Pattern (pattern) -> Pattern ()) - (Pattern : Pattern (pattern record-name level flds fns) -> Pattern (flds fns) - [,id (values id flds fns)] - [,ref - (let-values ([(ref meta-var) (Reference ref)]) - (values - ref - (cons - (in-context Field - `(,ref ,level ,(build-accessor record-name meta-var))) - flds) - (cons meta-var fns)))] - [(maybe ,ref) - (let-values ([(ref meta-var) (Reference ref)]) - (values - `(maybe ,ref) - (cons - (in-context Field - `(optional ,ref ,level ,(build-accessor record-name meta-var))) - flds) - (cons meta-var fns)))] - [(,pattern0 ,dots . ,pattern1) - (let*-values ([(pattern1 flds fns) (Pattern pattern1 record-name level flds fns)] - [(pattern0 flds fns) (Pattern pattern0 record-name (fx+ level 1) flds fns)]) - (values `(,pattern0 ,dots . ,pattern1) flds fns))] - [(,pattern0 . ,pattern1) - (let*-values ([(pattern1 flds fns) (Pattern pattern1 record-name level flds fns)] - [(pattern0 flds fns) (Pattern pattern0 record-name level flds fns)]) - (values `(,pattern0 . ,pattern1) flds fns))] - [,null (values null flds fns)]) - (Reference : Reference (ref) -> Reference (id) - [(term-ref ,id0 ,id1 ,b) (values `(term-ref ,id0 ,id1 ,(car (unbox b))) id0)] - [(nt-ref ,id0 ,id1 ,b) (values `(nt-ref ,id0 ,id1 ,(car (unbox b))) id0)]) - ) - - (define-pass prune-lang : Lannotated (ir caller-who maybe-name) -> * (stx) - (Defn : Defn (ir) -> * (stx) - [(define-language ,id ,ref ,id0? ,rtd ,rcd ,tag-mask (,term* ...) ,nt* ...) - (let ([ht (make-eq-hashtable)]) - (let-values ([(entry-id ts nts) (FollowReference ref ht '() '())]) - (with-syntax ([define-language-exp (datum->syntax id 'define-language-exp)]) - (with-implicit (id entry terminals nongenerative-id) - #`(define-language-exp #,(or maybe-name id) - (entry #,entry-id) - #,@(if id0? #`((nongenerative-id #,id0?)) #'()) - (terminals #,@ts) - #,@nts)))))]) - (FollowReference : Reference (ir ht ts nts) -> * (id ts nts) - [(term-ref ,id0 ,id1 ,b) - (unless (eq-hashtable-ref ht ir #f) - (eq-hashtable-set! ht ir #t) - (FollowTerminal (unbox b) ts nts id0))] - [(nt-ref ,id0 ,id1 ,b) - (unless (eq-hashtable-ref ht ir #f) - (eq-hashtable-set! ht ir #t) - (FollowNonterminal (unbox b) ht ts nts id0))]) - (FollowTerminal : Terminal (ir ts nts id0) -> * (id0 ts nts) - [(,id (,id* ...) ,b ,handler? ,pred) - (values - id0 - (cons - (if handler? - #`(=> (#,id #,id*) #,handler?) - #`(#,id #,id*)) - ts) - nts)]) - (FollowNonterminal : Nonterminal (ir ht ts nts id0) -> * (id0 ts nts) - [(,id (,id* ...) ,b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,prod* ...) - (let loop ([prod* prod*] [ts ts] [nts nts] [rprod* '()]) - (if (null? prod*) - (values id0 ts (cons #`(#,id #,id* . #,rprod*) nts)) - (let-values ([(prod ts nts) (Production (car prod*) ht ts nts)]) - (loop (cdr prod*) ts nts (cons prod rprod*)))))]) - (Production : Production (ir ht ts nts) -> * (stx ts nts) - (definitions (define (maybe-wrap pp? stx) (if pp? (PrettyProduction pp? stx) stx))) - [(production ,[stx] ,pretty-prod? ,rtd ,tag ,pred ,maker ,field* ...) - (let loop ([field* field*] [ts ts] [nts nts]) - (if (null? field*) - (values (maybe-wrap pretty-prod? stx) ts nts) - (let-values ([(ts nts) (FollowField (car field*) ht ts nts)]) - (loop (cdr field*) ts nts))))] - [(terminal ,ref ,pretty-prod?) - (let-values ([(id0 ts nts) (FollowReference ref ht ts nts)]) - (values (maybe-wrap pretty-prod? id0) ts nts))] - [(nonterminal ,ref ,pretty-prod?) - (let-values ([(id0 ts nts) (FollowReference ref ht ts nts)]) - (values (maybe-wrap pretty-prod? id0) ts nts))]) - (FollowField : Field (field ht ts nts) -> * (ts nts) - [(,[id0 ts nts] ,level ,accessor) (values ts nts)] - [(optional ,[id0 ts nts] ,level ,accessor) (values ts nts)]) - (PrettyProduction : PrettyProduction (ir stx) -> * (stx) - [(procedure ,handler) #`(-> #,stx #,handler)] - [(pretty ,[pattern]) #`(=> #,stx #,pattern)]) - (Pattern : Pattern (ir) -> * (stx) - [,id id] - [,ref (Reference ref)] - [,null #'()] - [(maybe ,[id]) #`(maybe #,id)] - [(,[pattern0] ,dots . ,[pattern1]) - #`(#,pattern0 (... ...) . #,pattern1)] - [(,[pattern0] . ,[pattern1]) #`(#,pattern0 . #,pattern1)]) - (Reference : Reference (ir) -> * (id) - [(term-ref ,id0 ,id1 ,b) id0] - [(nt-ref ,id0 ,id1 ,b) id0]) - (Defn ir)) - - (define-pass diff-langs : Llanguage (ir-out ir-base) -> * (stx) - (definitions - (define (separate-clauses cl*) - (let loop ([cl* cl*] [rcl* '()] [term* '()] [nt* '()]) - (if (null? cl*) - (values rcl* term* nt*) - (let-values ([(rcl* term* nt*) (BinClause (car cl*) rcl* term* nt*)]) - (loop (cdr cl*) rcl* term* nt*))))) - (define (find-matching-terminal id term1*) - (let f ([term1* term1*]) - (if (null? term1*) - (values #f '()) - (let ([term (car term1*)]) - (nanopass-case (Llanguage Terminal) term - [(,id1 (,id1* ...) ,b) - (if (eq? (syntax->datum id) - (syntax->datum id1)) - (values #t (cdr term1*)) - (let-values ([(found? term1*) (f (cdr term1*))]) - (values found? (cons term term1*))))] - [(=> (,id1 (,id1* ...) ,b) ,handler) - (if (eq? (syntax->datum id) - (syntax->datum id1)) - (values #t (cdr term1*)) - (let-values ([(found? term1*) (f (cdr term1*))]) - (values found? (cons term term1*))))]))))) - (define (find-matching-nonterminal id nt1*) - (let f ([nt1* nt1*]) - (if (null? nt1*) - (values '() '()) - (let ([nt (car nt1*)]) - (nanopass-case (Llanguage Clause) nt - [(,id1 (,id1* ...) ,b ,prod* ...) - (if (eq? (syntax->datum id) - (syntax->datum id1)) - (values prod* (cdr nt1*)) - (let-values ([(prod* nt1*) (f (cdr nt1*))]) - (values prod* (cons nt nt1*))))] - [else (errorf who "unexpected clause in nonterminal ~s" (unparse-Llanguage nt))]))))) - (define (add-terms-clause type term* cl*) - (if (null? term*) - cl* - (cons #`(#,type . #,term*) cl*))) - (define (Terminal* term0* term1*) - (let loop ([term0* term0*] [term1* term1*] [add-term* '()]) - (if (null? term0*) - (add-terms-clause #'- (map RewriteTerminal term1*) - (add-terms-clause #'+ add-term* '())) - (let-values ([(term1* add-term*) (Terminal (car term0*) term1* add-term*)]) - (loop (cdr term0*) term1* add-term*))))) - (define (Nonterminal* nt0* nt1*) - (let loop ([nt0* nt0*] [nt1* nt1*] [rnt* '()]) - (if (null? nt0*) - (reverse - (fold-left - (lambda (rnt* nt) - (nanopass-case (Llanguage Clause) nt - [(,id (,id* ...) ,b ,prod* ...) - #`(#,id #,id* (- . #,(map RewriteProduction prod*)))] - [else (errorf who "unexpected clause in nonterminal ~s" (unparse-Llanguage nt))])) - rnt* nt1*)) - (let-values ([(rnt* nt1*) (Nonterminal (car nt0*) nt1* rnt*)]) - (loop (cdr nt0*) nt1* rnt*))))) - (define (add-productions type prod* cl*) - (if (null? prod*) - cl* - (cons - #`(#,type . #,(fold-left - (lambda (out* prod) - (cons (RewriteProduction prod) out*)) - '() prod*)) - cl*))) - (define (Production* prod0* prod1*) - (let loop ([prod0* prod0*] [prod1* prod1*] [add-prod* '()]) - (if (null? prod0*) - (add-productions #'- prod1* - (add-productions #'+ add-prod* '())) - (let-values ([(prod1* add-prod*) - (Production (car prod0*) prod1* add-prod*)]) - (loop (cdr prod0*) prod1* add-prod*))))) - (define (find-matching-pattern pattern prod1*) - (let f ([prod1* prod1*]) - (if (null? prod1*) - (values #f '()) - (let* ([prod1 (car prod1*)] - [pattern1 (ProductionPattern prod1)]) - (if (Pattern=? pattern pattern1) - (values #t (cdr prod1*)) - (let-values ([(found? prod1*) (f (cdr prod1*))]) - (values found? (cons prod1 prod1*)))))))) - ) - (Defn : Defn (ir-out ir-base) -> * (stx) - [(define-language ,id0 ,cl0* ...) - (let-values ([(base-cl* term0* nt0*) (separate-clauses cl0*)]) - (nanopass-case (Llanguage Defn) ir-base - [(define-language ,id1 ,cl1* ...) - (let-values ([(_ term1* nt1*) (separate-clauses cl1*)]) - (let ([term* (Terminal* term0* term1*)] - [nt* (Nonterminal* nt0* nt1*)]) - (if (null? term*) - #`(define-language #,id0 #,@base-cl* . #,nt*) - #`(define-language #,id0 #,@base-cl* (terminals . #,term*) . #,nt*))))]))]) - (BinClause : Clause (ir cl* all-term* nt*) -> * (cl* all-term* nt*) - [(entry ,[id]) (values (cons #`(entry #,id) cl*) all-term* nt*)] - [(nongenerative-id ,id) (values (cons #`(nongenerative-id #,id) cl*) all-term* nt*)] - [(terminals ,term* ...) (values cl* (append term* all-term*) nt*)] - [(,id (,id* ...) ,b ,prod* ...) (values cl* all-term* (cons ir nt*))]) - (Terminal : Terminal (term0 term1* add-term*) -> * (term1* add-term*) - [(=> (,id (,id* ...) ,b) ,handler) - (let-values ([(found? term1*) (find-matching-terminal id term1*)]) - (if found? - (values term1* add-term*) - (values - term1* - (cons #`(=> (#,id #,id*) #,handler) add-term*))))] - [(,id (,id* ...) ,b) - (let-values ([(found? term1*) (find-matching-terminal id term1*)]) - (if found? - (values term1* add-term*) - (values - term1* - (cons #`(#,id #,id*) add-term*))))] - [else (errorf who "unreachable clause in Terminal")]) - (Nonterminal : Clause (nt0 nt1* rnt*) -> * (rnt* nt1*) - [(,id (,id* ...) ,b ,prod* ...) - (let*-values ([(prod1* nt1*) (find-matching-nonterminal id nt1*)]) - (let ([prod* (Production* prod* prod1*)]) - (if (null? prod*) - (values rnt* nt1*) - (values (cons #`(#,id #,id* . #,prod*) rnt*) nt1*))))] - [else (errorf who "unexpected clause ~s" (unparse-Llanguage nt0))]) - (Production : Production (prod prod1* add-prod*) -> * (prod1* add-prod*) - [,pattern - (let-values ([(found? prod1*) (find-matching-pattern pattern prod1*)]) - (if found? - (values prod1* add-prod*) - (values prod1* (cons prod add-prod*))))] - [(=> ,pattern0 ,pattern1) - (let-values ([(found? prod1*) (find-matching-pattern pattern0 prod1*)]) - (if found? - (values prod1* add-prod*) - (values prod1* (cons prod add-prod*))))] - [(-> ,pattern ,handler) - (let-values ([(found? prod1*) (find-matching-pattern pattern prod1*)]) - (if found? - (values prod1* add-prod*) - (values prod1* (cons prod add-prod*))))]) - (Pattern=? : Pattern (pattern0 pattern1) -> * (bool?) - [,id0 (nanopass-case (Llanguage Pattern) pattern1 - [,id1 (eq? (syntax->datum id0) (syntax->datum id1))] - [else #f])] - [,ref0 (nanopass-case (Llanguage Pattern) pattern1 - [,ref1 (Reference=? ref0 ref1)] - [else #f])] - [,null0 (nanopass-case (Llanguage Pattern) pattern1 - [,null1 #t] - [else #f])] - [(maybe ,ref0) - (nanopass-case (Llanguage Pattern) pattern1 - [(maybe ,ref1) (Reference=? ref0 ref1)] - [else #f])] - [(,pattern00 ,dots . ,pattern10) - (nanopass-case (Llanguage Pattern) pattern1 - [(,pattern01 ,dots . ,pattern11) - (and (Pattern=? pattern00 pattern01) - (Pattern=? pattern10 pattern11))] - [else #f])] - [(,pattern00 . ,pattern10) - (nanopass-case (Llanguage Pattern) pattern1 - [(,pattern01 . ,pattern11) - (and (Pattern=? pattern00 pattern01) - (Pattern=? pattern10 pattern11))] - [else #f])]) - (Reference=? : Reference (ref0 ref1) -> * (bool?) - [(term-ref ,id00 ,id10 ,b0) - (nanopass-case (Llanguage Pattern) ref1 - [(term-ref ,id01 ,id11 ,b1) - (eq? (syntax->datum id00) - (syntax->datum id01))] - [else #f])] - [(nt-ref ,id00 ,id10 ,b0) - (nanopass-case (Llanguage Pattern) ref1 - [(nt-ref ,id01 ,id11 ,b1) - (eq? (syntax->datum id00) - (syntax->datum id01))] - [else #f])]) - (ProductionPattern : Production (ir) -> * (stx) - [,pattern pattern] - [(=> ,pattern0 ,pattern1) pattern0] - [(-> ,pattern ,handler) pattern]) - (RewriteTerminal : Terminal (ir) -> * (stx) - [(,id (,id* ...) ,b) #`(#,id #,id*)] - [(=> (,id (,id* ...) ,b) ,handler) - #`(=> (#,id #,id*) ,handler)] - [else (errorf who "unexpected terminal ~s" (unparse-Llanguage ir))]) - (RewriteProduction : Production (ir) -> * (stx) - [,pattern (RewritePattern pattern)] - [(=> ,[stx0] ,[stx1]) #`(=> #,stx0 #,stx1)] - [(-> ,[stx0] ,handler) #`(-> #,stx0 ,handler)]) - (RewritePattern : Pattern (ir) -> * (stx) - [,id id] - [,ref (RewriteReference ref)] - [,null #'()] - [(maybe ,[id]) #`(maybe #,id)] - [(,[stx0] ,dots . ,[stx1]) - #`(#,stx0 (... ...) . #,stx1)] - [(,[stx0] . ,[stx1]) #`(#,stx0 . #,stx1)]) - (RewriteReference : Reference (ir) -> * (stx) - [(term-ref ,id0 ,id1 ,b) id0] - [(nt-ref ,id0 ,id1 ,b) id0]) - (Defn ir-out ir-base)) - - (define-pass build-lang-node-counter : Lannotated (ir name) -> * (stx) - (Defn : Defn (ir) -> * (stx) - [(define-language ,id ,[id1] ,id0? ,rtd ,rcd ,tag-mask (,term* ...) ,[procs] ...) - #`(define-pass #,name : #,id (ir) -> * (cnt) - #,@procs - (#,id1 ir))]) - (Nonterminal : Nonterminal (ir) -> * (stx) - [(,id (,id* ...) ,b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,[cl*] ...) - #`(#,id : #,id (ir) -> * (cnt) . #,cl*)]) - (Production : Production (ir) -> * (stx) - [(production ,[pattern] ,pretty-prod? ,rtd ,tag ,pred ,maker ,[recur] ...) - #`[#,pattern (+ 1 . #,recur)]] - [(terminal (term-ref ,id0 ,id1 ,b) ,pretty-prod?) - #`[,#,id0 0]] - [(nonterminal (nt-ref ,id0 ,id1 ,b) ,pretty-prod?) - #`[,#,id0 (#,id1 #,id0)]] - [else (errorf who "unrecognized production ~s" (unparse-Lannotated ir))]) - (Pattern : Pattern (ir) -> * (stx) - [,id id] - [,ref #`,#,(Reference ref)] - [,null #'()] - [(maybe ,[id]) #`,#,id] - [(,[pattern0] ,dots . ,[pattern1]) - #`(#,pattern0 (... ...) . #,pattern1)] - [(,[pattern0] . ,[pattern1]) - #`(#,pattern0 . #,pattern1)]) - (Field : Field (ir) -> * (stx) - (definitions - (define (build-recur recur level) - (let f ([level level]) - (if (fx=? level 0) - recur - #`(lambda (x) - (fold-left - (lambda (c x) (+ c (#,(f (fx- level 1)) x))) - 0 x))))) - (define (Ref ref level optional?) - (nanopass-case (Lannotated Reference) ref - [(term-ref ,id0 ,id1 ,b) #'0] ;; possibly should be 1 at base, with recur to sum - [(nt-ref ,id0 ,id1 ,b) - (let ([recur-base (if optional? #`(lambda (x) (if x (#,id1 x) 0)) id1)]) - #`(#,(build-recur recur-base level) #,id0))]))) - [(,ref ,level ,accessor) (Ref ref level #f)] - [(optional ,ref ,level ,accessor) (Ref ref level #t)] - [else (errorf who "unrecognized field ~s" (unparse-Lannotated ir))]) - (Reference : Reference (ir) -> * (id) - [(term-ref ,id0 ,id1 ,b) id0] - [(nt-ref ,id0 ,id1 ,b) id0]) - (Defn ir)) - - (define-pass build-unparser : Lannotated (ir name) -> * (stx) - (definitions - (define (build-mv-refs pat flds) - (if flds - (map Field flds) - (let-values ([(mv up) (Reference pat)]) (list mv))))) - (Defn : Defn (ir) -> * (stx) - [(define-language ,id ,[mv upname] ,id? ,rtd ,rcd ,tag-mask (,[tup* tpred* tn*] ...) ,[up* pred* n*] ...) - (with-syntax ([(tup* ...) tup*] - [(tpred* ...) tpred*] - [(tn* ...) tn*] - [(up* ...) up*] - [(pred* ...) pred*] - [(n* ...) n*] - [who (datum->syntax name 'who)]) - ;; NOTE: entry is #f when not specified to preserve the current - ;; behavior, but could be specified to be the entry instead. - #`(define #,name - (let () - (define-pass #,name : #,id (lf entry raw?) -> * (sexp) - tup* ... - up* ... - (case entry - [(n*) (n* lf)] ... - [(tn*) (tn* lf)] ... - [else (cond - [(pred* lf) (n* lf)] ... - [(tpred* lf) (tn* lf)] ... - [else (errorf who "Unrecognized input ~s" lf)])])) - (case-lambda - [(lf) (#,name lf #f #f)] - [(lf entry/raw?) - (if (symbol? entry/raw?) - (#,name lf entry/raw? #f) - (#,name lf #f entry/raw?))] - [(lf entry raw?) (#,name lf entry raw?)]))))]) - (Terminal : Terminal (ir) -> * (tup tpred tn) - [(,id (,id* ...) ,b ,handler? ,pred) - (values - (if handler? - #`(#,id : #,id (lf) -> * (sexp) (if raw? lf (#,handler? lf))) - #`(#,id : #,id (lf) -> * (sexp) lf)) - pred - id)]) - (Nonterminal : Nonterminal (ir) -> * (up pred n) - [(,id (,id* ...) ,b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,[cl*] ...) - (values - #`(#,id : #,id (lf) -> * (sexp) . #,cl*) - all-pred - id)]) - (Production : Production (ir) -> * (cl) - (definitions - (define (build-sexp pretty-prod? raw-pattern mv*) - (if pretty-prod? - (PrettyProduction pretty-prod? raw-pattern mv*) - #`(with-extended-quasiquote (quasiquote #,raw-pattern))))) - [(production ,[pattern] ,pretty-prod? ,rtd ,tag ,pred ,maker ,[mv* up*] ...) - (with-syntax ([sexp-builder (build-sexp pretty-prod? pattern mv*)] - [(mv* ...) mv*] - [(up* ...) up*]) - #`[#,pattern (let ([mv* (up* mv*)] ...) sexp-builder)])] - [(terminal ,[ref -> mv upname] ,pretty-prod?) - (with-syntax ([sexp-builder (build-sexp pretty-prod? #`,#,mv (list mv))]) - #`[,#,mv (let ([#,mv (#,upname #,mv)]) sexp-builder)])] - [(nonterminal ,[ref -> mv upname] ,pretty-prod?) - (with-syntax ([sexp-builder (build-sexp pretty-prod? #`,#,mv (list mv))]) - #`[,#,mv (let ([#,mv (#,upname #,mv)]) sexp-builder)])]) - (Pattern : Pattern (ir) -> * (stx) - [,id id] - [,ref (let-values ([(mv up) (Reference ref)]) #`,#,mv)] - [,null #'()] - [(maybe ,[mv up]) #`,#,mv] - [(,[pattern0] ,dots . ,[pattern1]) - #`(#,pattern0 (... ...) . #,pattern1)] - [(,[pattern0] . ,[pattern1]) #`(#,pattern0 . #,pattern1)]) - (PrettyProduction : PrettyProduction (ir raw-pattern mv*) -> * (stx) - [(procedure ,handler) - #`(if raw? - (with-extended-quasiquote (quasiquote #,raw-pattern)) - (#,handler #,name . #,mv*))] - [(pretty ,pattern) - (with-syntax ([pretty-builder (Pattern pattern)]) - #`(if raw? - (with-extended-quasiquote (quasiquote #,raw-pattern)) - (with-extended-quasiquote (quasiquote pretty-builder))))]) - (Field : Field (ir) -> * (mv up) - (definitions - (define (build-unparser-for-level up level) - (let f ([level level]) - (if (fx=? level 0) - up - #`(lambda (x) (map #,(f (fx- level 1)) x)))))) - [(,[mv up] ,level ,accessor) - (values mv (build-unparser-for-level up level))] - [(optional ,[mv up] ,level ,accessor) - (values mv - (build-unparser-for-level - #`(lambda (x) (and x (#,up x))) - level))]) - (Reference : Reference (ir) -> * (mv up) - [(term-ref ,id0 ,id1 ,b) (values id0 id1)] - [(nt-ref ,id0 ,id1 ,b) (values id0 id1)]) - (Defn ir)) - - (define-pass build-parser : Lannotated (ir name) -> * (stx) - (definitions - (define-pass extract-bindings : (Lannotated Pattern) (ir) -> * (id*) - (Pattern : Pattern (ir id*) -> * (id*) - [,id id*] - [,ref (Reference ref id*)] - [(maybe ,[id*]) id*] - [,null id*] - [(,pattern0 . ,[id*]) (Pattern pattern0 id*)] - [(,pattern0 ,dots . ,[id*]) - (Pattern pattern0 id*)]) - (Reference : Reference (ir id*) -> * (id*) - [(term-ref ,id0 ,id1 ,b) (cons id0 id*)] - [(nt-ref ,id0 ,id1 ,b) (cons id0 id*)]) - (Pattern ir '())) - (define (build-body id prod*) - (let f ([prod* prod*]) - (if (null? prod*) - #'fk - (with-syntax ([(fk) (generate-temporaries '(fk))]) - (Production (car prod*) id #'fk - #`(lambda () #,(f (cdr prod*))))))))) - (Defn : Defn (ir) -> * (stx) - [(define-language ,id ,[mv pname pred term?] ,id? ,rtd ,rcd ,tag-mask (,term* ...) ,[p* n*] ...) - (with-syntax ([(p* ...) p*] - [(n* ...) n*] - [who (datum->syntax name 'who)]) - #`(define #,name - (let () - (define-pass #,name : * (sexp entry) -> #,id () - (definitions - (define (squawk) (errorf who "unrecognized syntax ~s" sexp))) - p* ... - (case entry - [(n*) (n* sexp squawk)] ... - [else (errorf who "Unexpected entry name ~s" entry)])) - (case-lambda - [(sexp) (#,name sexp '#,pname)] - [(sexp entry) (#,name sexp entry)]))))]) - (Nonterminal : Nonterminal (ir) -> * (stx n) - [(,id (,id* ...) ,b ,rtd ,rcd ,tag ,pred ,all-pred ,all-term-pred ,prod* ...) - (values #`(#,id : * (sexp fk) -> #,id () #,(build-body id prod*)) id)]) - (Production : Production (ir id fk-id fk) -> * (stx) - [(production ,[pattern -> build-rec] ,pretty-prod? ,rtd ,tag ,pred ,maker ,field* ...) - (with-syntax ([quasiquote (datum->syntax id 'quasiquote)]) - #`(let ([#,fk-id #,fk]) #,(Pattern pattern #'sexp #`(quasiquote #,build-rec) fk-id)))] - [(terminal ,[mv p pred term?] ,pretty-prod?) - #`(let ([#,fk-id #,fk]) (if (#,pred sexp) sexp (#,fk-id)))] - [(nonterminal ,[mv p pred term?] ,pretty-prod?) - #`(let ([#,fk-id #,fk]) (#,p sexp #,fk-id))]) - (Pattern : Pattern (ir sexp-id body fk) -> * (stx) - [,id #`(if (eq? #,sexp-id '#,id) #,body (#,fk))] - [,ref (let-values ([(mv p pred term?) (Reference ref)]) - (if term? - #`(if (#,pred #,sexp-id) - (let ([#,mv #,sexp-id]) #,body) - (#,fk)) - #`(let ([#,mv (#,p #,sexp-id #,fk)]) #,body)))] - [,null #`(if (null? #,sexp-id) #,body (#,fk))] - [(maybe ,[mv p pred term?]) - (if term? - #`(if (or (eq? #,sexp-id #f) - (#,pred #,sexp-id)) - (let ([#,mv #,sexp-id]) #,body) - (#,fk)) - #`(let ([#,mv (and #,sexp-id (#,p #,sexp-id #,fk))]) #,body))] - [(,pattern0 . ,pattern1) - (with-syntax ([(a d) (generate-temporaries '(a d))]) - #`(if (pair? #,sexp-id) - (let ([a (car #,sexp-id)] [d (cdr #,sexp-id)]) - #,(Pattern pattern0 #'a - (Pattern pattern1 #'d body fk) - fk)) - (#,fk)))] - [(,pattern0 ,dots . ,pattern1) - (let ([binding* (extract-bindings pattern0)]) - (with-syntax ([(binding ...) binding*] - [(tbinding ...) (generate-temporaries binding*)] - [(t0 t1 new-k loop) (generate-temporaries '(t0 t1 new-fk loop))]) - #`(let loop ([t0 #,sexp-id] [tbinding '()] ...) - (let ([new-fk (lambda () - (if (pair? t0) - (let ([t1 (car t0)] [t0 (cdr t0)]) - #,(Pattern pattern0 #'t1 - #'(loop t0 (cons binding tbinding) ...) - fk)) - (#,fk)))]) - #,(Pattern pattern1 #'t0 - #`(let ([binding (reverse tbinding)] ...) - #,body) - #'new-fk)))))]) - (BuildPattern : Pattern (ir) -> * (stx) - [,id id] - [,ref (let-values ([(mv up pred term?) (Reference ref)]) #`,#,mv)] - [,null #'()] - [(maybe ,[mv up pred term?]) #`,#,mv] - [(,[pattern0] ,dots . ,[pattern1]) - #`(#,pattern0 (... ...) . #,pattern1)] - [(,[pattern0] . ,[pattern1]) #`(#,pattern0 . #,pattern1)]) - (Reference : Reference (ir) -> * (mv pname pred term?) - [(term-ref ,id0 ,id1 ,b) - (values id0 id1 - (nanopass-case (Lannotated Terminal) (unbox b) - [(,id (,id* ...) ,b ,handler? ,pred) pred]) - #t)] - [(nt-ref ,id0 ,id1 ,b) (values id0 id1 #f #f)]) - (Defn ir)) - - (define (star? x) - (or (eq? x '*) - (eq? (syntax->datum x) '*))) - - (define (modifier? x) - (memq (syntax->datum x) '(echo trace))) - - (define (definitions? x) - (or (eq? x 'definitions) - (eq? (syntax->datum x) 'defintions))) - - (define (options? x) - (or (eq? x 'options) - (eq? (syntax->datum x) 'options))) - - (define-language Lpass-src - (terminals - (identifier (id)) - (colon (:)) - (arrow (->)) - (star (*)) - (definitions (definitions)) - (options (options)) - (syntax (stx)) - (modifier (modifier)) - (null (null)) - (dots (dots)) - (unquote (unquote)) - (boolean (b))) - (Program (prog) - (define-pass id : lname0 (id* ...) -> lname1 (out* ...) - (options opt* ...) - (definitions stx* ...) - proc* ... - (maybe stx))) - (LanguageName (lname) - * - id - (id0 id1)) - (Processor (proc) - (id : id0 (in* ...) -> id1 (out* ...) - (options opt* ...) - (definitions stx* ...) - cl* ...)) - (InputArgument (in) - id - [id stx]) - (OutputExpression (out) - id - stx) - (Clause (cl) - [pattern stx* ... stx]) - (Pattern (pattern) - id - (binding hole) - (pattern0 dots . pattern1) - (pattern0 . pattern1) - null) - (Hole (hole) - id - cata) - (Catamorphism (cata) - (stx : . cata-remainder) - cata-remainder) - (CatamorphismRemainder (cata-remainder) - (stx* ... -> . cata-out) - cata-out) - (CatamorphismOutputVariables (cata-out) - (id* ...)) - (Option (opt) - (trace b) - (echo b) - (generate-transformers b))) - - (define-pass parse-pass : * (stx who) -> Lpass-src () - (definitions - (define (has-language? lang) - (nanopass-case (Lpass-src LanguageName) lang - [,* #f] - [else #t]))) - (Program : * (stx) -> Program () - (syntax-case stx () - [(_ pass-name ?colon iname (fml ...) ?arrow oname (xval ...) . rest) - (let ([squawk (lambda (msg what) (syntax-violation who msg stx what))]) - (unless (identifier? #'pass-name) (squawk "invalid pass name" #'pass-name)) - (unless (eq? (datum ?colon) ':) (squawk "expected colon" #'?colon)) - (let ([ilang (LanguageName #'iname squawk)] [fml* #'(fml ...)]) - (unless (for-all identifier? #'(fml ...)) (squawk "expected list of identifiers" fml*)) - (when (and (has-language? ilang) (null? fml*)) (squawk "expected non-empty list of formals" fml*)) - (unless (eq? (datum ?arrow) '->) (squawk "expected arrow" #'?arrow)) - (let ([olang (LanguageName #'oname squawk)]) - (define (looks-like-processor? x) - (let loop ([x x] [mcount 0]) - (syntax-case x () - [(pname ?colon itype (fml ...) ?arrow otype (xval ...) . more) - (and (eq? (datum ?colon) ':) - (eq? (datum ?arrow) '->) - (identifier? #'itype) - (identifier? #'otype) - (for-all (lambda (fml) - (or (identifier? fml) - (syntax-case fml () - [[fml exp-value] (identifier? #'fml)]))) - #'(fml ...))) - #t] - [(?modifier ?not-colon . more) - (and (memq (datum ?modifier) '(trace echo)) - (not (eq? (datum ?not-colon) ':)) - (< mcount 2)) - (loop #'(?not-colon . more) (fx+ mcount 1))] - [_ #f]))) - (define (s0 rest defn* pass-options) - (syntax-case rest () - [((definitions defn* ...) . rest) - (eq? (datum definitions) 'definitions) - (s0 #'rest #'(defn* ...) pass-options)] - [((pass-options options ...) . rest) - (eq? (datum pass-options) 'pass-options) - (s0 #'rest defn* (map Option #'(options ...)))] - [_ (s1 rest defn* pass-options '())])) - (define (s1 rest defn* pass-options processor*) - (syntax-case rest () - [(a . rest) - (looks-like-processor? #'a) - (s1 #'rest defn* pass-options (cons (Processor #'a squawk) processor*))] - [_ (s2 rest defn* pass-options processor*)])) - (define (s2 rest defn* pass-options processor*) - `(define-pass ,#'pass-name ,#'?colon ,ilang (,fml* ...) ,#'?arrow ,olang (,#'(xval ...) ...) - (options ,(or pass-options '()) ...) - (definitions ,defn* ...) - ,processor* ... - ,(syntax-case rest () - [() #f] - [oth #`(begin . oth)]))) - (s0 #'rest '() #f))))])) - (LanguageName : * (stx squawk) -> LanguageName () - (syntax-case stx () - [* (eq? (datum #'*) '*) #'*] - [id (identifier? #'id) #'id] - [(id0 id1) - (and (identifier? #'id0) (identifier? #'id1)) - `(,#'id0 ,#'id1)] - [_ (squawk "invalid language specifier" stx)])) - (Option : * (stx squawk) -> Option () - (syntax-case stx () - [trace (eq? (datum #'trace) 'trace) `(trace #t)] - [echo (eq? (datum #'echo) 'echo) `(echo #t)] - [generate-transformers (eq? (datum #'generate-transforms) 'generate-transforms) `(generate-transformers #t)] - [_ (squawk "unexpected option" stx)])) - (Processor : * (stx squawk) -> Processor () - (let s0 ([stx stx] [modifier* '()]) - (syntax-case stx () - [(pname ?colon itype (fml ...) ?arrow otype (xval ...) . more) - (and (eq? (datum ?colon) ':) - (eq? (datum ?arrow) '->) - (identifier? #'itype) - (identifier? #'otype) - (for-all (lambda (fml) - (or (identifier? fml) - (syntax-case fml () - [[fml exp-value] (identifier? #'fml)]))) - #'(fml ...))) - (syntax-case #'more () - [((definitions defn ...) cl ...) - (eq? (datum definitions) 'definitions) - (let ([cl* (map Clause #'(cl ...))] - [in* (map InputArgument #'(fml ...))]) - `(,#'id ,#'?colon ,#'itype (,in* ...) ,#'?arrow ,#'otype (,#'(xval ...) ...) - (options ,modifier* ...) - (definitions ,#'(defn ...) ...) - ,cl* ...))] - [(cl ...) - (let ([cl* (map Clause #'(cl ...))] - [in* (map InputArgument #'(fml ...))]) - `(,#'id ,#'?colon ,#'itype (,in* ...) ,#'?arrow ,#'otype (,#'(xval ...) ...) - (options ,modifier* ...) - (definitions) - ,cl* ...))])] - [(?modifier ?not-colon . more) - (s0 #'(?not-colon . more) (cons (Option #'?modifier squawk) modifier*))]))) - (InputArgument : * (stx) -> InputArgument () - (syntax-case stx () - [id (identifier? #'id) #'id] - [[id stx] (identifier? #'id) `(,#'id ,#'stx)])) - (Clause : * (stx) -> Clause () - (syntax-case stx () - [(pattern stx* ... stx) - (let ([pattern (Pattern #'pattern)]) - `(,pattern ,#'(stx* ...) ... ,#'stx))])) - (Pattern : * (stx) -> Pattern () - (syntax-case stx () - [id (identifier? #'id) #'id] - [(unq hole) (eq? (datum unq) 'unquote) `(binding ,(Hole #'hole))] - [(pattern0 dots . pattern1) - (eq? (datum dots) '...) - `(,(Pattern #'pattern0) ,#'dots . ,(Pattern #'pattern1))] - [(pattern0 . pattern1) `(,(Pattern #'pattern0) . ,(Pattern #'pattern1))] - [null '()])) - (Hole : * (stx) -> Hole () - (syntax-case stx () - [id (identifier? #'id) #'id] - [_ (Catamorphism stx)])) - (Catamorphism : * (stx) -> Catamorphism () - (let () - (define (s0 stx) - (syntax-case stx () - [(: . stx) (colon? #':) (s2 #f #'stx)] - [(-> . stx) (arrow? #'->) (s4 #f #f '() #'stx)] - [(e . stx) (s1 #'e #'stx)] - [() (in-context CatamorphismOutputVariables `(,'() ...))])) - (define (s1 e stx) - (syntax-case stx () - [(: . stx) (colon? #':) (s2 e #'stx)] - [(-> . stx) - (and (arrow? #'->) (identifier? e)) - (s4 #f (list e) '() #'stx)] - [(expr . stx) - (identifier? e) - (s3 #f (list #'expr e) #'stx)] - [() (identifier? e) (in-context CatamorphismOutputVariables `(,e))])) - (define (s2 f stx) - (syntax-case stx () - [(-> . stx) - (arrow? #'->) - (s4 f #f '() #'stx)] - [(id . stx) - (identifier? #'id) - (s3 f (list #'id) #'stx)])) - (define (s3 f e* stx) - (syntax-case stx () - [(-> . stx) - (arrow? #'->) - (s4 f (reverse e*) '() #'stx)] - [(e . stx) - (s3 f (cons #'e e*) #'stx)] - [() - (for-all identifier? e*) - `(,f : -> ,e* ...)])) - (define (s4 f maybe-inid* routid* stx) - (syntax-case stx () - [(id . stx) - (identifier? #'id) - (s4 f maybe-inid* (cons #'id routid*) #'stx)] - [() `(,f : ,(or maybe-inid* '()) ... -> ,(reverse routid*) ...)])) - (s0 stx))) - (Program stx)) - - (define-language Lpass - (extends Lpass-src) - (terminals - (+ (Lannotated (np-lang)))) - (Program (prog) - (- (define-pass id : lname0 (id* ...) -> lname1 (out* ...) - (options opt* ...) - (definitions stx* ...) - proc* ... - (maybe stx))) - (+ (define-pass id : lang0 (id* ...) -> lang1 (stx0* ...) - (options opt* ...) - (definitions stx1* ...) - proc* ... - stx))) - (LanguageName (lname) - (- * - id - (id0 id1))) - (Language (lang) - (+ (none) - np-lang - (np-lang id))) - (Clause (cl) - (- (pattern stx* ... stx)) - (+ (pattern stx))) - (Catamorphism (cata) - (- (stx : . cata-remainder) - cata-remainder) - (+ (stx : (stx* ...) -> id* ...))) - (CatamorphismRemainder (cata-remainder) - (- (stx* ... -> . cata-out) - cata-out)) - (CatamorphismOutputVariables (cata-out) - (- (id* ...)))) - - (define lookup-language - (lambda (rho name) - (let ([lang (rho name #'experimental-language)]) - (unless (language-information? lang) - (errorf 'with-language "unable to find language information for ~s" (syntax->datum name))) - lang))) - ) diff --git a/ta6ob/nanopass/nanopass/helpers.ss b/ta6ob/nanopass/nanopass/helpers.ss deleted file mode 100644 index 0bcd10e..0000000 --- a/ta6ob/nanopass/nanopass/helpers.ss +++ /dev/null @@ -1,453 +0,0 @@ -;;; Copyright (c) 2000-2018 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (nanopass helpers) - (export - ;; auxiliary keywords for language/pass definitions - extends definitions entry terminals nongenerative-id maybe - - ;; predicates for looking for identifiers independent of context - ellipsis? unquote? colon? arrow? plus? minus? double-arrow? - - ;; things for dealing with syntax and idetnfieris - all-unique-identifiers? construct-id construct-unique-id gentemp - bound-id-member? bound-id-union partition-syn datum - - ;; things for dealing with language meta-variables - meta-var->raw-meta-var combine unique-name - - ;; convenience syntactic forms - rec with-values define-who trace-define-who - - ;; source information funtions - syntax->source-info - - ;;; stuff imported from implementation-helpers - - ;; formatting - format printf pretty-print - - ;; listy stuff - iota make-list list-head - - ;; gensym stuff (related to nongenerative languages) - gensym regensym - - ;; library export stuff (needed for when used inside module to - ;; auto-indirect export things) - indirect-export - - ;; compile-time environment helpers - define-property make-compile-time-value - - ;; code organization helpers - module - - ;; useful for warning items - warningf errorf - - ;; used to get the best performance from hashtables - eq-hashtable-set! eq-hashtable-ref - - ;; debugging support - trace-lambda trace-define-syntax trace-let trace-define - - ;; needed to know what code to generate - optimize-level - - ;; the base record, so that we can use gensym syntax - define-nanopass-record - - ;; handy syntactic stuff - with-implicit with-r6rs-quasiquote with-extended-quasiquote - extended-quasiquote with-auto-unquote - - ;; abstraction of the grabbing the syntactic environment that will work in - ;; Chez, Ikarus, & Vicare - with-compile-time-environment - - ;; expose the source information stuff - syntax->source-information - source-information-source-file - source-information-byte-offset-start - source-information-char-offset-start - source-information-byte-offset-end - source-information-char-offset-end - source-information-position-line - source-information-position-column - source-information-type - provide-full-source-information) - (import (rnrs) (nanopass implementation-helpers)) - - (define-syntax datum - (syntax-rules () - [(_ e) (syntax->datum #'e)])) - - (define-syntax with-r6rs-quasiquote - (lambda (x) - (syntax-case x () - [(k . body) - #`(let-syntax ([#,(datum->syntax #'k 'quasiquote) (syntax-rules () [(_ x) `x])]) - . body)]))) - - (define-syntax extended-quasiquote - (lambda (x) - (define gather-unquoted-exprs - (lambda (body) - (let f ([body body] [t* '()] [e* '()]) - (syntax-case body (unquote unquote-splicing) - [(unquote x) - (identifier? #'x) - (if (memp (lambda (t) (bound-identifier=? t #'x)) t*) - (values body t* e*) - (values body (cons #'x t*) (cons #'x e*)))] - [(unquote-splicing x) - (identifier? #'x) - (if (memp (lambda (t) (bound-identifier=? t #'x)) t*) - (values body t* e*) - (values body (cons #'x t*) (cons #'x e*)))] - [(unquote e) - (with-syntax ([(t) (generate-temporaries '(t))]) - (values #'(unquote t) (cons #'t t*) (cons #'e e*)))] - [(unquote-splicing e) - (with-syntax ([(t) (generate-temporaries '(t))]) - (values #'(unquote-splicing t) (cons #'t t*) (cons #'e e*)))] - [(tmpl0 . tmpl1) - (let-values ([(tmpl0 t* e*) (f #'tmpl0 t* e*)]) - (let-values ([(tmpl1 t* e*) (f #'tmpl1 t* e*)]) - (values #`(#,tmpl0 . #,tmpl1) t* e*)))] - [atom (values #'atom t* e*)])))) - (define build-list - (lambda (body orig-level) - (let loop ([body body] [level orig-level]) - (syntax-case body (unquote unquote-splicing) - [(tmpl0 ... (unquote e)) - (with-syntax ([(tmpl0 ...) (rebuild-body #'(tmpl0 ...) (fx- orig-level 1))]) - (cond - [(fx=? level 0) #'(tmpl0 ... (unquote e))] - [(fx=? level 1) #'(tmpl0 ... (unquote-splicing e))] - [else (let loop ([level level] [e #'e]) - (if (fx=? level 1) - #`(tmpl0 ... (unquote-splicing #,e)) - (loop (fx- level 1) #`(apply append #,e))))]))] - [(tmpl0 ... (unquote-splicing e)) - (with-syntax ([(tmpl0 ...) (rebuild-body #'(tmpl0 ...) (fx- orig-level 1))]) - (cond - [(fx=? level 0) #'(tmpl0 ... (unquote-splicing e))] - [else (let loop ([level level] [e #'e]) - (if (fx=? level 0) - #`(tmpl0 ... (unquote-splicing #,e)) - (loop (fx- level 1) #`(apply append #,e))))]))] - [(tmpl0 ... tmpl1 ellipsis) - (eq? (datum ellipsis) '...) - (loop #'(tmpl0 ... tmpl1) (fx+ level 1))] - [(tmpl0 ... tmpl1) - (with-syntax ([(tmpl0 ...) (rebuild-body #'(tmpl0 ...) (fx- orig-level 1))]) - (let-values ([(tmpl1 t* e*) (gather-unquoted-exprs #'tmpl1)]) - (when (null? e*) - (syntax-violation 'extended-quasiquote - "no variables found in ellipsis expression" body)) - (let loop ([level level] - [e #`(map (lambda #,t* - (extended-quasiquote - #,tmpl1)) - . #,e*)]) - (if (fx=? level 1) - #`(tmpl0 ... (unquote-splicing #,e)) - (loop (fx- level 1) #`(apply append #,e))))))])))) - (define rebuild-body - (lambda (body level) - (syntax-case body (unquote unquote-splicing) - [(unquote e) #'(unquote e)] - [(unquote-splicing e) #'(unquote-splicing e)] - [(tmpl0 ... tmpl1 ellipsis) - (eq? (datum ellipsis) '...) - (with-syntax ([(tmpl0 ...) (build-list #'(tmpl0 ... tmpl1) (fx+ level 1))]) - #'(tmpl0 ...))] - [(tmpl0 ... tmpl1 ellipsis . tmpl2) - (eq? (datum ellipsis) '...) - (with-syntax ([(tmpl0 ...) (build-list #'(tmpl0 ... tmpl1) (fx+ level 1))] - [tmpl2 (rebuild-body #'tmpl2 level)]) - #'(tmpl0 ... . tmpl2))] - [(tmpl0 ... tmpl1) - (with-syntax ([(tmpl0 ...) (rebuild-body #'(tmpl0 ...) level)] - [tmpl1 (rebuild-body #'tmpl1 level)]) - #'(tmpl0 ... tmpl1))] - [(tmpl0 ... tmpl1 . tmpl2) - (with-syntax ([(tmpl0 ...) (rebuild-body #'(tmpl0 ... tmpl1) level)] - [tmpl2 (rebuild-body #'tmpl2 level)]) - #'(tmpl0 ... . tmpl2))] - [other #'other]))) - (syntax-case x () - [(k body) - (with-syntax ([body (rebuild-body #'body 0)]) - #'(quasiquote body))]))) - - (define-syntax with-extended-quasiquote - (lambda (x) - (syntax-case x () - [(k . body) - (with-implicit (k quasiquote) - #'(let-syntax ([quasiquote (syntax-rules () - [(_ x) (extended-quasiquote x)])]) - - . body))]))) - - (define-syntax with-auto-unquote - (lambda (x) - (syntax-case x () - [(k (x* ...) . body) - (with-implicit (k quasiquote) - #'(let-syntax ([quasiquote - (lambda (x) - (define replace-vars - (let ([vars (list #'x* ...)]) - (lambda (b) - (let f ([b b]) - (syntax-case b () - [id (identifier? #'id) - (if (memp (lambda (var) (free-identifier=? var #'id)) vars) - #'(unquote id) - #'id)] - [(a . d) (with-syntax ([a (f #'a)] [d (f #'d)]) #'(a . d))] - [atom #'atom]))))) - (syntax-case x () - [(_ b) - (with-syntax ([b (replace-vars #'b)]) - #'`b)]))]) - . body))]))) - - (define all-unique-identifiers? - (lambda (ls) - (and (for-all identifier? ls) - (let f ([ls ls]) - (if (null? ls) - #t - (let ([id (car ls)] [ls (cdr ls)]) - (and (not (memp (lambda (x) (free-identifier=? x id)) ls)) - (f ls)))))))) - - (define-syntax with-values - (syntax-rules () - [(_ p c) (call-with-values (lambda () p) c)])) - - (define-syntax rec - (syntax-rules () - [(_ name proc) (letrec ([name proc]) name)] - [(_ (name . arg) body body* ...) - (letrec ([name (lambda arg body body* ...)]) name)])) - - (define-syntax define-auxiliary-keyword - (syntax-rules () - [(_ name) - (define-syntax name - (lambda (x) - (syntax-violation 'name "misplaced use of auxiliary keyword" x)))])) - - (define-syntax define-auxiliary-keywords - (syntax-rules () - [(_ name* ...) - (begin (define-auxiliary-keyword name*) ...)])) - - (define-auxiliary-keywords extends definitions entry terminals nongenerative-id maybe) - - (define-syntax define-who - (lambda (x) - (syntax-case x () - [(k name expr) - (with-implicit (k who) - #'(define name (let () (define who 'name) expr)))] - [(k (name . fmls) expr exprs ...) - #'(define-who name (lambda (fmls) expr exprs ...))]))) - - (define-syntax trace-define-who - (lambda (x) - (syntax-case x () - [(k name expr) - (with-implicit (k who) - #'(trace-define name (let () (define who 'name) expr)))] - [(k (name . fmls) expr exprs ...) - #'(trace-define-who name (lambda (fmls) expr exprs ...))]))) - - ;;; moved from meta-syntax-dispatch.ss and nano-syntax-dispatch.ss - (define combine - (lambda (r* r) - (if (null? (car r*)) - r - (cons (map car r*) (combine (map cdr r*) r))))) - - ;;; moved from meta-syntax-dispatch.ss and syntaxconvert.ss - (define ellipsis? - (lambda (x) - (and (identifier? x) (free-identifier=? x (syntax (... ...)))))) - - (define unquote? - (lambda (x) - (and (identifier? x) (free-identifier=? x (syntax unquote))))) - - (define unquote-splicing? - (lambda (x) - (and (identifier? x) (free-identifier=? x (syntax unquote-splicing))))) - - (define plus? - (lambda (x) - (and (identifier? x) - (or (free-identifier=? x #'+) - (eq? (syntax->datum x) '+))))) - - (define minus? - (lambda (x) - (and (identifier? x) - (or (free-identifier=? x #'-) - (eq? (syntax->datum x) '-))))) - - (define double-arrow? - (lambda (x) - (and (identifier? x) - (or (free-identifier=? x #'=>) - (eq? (syntax->datum x) '=>))))) - - (define colon? - (lambda (x) - (and (identifier? x) - (or (free-identifier=? x #':) - (eq? (syntax->datum x) ':))))) - - (define arrow? - (lambda (x) - (and (identifier? x) - (or (free-identifier=? x #'->) - (eq? (syntax->datum x) '->))))) - - ;;; unique-name produces a unique name derived the input name by - ;;; adding a unique suffix of the form .+. creating a unique - ;;; name from a unique name has the effect of replacing the old - ;;; unique suffix with a new one. - - (define unique-suffix - (let ((count 0)) - (lambda () - (set! count (+ count 1)) - (number->string count)))) - - (define unique-name - (lambda (id . id*) - (string-append - (fold-right - (lambda (id str) (string-append str ":" (symbol->string (syntax->datum id)))) - (symbol->string (syntax->datum id)) id*) - "." - (unique-suffix)))) - - ; TODO: at some point we may want this to be a little bit more - ; sophisticated, or we may want to have something like a regular - ; expression style engine where we bail as soon as we can identify - ; what the meta-var corresponds to. - (define meta-var->raw-meta-var - (lambda (sym) - (let ([s (symbol->string sym)]) - (let f ([i (fx- (string-length s) 1)]) - (cond - [(fx=? i -1) sym] - [(or (char=? #\* (string-ref s i)) - (char=? #\^ (string-ref s i)) - (char=? #\? (string-ref s i))) - (f (fx- i 1))] - [else (let f ([i i]) - (cond - [(fx=? i -1) sym] - [(char-numeric? (string-ref s i)) (f (fx- i 1))] - [else (string->symbol (substring s 0 (fx+ i 1)))]))]))))) - - (define build-id - (lambda (who x x*) - (define ->str - (lambda (x) - (cond - [(string? x) x] - [(identifier? x) (symbol->string (syntax->datum x))] - [(symbol? x) (symbol->string x)] - [else (error who "invalid input ~s" x)]))) - (apply string-append (->str x) (map ->str x*)))) - - (define $construct-id - (lambda (who str->sym tid x x*) - (unless (identifier? tid) - (error who "template argument ~s is not an identifier" tid)) - (datum->syntax tid (str->sym (build-id who x x*))))) - - (define-who construct-id - (lambda (tid x . x*) - ($construct-id who string->symbol tid x x*))) - - (define-who construct-unique-id - (lambda (tid x . x*) - ($construct-id who gensym tid x x*))) - - (define-syntax partition-syn - (lambda (x) - (syntax-case x () - [(_ ls-expr () e0 e1 ...) #'(begin ls-expr e0 e1 ...)] - [(_ ls-expr ([set pred] ...) e0 e1 ...) - (with-syntax ([(pred ...) - (let f ([preds #'(pred ...)]) - (if (null? (cdr preds)) - (if (free-identifier=? (car preds) #'otherwise) - (list #'(lambda (x) #t)) - preds) - (cons (car preds) (f (cdr preds)))))]) - #'(let-values ([(set ...) - (let f ([ls ls-expr]) - (if (null? ls) - (let ([set '()] ...) (values set ...)) - (let-values ([(set ...) (f (cdr ls))]) - (cond - [(pred (car ls)) - (let ([set (cons (car ls) set)]) - (values set ...))] - ... - [else (error 'partition-syn - "no home for ~s" - (car ls))]))))]) - e0 e1 ...))]))) - - (define gentemp - (lambda () - (car (generate-temporaries '(#'t))))) - - (define bound-id-member? - (lambda (id id*) - (and (not (null? id*)) - (or (bound-identifier=? id (car id*)) - (bound-id-member? id (cdr id*)))))) - - (define bound-id-union ; seems to be unneeded - (lambda (ls1 ls2) - (cond - [(null? ls1) ls2] - [(bound-id-member? (car ls1) ls2) (bound-id-union (cdr ls1) ls2)] - [else (cons (car ls1) (bound-id-union (cdr ls1) ls2))]))) - - (define syntax->source-info - (lambda (stx) - (let ([si (syntax->source-information stx)]) - (and si - (cond - [(and (source-information-position-line si) - (source-information-position-column si)) - (format "~s line ~s, char ~s of ~a" - (source-information-type si) - (source-information-position-line si) - (source-information-position-column si) - (source-information-source-file si))] - [(source-information-byte-offset-start si) - (format "~s byte position ~s of ~a" - (source-information-type si) - (source-information-byte-offset-start si) - (source-information-source-file si))] - [(source-information-char-offset-start si) - (format "~s character position ~s of ~a" - (source-information-type si) - (source-information-char-offset-start si) - (source-information-source-file si))] - [else (format "in ~a" (source-information-source-file si))])))))) diff --git a/ta6ob/nanopass/nanopass/implementation-helpers.chezscheme.sls b/ta6ob/nanopass/nanopass/implementation-helpers.chezscheme.sls deleted file mode 100644 index 259d031..0000000 --- a/ta6ob/nanopass/nanopass/implementation-helpers.chezscheme.sls +++ /dev/null @@ -1,203 +0,0 @@ -;;; Copyright (c) 2000-2018 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details -#!chezscheme -(library (nanopass implementation-helpers) - (export - ;; formatting - format printf pretty-print - - ;; listy stuff - iota make-list list-head - - ;; gensym stuff (related to nongenerative languages) - gensym regensym - - ;; source-information stuff - syntax->source-information - source-information-source-file - source-information-byte-offset-start - source-information-char-offset-start - source-information-byte-offset-end - source-information-char-offset-end - source-information-position-line - source-information-position-column - source-information-type - provide-full-source-information - - ;; library export stuff (needed for when used inside module to - ;; auto-indirect export things) - indirect-export - - ;; compile-time environment helpers - define-property make-compile-time-value - - ;; code organization helpers - module - - ;; useful for warning items - warningf errorf - - ;; used to get the best performance from hashtables - eq-hashtable-set! eq-hashtable-ref - - ;; debugging support - trace-lambda trace-define-syntax trace-let trace-define - - ;; needed to know what code to generate - optimize-level - - ;; the base record, so that we can use gensym syntax - define-nanopass-record - - ;; handy syntactic stuff - with-implicit - - ;; abstraction of the grabbing the syntactic environment that will work in - ;; Chez, Ikarus, & Vicare - with-compile-time-environment - - ;; apparently not neeaded (or no longer needed) - ; scheme-version= scheme-version< scheme-version> scheme-version>= - ; scheme-version<= with-scheme-version gensym? errorf with-output-to-string - ; with-input-from-string - ) - (import (chezscheme)) - - ; the base language - (define-syntax define-nanopass-record - (lambda (x) - (syntax-case x () - [(k) (with-implicit (k nanopass-record nanopass-record? nanopass-record-tag) - #'(define-record-type (nanopass-record make-nanopass-record nanopass-record?) - (nongenerative #{nanopass-record d47f8omgluol6otrw1yvu5-0}) - (fields (immutable tag nanopass-record-tag))))]))) - - ;; the following should get moved into Chez Scheme proper (and generally - ;; cleaned up with appropriate new Chez Scheme primitives for support) - (define regensym - (case-lambda - [(gs extra) - (unless (gensym? gs) (errorf 'regensym "~s is not a gensym" gs)) - (unless (string? extra) (errorf 'regensym "~s is not a string" extra)) - (let ([pretty-name (parameterize ([print-gensym #f]) (format "~s" gs))] - [unique-name (gensym->unique-string gs)]) - (with-input-from-string (format "#{~a ~a~a}" pretty-name unique-name extra) read))] - [(gs extra0 extra1) - (unless (gensym? gs) (errorf 'regensym "~s is not a gensym" gs)) - (unless (string? extra0) (errorf 'regensym "~s is not a string" extra0)) - (unless (string? extra1) (errorf 'regensym "~s is not a string" extra1)) - (with-output-to-string (lambda () (format "~s" gs))) - (let ([pretty-name (parameterize ([print-gensym #f]) (format "~s" gs))] - [unique-name (gensym->unique-string gs)]) - (with-input-from-string (format "#{~a~a ~a~a}" pretty-name extra0 unique-name extra1) read))])) - - (define-syntax define-scheme-version-relop - (lambda (x) - (syntax-case x () - [(_ name relop strict-inequality?) - #`(define name - (lambda (ls) - (let-values ([(a1 b1 c1) (scheme-version-number)] - [(a2 b2 c2) - (cond - [(fx= (length ls) 1) (values (car ls) 0 0)] - [(fx= (length ls) 2) (values (car ls) (cadr ls) 0)] - [(fx= (length ls) 3) (values (car ls) (cadr ls) (caddr ls))])]) - #,(if (datum strict-inequality?) - #'(or (relop a1 a2) - (and (fx= a1 a2) - (or (relop b1 b2) - (and (fx= b1 b2) - (relop c1 c2))))) - #'(and (relop a1 a2) (relop b1 b2) (relop c1 c2))))))]))) - - (define-scheme-version-relop scheme-version= fx= #f) - (define-scheme-version-relop scheme-version< fx< #t) - (define-scheme-version-relop scheme-version> fx> #t) - (define-scheme-version-relop scheme-version<= fx<= #f) - (define-scheme-version-relop scheme-version>= fx>= #f) - - (define-syntax with-scheme-version - (lambda (x) - (define-scheme-version-relop scheme-version= fx= #f) - (define-scheme-version-relop scheme-version< fx< #t) - (define-scheme-version-relop scheme-version> fx> #t) - (define-scheme-version-relop scheme-version<= fx<= #f) - (define-scheme-version-relop scheme-version>= fx>= #f) - (define finish - (lambda (pat* e** elsee*) - (if (null? pat*) - #`(begin #,@elsee*) - (or (and (syntax-case (car pat*) (< <= = >= >) - [(< v ...) (scheme-version< (datum (v ...)))] - [(<= v ...) (scheme-version<= (datum (v ...)))] - [(= v ...) (scheme-version= (datum (v ...)))] - [(>= v ...) (scheme-version>= (datum (v ...)))] - [(> v ...) (scheme-version> (datum (v ...)))] - [else #f]) - #`(begin #,@(car e**))) - (finish (cdr pat*) (cdr e**) elsee*))))) - (syntax-case x (else) - [(_ [pat e1 e2 ...] ... [else ee1 ee2 ...]) - (finish #'(pat ...) #'((e1 e2 ...) ...) #'(ee1 ee2 ...))] - [(_ [pat e1 e2 ...] ...) - (finish #'(pat ...) #'((e1 e2 ...) ...) #'())]))) - - (define provide-full-source-information - (make-parameter #t (lambda (n) (and n #t)))) - - (define-record-type source-information - (nongenerative) - (sealed #t) - (fields source-file byte-offset-start char-offset-start byte-offset-end - char-offset-end position-line position-column type) - (protocol - (lambda (new) - (lambda (a type) - (let ([so (annotation-source a)]) - (let ([sfd (source-object-sfd so)] - [bfp (source-object-bfp so)] - [efp (source-object-efp so)]) - (if (provide-full-source-information) - (let ([ip (open-source-file sfd)]) - (let loop ([n bfp] [line 1] [col 1]) - (if (= n 0) - (let ([byte-offset-start (port-position ip)]) - (let loop ([n (- efp bfp)]) - (if (= n 0) - (let ([byte-offset-end (port-position ip)]) - (close-input-port ip) - (new (source-file-descriptor-path sfd) - byte-offset-start bfp - byte-offset-end efp - line col type)) - (let ([c (read-char ip)]) (loop (- n 1)))))) - (let ([c (read-char ip)]) - (if (char=? c #\newline) - (loop (- n 1) (fx+ line 1) 1) - (loop (- n 1) line (fx+ col 1))))))) - (new (source-file-descriptor-path sfd) - #f bfp #f efp #f #f type)))))))) - - (define syntax->source-information - (lambda (stx) - (let loop ([stx stx] [type 'at]) - (cond - [(syntax->annotation stx) => - (lambda (a) (make-source-information a type))] - [(pair? stx) (or (loop (car stx) 'near) (loop (cdr stx) 'near))] - [else #f])))) - - (define-syntax with-compile-time-environment - (syntax-rules () - [(_ (arg) body* ... body) (lambda (arg) body* ... body)])) - - (with-scheme-version - [(< 8 3 1) - (define syntax->annotation (lambda (x) #f)) - (define annotation-source (lambda (x) (errorf 'annotation-source "unsupported before version 8.4"))) - (define source-object-bfp (lambda (x) (errorf 'source-object-bfp "unsupported before version 8.4"))) - (define source-object-sfd (lambda (x) (errorf 'source-object-sfd "unsupported before version 8.4"))) - (define source-file-descriptor-path (lambda (x) (errorf 'source-file-descriptor-path "unsupported before version 8.4")))]) - (with-scheme-version - [(< 8 1) (define-syntax indirect-export (syntax-rules () [(_ id indirect-id ...) (define t (if #f #f))]))])) diff --git a/ta6ob/nanopass/nanopass/implementation-helpers.ikarus.ss b/ta6ob/nanopass/nanopass/implementation-helpers.ikarus.ss deleted file mode 100644 index 385c1cd..0000000 --- a/ta6ob/nanopass/nanopass/implementation-helpers.ikarus.ss +++ /dev/null @@ -1,185 +0,0 @@ -;;; Copyright (c) 2000-2018 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (nanopass implementation-helpers) - (export - ;; formatting - format printf pretty-print - - ;; listy stuff - iota make-list list-head - - ;; gensym stuff (related to nongenerative languages) - gensym regensym - - ;; source-information stuff - syntax->source-information - source-information-source-file - source-information-byte-offset-start - source-information-char-offset-start - source-information-byte-offset-end - source-information-char-offset-end - source-information-position-line - source-information-position-column - source-information-type - provide-full-source-information - - ;; library export stuff (needed for when used inside module to - ;; auto-indirect export things) - indirect-export - - ;; compile-time environment helpers - define-property make-compile-time-value - - ;; code organization helpers - module - - ;; useful for warning and error items - warningf errorf - - ;; used to get the best performance from hashtables - eq-hashtable-set! eq-hashtable-ref - - ;; debugging support - trace-lambda trace-define-syntax trace-let trace-define - - ;; needed to know what code to generate - optimize-level - - ;; the base record, so that we can use gensym syntax - define-nanopass-record - - ;; handy syntactic stuff - with-implicit - - ;; abstraction of the grabbing the syntactic environment that will work in - ;; Chez, Ikarus, & Vicare - with-compile-time-environment - - ;; apparently not neeaded (or no longer needed) - ; scheme-version= scheme-version< scheme-version> scheme-version>= - ; scheme-version<= with-scheme-version gensym? errorf with-output-to-string - ; with-input-from-string - ) - (import (rnrs) (rnrs eval) (ikarus) (nanopass syntactic-property)) - - (define-syntax with-implicit - (syntax-rules () - [(_ (id name ...) body bodies ...) - (with-syntax ([name (datum->syntax #'id 'name)] ...) body bodies ...)])) - - ; the base language - (define-syntax define-nanopass-record - (lambda (x) - (syntax-case x () - [(k) (with-implicit (k nanopass-record nanopass-record? nanopass-record-tag) - #'(define-record-type (nanopass-record make-nanopass-record nanopass-record?) - (nongenerative #{nanopass-record d47f8omgluol6otrw1yvu5-0}) - (fields (immutable tag nanopass-record-tag))))]))) - - (define-syntax eq-hashtable-set! (identifier-syntax hashtable-set!)) - (define-syntax eq-hashtable-ref (identifier-syntax hashtable-ref)) - - (define list-head - (lambda (orig-ls orig-n) - (let f ([ls orig-ls] [n orig-n]) - (cond - [(fxzero? n) '()] - [(null? ls) (error 'list-head "index out of range" orig-ls orig-n)] - [else (cons (car ls) (f (cdr ls) (fx- n 1)))])))) - - (define iota - (lambda (n) - (let loop ([n n] [ls '()]) - (if (fxzero? n) - ls - (let ([n (- n 1)]) - (loop n (cons n ls))))))) - - (define regensym - (case-lambda - [(gs extra) - (unless (gensym? gs) (errorf 'regensym "~s is not a gensym" gs)) - (unless (string? extra) (errorf 'regensym "~s is not a string" extra)) - (let ([pretty-name (parameterize ([print-gensym #f]) (format "~s" gs))] - [unique-name (gensym->unique-string gs)]) - (with-input-from-string (format "#{~a ~a~a}" pretty-name unique-name extra) read))] - [(gs extra0 extra1) - (unless (gensym? gs) (errorf 'regensym "~s is not a gensym" gs)) - (unless (string? extra0) (errorf 'regensym "~s is not a string" extra0)) - (unless (string? extra1) (errorf 'regensym "~s is not a string" extra1)) - (with-output-to-string (lambda () (format "~s" gs))) - (let ([pretty-name (parameterize ([print-gensym #f]) (format "~s" gs))] - [unique-name (gensym->unique-string gs)]) - (with-input-from-string (format "#{~a~a ~a~a}" pretty-name extra0 unique-name extra1) read))])) - - (define provide-full-source-information - (make-parameter #t (lambda (x) (and x #t)))) - - (define-record-type source-information - (nongenerative) - (sealed #t) - (fields source-file byte-offset-start char-offset-start byte-offset-end - char-offset-end position-line position-column type) - (protocol - (lambda (new) - (lambda (a type) - (let ([as (annotation-source a)]) - (let ([fn (car as)] [cp (cdr as)]) - (if (provide-full-source-information) - (call-with-input-file fn - (lambda (ip) - (let loop ([n cp] [line 1] [col 0]) - (if (= n 0) - (new fn (port-position ip) cp #f #f line col type) - (let ([c (read-char ip)]) - (if (char=? c #\newline) - (loop (- n 1) (fx+ line 1) 0) - (loop (- n 1) line (fx+ col 1)))))))) - (new fn #f cp #f #f #f #f type)))))))) - - (define syntax->annotation - (lambda (x) - (and (struct? x) ;; syntax objects are structs - (string=? (struct-name x) "stx") ;; with the name syntax - (let ([e (struct-ref x 0)]) ;; the 0th element is potentially an annotation - (and (annotation? e) e))))) ;; if it is an annotation return it - - (define syntax->source-information - (lambda (stx) - (let loop ([stx stx] [type 'at]) - (cond - [(syntax->annotation stx) => - (lambda (a) (make-source-information a type))] - [(pair? stx) (or (loop (car stx) 'near) (loop (cdr stx) 'near))] - [else #f])))) - - (define-syntax errorf - (syntax-rules () - [(_ who fmt args ...) (error who (format fmt args ...))])) - - (define-syntax warningf - (syntax-rules () - [(_ who fmt args ...) (warning who (format fmt args ...))])) - - (define-syntax indirect-export - (syntax-rules () - [(_ id indirect-id ...) (define t (if #f #f))])) - - (define-syntax define-property - (lambda (x) - (syntax-case x () - [(_ id key value) - (with-syntax ([t (datum->syntax #'id (gensym (syntax->datum #'id)))]) - (syntax-property-set! #'id #'key (syntax->datum #'t)) - #'(define-syntax waste (let () (set-symbol-value! 't value) (lambda (x) (syntax-violation #f "invalid syntax" x)))))]))) - - (define-syntax with-compile-time-environment - (syntax-rules () - [(k (arg) body* ... body) - (lambda (rho) - (let ([arg (case-lambda - [(x) (rho x)] - [(x y) (let ([sym (syntax-property-get x y #f)]) - (and sym (symbol-value sym)))])]) - body* ... body))]))) diff --git a/ta6ob/nanopass/nanopass/implementation-helpers.ironscheme.sls b/ta6ob/nanopass/nanopass/implementation-helpers.ironscheme.sls deleted file mode 100644 index f22a059..0000000 --- a/ta6ob/nanopass/nanopass/implementation-helpers.ironscheme.sls +++ /dev/null @@ -1,195 +0,0 @@ -;;; Copyright (c) 2000-2018 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (nanopass implementation-helpers) - (export - ;; formatting - format printf pretty-print - - ;; listy stuff - iota make-list list-head - - ;; gensym stuff (related to nongenerative languages) - gensym regensym - - ;; source-information stuff - syntax->source-information - source-information-source-file - source-information-byte-offset-start - source-information-char-offset-start - source-information-byte-offset-end - source-information-char-offset-end - source-information-position-line - source-information-position-column - source-information-type - provide-full-source-information - - ;; library export stuff (needed for when used inside module to - ;; auto-indirect export things) - indirect-export - - ;; compile-time environment helpers - define-property make-compile-time-value - - ;; code organization helpers - module - - ;; useful for warning and error items - warningf errorf - - ;; used to get the best performance from hashtables - eq-hashtable-set! eq-hashtable-ref - - ;; debugging support - trace-lambda trace-define-syntax trace-let trace-define - - ;; needed to know what code to generate - optimize-level - - ;; the base record, so that we can use gensym syntax - define-nanopass-record - - ;; handy syntactic stuff - with-implicit - - ;; abstraction of the grabbing the syntactic environment that will work in - ;; Chez, Ikarus, Vicare and IronScheme - with-compile-time-environment - - ;; apparently not neeaded (or no longer needed) - ; scheme-version= scheme-version< scheme-version> scheme-version>= - ; scheme-version<= with-scheme-version gensym? errorf with-output-to-string - ; with-input-from-string - ) - (import - (rnrs) - (rnrs eval) - (ironscheme) - (nanopass syntactic-property) - (ironscheme core) - (ironscheme clr) - (ironscheme reader)) - - (define optimize-level (make-parameter 0)) ;; not sure what this is used for (yet) - - (define-syntax with-implicit - (syntax-rules () - [(_ (id name ...) body bodies ...) - (with-syntax ([name (datum->syntax #'id 'name)] ...) body bodies ...)])) - - ; the base language - (define-syntax define-nanopass-record - (lambda (x) - (syntax-case x () - [(k) (with-implicit (k nanopass-record nanopass-record? nanopass-record-tag) - #'(define-record-type (nanopass-record make-nanopass-record nanopass-record?) - (nongenerative nanopass-record-d47f8omgluol6otrw1yvu5-0) - (fields (immutable tag nanopass-record-tag))))]))) - - (define-syntax eq-hashtable-set! (identifier-syntax hashtable-set!)) - (define-syntax eq-hashtable-ref (identifier-syntax hashtable-ref)) - - (define list-head - (lambda (orig-ls orig-n) - (let f ([ls orig-ls] [n orig-n]) - (cond - [(fxzero? n) '()] - [(null? ls) (error 'list-head "index out of range" orig-ls orig-n)] - [else (cons (car ls) (f (cdr ls) (fx- n 1)))])))) - - (define iota - (lambda (n) - (let loop ([n n] [ls '()]) - (if (fxzero? n) - ls - (let ([n (fx- n 1)]) - (loop n (cons n ls))))))) - - (define (gensym? s) (eq? s (ungensym s))) - - ;; just stuffing info for now... I guess it is needed for prettiness only? - (define regensym - (case-lambda - [(gs extra) - (unless (gensym? gs) (errorf 'regensym "~s is not a gensym" gs)) - (unless (string? extra) (errorf 'regensym "~s is not a string" extra)) - ; (let ([pretty-name (parameterize ([print-gensym #f]) (format "~s" gs))] - ; [unique-name (gensym->unique-string gs)]) - ; (with-input-from-string (format "~a-~a~a" pretty-name unique-name extra) read)) - (gensym (format "~a~a" gs extra))] - [(gs extra0 extra1) - (unless (gensym? gs) (errorf 'regensym "~s is not a gensym" gs)) - (unless (string? extra0) (errorf 'regensym "~s is not a string" extra0)) - (unless (string? extra1) (errorf 'regensym "~s is not a string" extra1)) - ; (with-output-to-string (lambda () (format "~s" gs))) - ; (let ([pretty-name (parameterize ([print-gensym #f]) (format "~s" gs))] - ; [unique-name (gensym->unique-string gs)]) - ; (with-input-from-string (format "~a~a-~a~a" pretty-name extra0 unique-name extra1) read)) - (gensym (format "~a~a~a" gs extra0 extra1)) - ])) - - (define provide-full-source-information - (make-parameter #f (lambda (x) (and x #t)))) - - (define-record-type source-information - (nongenerative) - (sealed #t) - (fields source-file byte-offset-start char-offset-start byte-offset-end - char-offset-end position-line position-column type) - (protocol - (lambda (new) - (lambda (a type) - (let* ([as (annotation-source a)][cp (car (clr-static-call IronScheme.Runtime.Builtins SourceLocation (cdr as)))]) - (let ([fn (car as)] [line (car cp)][col (cdr cp)]) - ;; the line/col info from the reader is pretty accurate, do I need the stuff below? - (if (provide-full-source-information) - (call-with-input-file fn - (lambda (ip) - (let loop ([n cp] [line 1] [col 0]) - (if (= n 0) - (new fn (port-position ip) cp #f #f line col type) - (let ([c (read-char ip)]) - (if (char=? c #\newline) - (loop (- n 1) (fx+ line 1) 0) - (loop (- n 1) line (fx+ col 1)))))))) - (new fn #f #f #f #f line col type)))))))) - - (define syntax->source-information - (lambda (stx) - (let loop ([stx stx] [type 'at]) - (cond - [(stx? stx) - (let ([e (stx-expr stx)]) - (and (annotation? e) (make-source-information e type)))] - [(pair? stx) (or (loop (car stx) 'near) (loop (cdr stx) 'near))] - [else #f])))) - - (define-syntax errorf - (syntax-rules () - [(_ who fmt args ...) (error who (format fmt args ...))])) - - (define-syntax warningf - (syntax-rules () - [(_ who fmt args ...) (warning who (format fmt args ...))])) - - (define-syntax indirect-export - (syntax-rules () - [(_ id indirect-id ...) (define t (if #f #f))])) - - (define-syntax define-property - (lambda (x) - (syntax-case x () - [(_ id key value) - (with-syntax ([t (datum->syntax #'id (gensym (syntax->datum #'id)))]) - (syntax-property-set! #'id #'key (syntax->datum #'t)) - #'(define-syntax waste (let () (set-symbol-value! 't value) (lambda (x) (syntax-violation #f "invalid syntax" x)))))]))) - - (define-syntax with-compile-time-environment - (syntax-rules () - [(k (arg) body* ... body) - (lambda (rho) - (let ([arg (case-lambda - [(x) (rho x)] - [(x y) (let ([sym (syntax-property-get x y #f)]) - (and sym (symbol-value sym)))])]) - body* ... body))]))) diff --git a/ta6ob/nanopass/nanopass/implementation-helpers.vicare.sls b/ta6ob/nanopass/nanopass/implementation-helpers.vicare.sls deleted file mode 100644 index c8a53ca..0000000 --- a/ta6ob/nanopass/nanopass/implementation-helpers.vicare.sls +++ /dev/null @@ -1,174 +0,0 @@ -;;; Copyright (c) 2000-2018 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details -(library (nanopass implementation-helpers) - (export - ;; formatting - format printf pretty-print - - ;; listy stuff - iota make-list list-head - - ;; gensym stuff (related to nongenerative languages) - gensym regensym - - ;; source-information stuff - syntax->source-information - source-information-source-file - source-information-byte-offset-start - source-information-char-offset-start - source-information-byte-offset-end - source-information-char-offset-end - source-information-position-line - source-information-position-column - source-information-type - provide-full-source-information - - ;; library export stuff (needed for when used inside module to - ;; auto-indirect export things) - indirect-export - - ;; compile-time environment helpers - define-property (rename (make-expand-time-value make-compile-time-value)) - - ;; code organization helpers - module - - ;; useful for warning and error items - warningf errorf - - ;; used to get the best performance from hashtables - eq-hashtable-set! eq-hashtable-ref - - ;; debugging support - trace-lambda trace-define-syntax trace-let trace-define - - ;; needed to know what code to generate - optimize-level - - ;; the base record, so that we can use gensym syntax - define-nanopass-record - - ;; handy syntactic stuff - with-implicit - - ;; abstraction of the grabbing the syntactic environment that will work in - ;; Chez, Ikarus, & Vicare - with-compile-time-environment - - ;; apparently not neeaded (or no longer needed) - ; scheme-version= scheme-version< scheme-version> scheme-version>= - ; scheme-version<= with-scheme-version gensym? errorf with-output-to-string - ; with-input-from-string - ) - (import - (vicare) - (vicare language-extensions) - (vicare language-extensions tracing-syntaxes) - (only (vicare expander) stx? stx-expr) - (only (vicare compiler) optimize-level)) - - (define-syntax with-implicit - (syntax-rules () - [(_ (id name ...) body bodies ...) - (with-syntax ([name (datum->syntax #'id 'name)] ...) body bodies ...)])) - - ; the base language - (define-syntax define-nanopass-record - (lambda (x) - (syntax-case x () - [(k) (with-implicit (k nanopass-record nanopass-record? nanopass-record-tag) - #'(define-record-type (nanopass-record make-nanopass-record nanopass-record?) - (nongenerative #{nanopass-record d47f8omgluol6otrw1yvu5-0}) - (fields (immutable tag nanopass-record-tag))))]))) - - (define-syntax eq-hashtable-set! (identifier-syntax hashtable-set!)) - (define-syntax eq-hashtable-ref (identifier-syntax hashtable-ref)) - - (define list-head - (lambda (orig-ls orig-n) - (let f ([ls orig-ls] [n orig-n]) - (cond - [(fxzero? n) '()] - [(null? ls) (error 'list-head "index out of range" orig-ls orig-n)] - [else (cons (car ls) (f (cdr ls) (fx- n 1)))])))) - - (define iota - (lambda (n) - (let loop ([n n] [ls '()]) - (if (fxzero? n) - ls - (let ([n (- n 1)]) - (loop n (cons n ls))))))) - - (define regensym - (case-lambda - [(gs extra) - (unless (gensym? gs) (errorf 'regensym "~s is not a gensym" gs)) - (unless (string? extra) (errorf 'regensym "~s is not a string" extra)) - (let ([pretty-name (parameterize ([print-gensym #f]) (format "~s" gs))] - [unique-name (gensym->unique-string gs)]) - (with-input-from-string (format "#{~a ~a~a}" pretty-name unique-name extra) read))] - [(gs extra0 extra1) - (unless (gensym? gs) (errorf 'regensym "~s is not a gensym" gs)) - (unless (string? extra0) (errorf 'regensym "~s is not a string" extra0)) - (unless (string? extra1) (errorf 'regensym "~s is not a string" extra1)) - (with-output-to-string (lambda () (format "~s" gs))) - (let ([pretty-name (parameterize ([print-gensym #f]) (format "~s" gs))] - [unique-name (gensym->unique-string gs)]) - (with-input-from-string (format "#{~a~a ~a~a}" pretty-name extra0 unique-name extra1) read))])) - - (define provide-full-source-information - (make-parameter #t (lambda (x) (and x #t)))) - - (define-record-type source-information - (nongenerative) - (sealed #t) - (fields source-file byte-offset-start char-offset-start byte-offset-end - char-offset-end position-line position-column type) - (protocol - (lambda (new) - (lambda (a type) - (let ([sp (reader-annotation-textual-position a)]) - (new - (source-position-port-id sp) (source-position-byte sp) - (source-position-character sp) #f #f (source-position-line sp) - (source-position-column sp) type)))))) - - (define syntax->source-information - (lambda (stx) - (let loop ([stx stx] [type 'at]) - (cond - [(stx? stx) - (let ([e (stx-expr stx)]) - (and (reader-annotation? e) (make-source-information e type)))] - [(pair? stx) (or (loop (car stx) 'near) (loop (cdr stx) 'near))] - [else #f])))) - - (define-syntax warningf - (syntax-rules () - [(_ who fmt args ...) (warning who (format fmt args ...))])) - - (define-syntax errorf - (syntax-rules () - [(_ who fmt args ...) (error who (format fmt args ...))])) - - (define-syntax indirect-export - (syntax-rules () - [(_ id indirect-id ...) (define t (if #f #f))])) - - (define-syntax define-property - (lambda (x) - (syntax-case x () - [(_ id key value) - (with-syntax ([t (datum->syntax #'id (gensym (syntax->datum #'id)))]) - (syntactic-binding-putprop #'id (syntax->datum #'key) (syntax->datum #'t)) - #'(define-syntax waste (let () (set-symbol-value! 't value) (lambda (x) (syntax-violation #f "invalid syntax" x)))))]))) - - (define-syntax with-compile-time-environment - (syntax-rules () - [(_ (arg) body* ... body) - (let ([arg (case-lambda - [(x) (retrieve-expand-time-value x)] - [(x y) (let ([sym (syntactic-binding-getprop x (syntax->datum y))]) - (and sym (symbol-value sym)))])]) - body* ... body)]))) diff --git a/ta6ob/nanopass/nanopass/language-helpers.ss b/ta6ob/nanopass/nanopass/language-helpers.ss deleted file mode 100644 index 8be4d22..0000000 --- a/ta6ob/nanopass/nanopass/language-helpers.ss +++ /dev/null @@ -1,59 +0,0 @@ -(library (nanopass language-helpers) - (export prune-language-helper) - (import (rnrs) (nanopass records)) - - (define tspec->ts-syntax - (lambda (tspec) - (with-syntax ([(meta-vars ...) (tspec-meta-vars tspec)] - [type (tspec-type tspec)]) - #'(type (meta-vars ...))))) - - (define ntspec->nts-syntax - (lambda (ntspec) - (with-syntax ([(meta-vars ...) (ntspec-meta-vars ntspec)] - [name (ntspec-name ntspec)] - [(prods ...) (map alt-syn (ntspec-alts ntspec))]) - #'(name (meta-vars ...) prods ...)))) - - (define prune-language-helper - (lambda (l) - (let ([entry (language-entry-ntspec l)]) - (let ([nt* (list (nonterm-id->ntspec 'prune-language entry (language-ntspecs l)))]) - (let loop ([nt* nt*] [ts '()] [nts '()]) - (if (null? nt*) - (with-syntax ([(ts ...) (map tspec->ts-syntax ts)] - [(nts ...) (map ntspec->nts-syntax nts)]) - #'((ts ...) (nts ...))) - (let ([nt (car nt*)] [nt* (cdr nt*)]) - (let ([nts (cons nt nts)]) - (let inner-loop ([prod* (ntspec-alts nt)] [nt* nt*] [ts ts]) - (if (null? prod*) - (loop nt* ts nts) - (let ([prod (car prod*)]) - (cond - [(terminal-alt? prod) - (inner-loop (cdr prod*) nt* - (let ([tspec (terminal-alt-tspec prod)]) - (if (memq tspec ts) ts (cons tspec ts))))] - [(nonterminal-alt? prod) - (inner-loop (cdr prod*) - (let ([ntspec (nonterminal-alt-ntspec prod)]) - (if (or (memq ntspec nt*) (memq ntspec nts)) nt* (cons ntspec nt*))) - ts)] - [(pair-alt? prod) - (let inner-inner-loop ([flds (pair-alt-field-names prod)] [nt* nt*] [ts ts]) - (if (null? flds) - (inner-loop (cdr prod*) nt* ts) - (let ([fld (car flds)]) - (cond - [(meta-name->tspec fld (language-tspecs l)) => - (lambda (tspec) - (inner-inner-loop (cdr flds) nt* - (if (memq tspec ts) ts (cons tspec ts))))] - [(meta-name->ntspec fld (language-ntspecs l)) => - (lambda (ntspec) - (inner-inner-loop (cdr flds) - (if (or (memq ntspec nt*) (memq ntspec nts)) nt* (cons ntspec nt*)) - ts))]))))]))))))))))))) - - diff --git a/ta6ob/nanopass/nanopass/language-node-counter.ss b/ta6ob/nanopass/nanopass/language-node-counter.ss deleted file mode 100644 index 3ac6564..0000000 --- a/ta6ob/nanopass/nanopass/language-node-counter.ss +++ /dev/null @@ -1,101 +0,0 @@ -;;; Copyright (c) 2000-2015 Andrew W. Keep -;;; See the accompanying file Copyright for details - -(library (nanopass language-node-counter) - (export define-language-node-counter) - (import (rnrs) (nanopass records) (nanopass helpers)) - - (define-syntax define-language-node-counter - (lambda (x) - (define make-ntspec-counter-assoc - (lambda (tid) - (lambda (ntspec) - (cons ntspec (construct-unique-id tid "count-" (ntspec-name ntspec)))))) - (syntax-case x () - [(_ name lang) - (and (identifier? #'name) (identifier? #'lang)) - (lambda (r) - (let ([l-pair (r #'lang)]) - (unless l-pair (syntax-violation 'define-language-node-counter (format "unknown language ~s" (datum lang)) #'name x)) - (let ([l (car l-pair)]) - (let ([ntspecs (language-ntspecs l)] [tspecs (language-tspecs l)]) - (let ([counter-names (map (make-ntspec-counter-assoc #'name) ntspecs)]) - (define lookup-counter - (lambda (ntspec) - (cond - [(assq ntspec counter-names) => cdr] - [else (syntax-violation 'define-language-node-counter - (format "unexpected nonterminal ~s in language ~s" - (syntax->datum (ntspec-name ntspec)) (datum lang)) - #'name x)]))) - (define build-counter-proc - (lambda (proc-name l) - (lambda (ntspec) - (let loop ([alt* (ntspec-alts ntspec)] [term* '()] [nonterm* '()] [pair* '()]) - (if (null? alt*) - #`(lambda (x) - (cond - #,@term* - #,@pair* - #,@nonterm* - [else (errorf who "unrecognized term ~s" x)])) - (let ([alt (car alt*)] [alt* (cdr alt*)]) - (cond - [(terminal-alt? alt) - (loop alt* - (cons #`[(#,(tspec-pred (terminal-alt-tspec alt)) x) 1] term*) - nonterm* pair*)] - [(nonterminal-alt? alt) - (let ([ntspec (nonterminal-alt-ntspec alt)]) - (loop alt* term* - (cons #`[(#,(ntspec-all-pred ntspec) x) - (#,(lookup-counter ntspec) x)] - nonterm*) - pair*))] - [(pair-alt? alt) - (let inner-loop ([fld* (pair-alt-field-names alt)] - [lvl* (pair-alt-field-levels alt)] - [maybe?* (pair-alt-field-maybes alt)] - [acc* (pair-alt-accessors alt)] - [rec* '()]) - (if (null? fld*) - (loop alt* term* nonterm* - (cons #`[(#,(pair-alt-pred alt) x) (+ 1 #,@rec*)] pair*)) - (inner-loop (cdr fld*) (cdr lvl*) (cdr maybe?*) (cdr acc*) - (cons - (let ([fld (car fld*)] [maybe? (car maybe?*)] [acc (car acc*)]) - (let ([spec (find-spec fld l)]) - (if (ntspec? spec) - #`(let ([x (#,acc x)]) - #,(let loop ([lvl (car lvl*)] [outer-most? #t]) - (if (fx=? lvl 0) - (if maybe? - (if outer-most? - #`(if x (#,(lookup-counter spec) x) 0) - #`(+ a (if x (#,(lookup-counter spec) x) 0))) - (if outer-most? - #`(#,(lookup-counter spec) x) - #`(+ a (#,(lookup-counter spec) x)))) - (if outer-most? - #`(fold-left - (lambda (a x) #,(loop (- lvl 1) #f)) - 0 x) - #`(fold-left - (lambda (a x) #,(loop (- lvl 1) #f)) - a x))))) - 0))) - rec*))))] - [else (syntax-violation 'define-language-node-counter - (format "unrecognized alt ~s building language node counter" (syntax->datum (alt-syn alt))) - proc-name x)]))))))) - (with-syntax ([(ntspec? ...) (map ntspec-pred ntspecs)] - [(proc-name ...) (map cdr counter-names)] - [(tspec? ...) (map tspec-pred tspecs)] - [(proc ...) (map (build-counter-proc #'name l) ntspecs)]) - #'(define-who name - (lambda (x) - (define proc-name proc) ... - (cond - [(ntspec? x) (proc-name x)] ... - [(tspec? x) 1] ... - [else (errorf who "unrecognized language record ~s" x)])))))))))])))) diff --git a/ta6ob/nanopass/nanopass/language.ss b/ta6ob/nanopass/nanopass/language.ss deleted file mode 100644 index 23344fd..0000000 --- a/ta6ob/nanopass/nanopass/language.ss +++ /dev/null @@ -1,536 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -;;; Producs are : record defs, parser, meta parser, lang -;;; may need to use meta define meta-parser. -;;; -;;; TODO: -;;; - add facility to allow for functional transformations while unparsing -;;; (instead of just the pattern ones available now). this should be -;;; clearer than the old definitions form. -;;; - re-investigate how language extensions work and see if there is a -;;; cleaner way to do this -;;; - better comparison of alts then simple symbolic equality -;;; - checking for language output to make sure constructed languages are -;;; internally consistent: -;;; - check to make sure metas are unique -(library (nanopass language) - (export define-language language->s-expression diff-languages prune-language define-pruned-language) - (import (rnrs) - (nanopass helpers) - (nanopass language-helpers) - (nanopass records) - (nanopass unparser) - (nanopass meta-parser)) - - (define-syntax define-language - (syntax-rules () - [(_ ?L ?rest ...) - (let-syntax ([a (syntax-rules () - [(_ ?XL) - (x-define-language ?XL ((... ...) ?rest) ...)])]) - (a ?L))])) - - (define-syntax x-define-language - (lambda (x) - ;; This function tests equality of tspecs - ;; tspecs are considered to be equal when the lists of metas are - ;; identical (same order too) and when they represent the same terminal - ; TODO: think about a better way of doing equality here... right now we get a weird - ; error message when the original had (fixnum (x y z)) and our extension has (fixnum (x y)) - (define tspec=? - (lambda (ts1 ts2) - (and (equal? (syntax->datum (tspec-meta-vars ts1)) - (syntax->datum (tspec-meta-vars ts2))) - (eq? (syntax->datum (tspec-type ts1)) - (syntax->datum (tspec-type ts2)))))) - - ;; This function tests the equality of ntspecs - ;; ntspecs are considered to be equal when they are ntspecs of - ;; the same nonterminal and the intersection of their alternatives is - ;; not null - (define ntspec=? - (lambda (p1 p2) - (eq? (syntax->datum (ntspec-name p1)) - (syntax->datum (ntspec-name p2))))) - - ;; It is enough to check for same syntax because the record-decls of the - ;; new alternative will be different because they are parsed again - (define alt=? - (lambda (a1 a2) - (equal? (syntax->datum (alt-syn a1)) (syntax->datum (alt-syn a2))))) - - (define fresh-tspec - (lambda (tspec) - (make-tspec - (tspec-type tspec) - (tspec-meta-vars tspec) - (tspec-handler tspec)))) - - (define-who fresh-alt - (lambda (alt) - (cond - [(pair-alt? alt) (make-pair-alt (alt-syn alt) (alt-pretty alt) (alt-pretty-procedure? alt))] - [(terminal-alt? alt) (make-terminal-alt (alt-syn alt) (alt-pretty alt) (alt-pretty-procedure? alt))] - [(nonterminal-alt? alt) (make-nonterminal-alt (alt-syn alt) (alt-pretty alt) (alt-pretty-procedure? alt))] - [else (error who "unexpected alt" alt)]))) - - (define fresh-ntspec - (lambda (ntspec) - (make-ntspec - (ntspec-name ntspec) - (ntspec-meta-vars ntspec) - (map fresh-alt (ntspec-alts ntspec))))) - - ;; Doing a little extra work here to make sure that we are able to track - ;; errors. The basic idea is that we want to go through the list of - ;; existing tspecs, and when we keep them, make a new copy (so that - ;; language specific information can be updated in them), and when they - ;; are being removed, we "mark" that we found the one to remove by - ;; pulling it out of our removal list. If any remain in the removal - ;; list when we're done, we complain about it. - (define freshen-objects - (lambda (o=? fresh-o msg unpacker) - (rec f - (lambda (os os-) - (cond - [(and (null? os) (not (null? os-))) - (syntax-violation 'define-language msg (map unpacker os-))] - [(null? os) '()] - [else - (let g ([os- os-] [o (car os)] [checked-os- '()]) - (cond - [(null? os-) (cons (fresh-o o) (f (cdr os) checked-os-))] - [(o=? o (car os-)) - (f (cdr os) (append checked-os- (cdr os-)))] - [else (g (cdr os-) o (cons (car os-) checked-os-))]))]))))) - - (define freshen-tspecs - (freshen-objects tspec=? fresh-tspec "unrecognized tspecs" tspec-type)) - (define freshen-alts - (freshen-objects alt=? fresh-alt "unrecognized alts" alt-syn)) - - (define add-objects - (lambda (o=? msg) - (letrec ([f (lambda (os os+) - (if (null? os+) - os - (let ([o+ (car os+)]) - (when (memp (lambda (x) (o=? o+ x)) os) - (syntax-violation 'define-language msg o+)) - (f (cons o+ os) (cdr os+)))))]) - f))) - - (define add-tspecs (add-objects tspec=? "duplicate tspec in add")) - (define add-alts (add-objects alt=? "duplicate alt in add")) - - (define freshen-ntspecs - (lambda (ntspecs ntspecs-) - (cond - [(and (null? ntspecs) (not (null? ntspecs-))) - (if (fx>? (length ntspecs-) 1) - (syntax-violation 'define-language - "multiple unrecognized ntspecs, including" - (ntspec-name (car ntspecs-))) - (syntax-violation 'define-language - "unrecognized ntspec" (ntspec-name (car ntspecs-))))] - [(null? ntspecs) '()] - [else - (let g ([ntspecs- ntspecs-] [ntspec (car ntspecs)] [remaining '()]) - (if (null? ntspecs-) - (cons (fresh-ntspec ntspec) (freshen-ntspecs (cdr ntspecs) remaining)) - (let ([ntspec- (car ntspecs-)]) - (if (ntspec=? ntspec- ntspec) - (let ([alts (freshen-alts (ntspec-alts ntspec) (ntspec-alts ntspec-))]) - (if (null? alts) - (freshen-ntspecs (cdr ntspecs) (append remaining (cdr ntspecs-))) - (cons (make-ntspec - (ntspec-name ntspec-) - (ntspec-meta-vars ntspec-) - alts) - (freshen-ntspecs (cdr ntspecs) (append remaining (cdr ntspecs-)))))) - (g (cdr ntspecs-) ntspec (cons (car ntspecs-) remaining))))))]))) - - (define add-ntspecs - (lambda (ntspecs ntspecs+) - (cond - [(null? ntspecs) ntspecs+] - [else - (let g ([ntspecs+ ntspecs+] [ntspec (car ntspecs)] [remaining '()]) - (if (null? ntspecs+) - (cons ntspec (add-ntspecs (cdr ntspecs) remaining)) - (let ([ntspec+ (car ntspecs+)]) - (if (ntspec=? ntspec+ ntspec) - (let ([alts (add-alts (ntspec-alts ntspec) (ntspec-alts ntspec+))]) - (cons (make-ntspec - (ntspec-name ntspec+) - (ntspec-meta-vars ntspec+) - alts) - (add-ntspecs (cdr ntspecs) (append remaining (cdr ntspecs+))))) - (g (cdr ntspecs+) ntspec (cons (car ntspecs+) remaining))))))]))) - - (define partition-terms - (lambda (terms) - (let f ([terms terms] [terms+ '()] [terms- '()]) - (syntax-case terms () - [() (values terms+ terms-)] - [((+ t* ...) terms ...) (plus? #'+) - (f #'(terms ...) - (append terms+ (parse-terms #'(t* ...))) terms-)] - [((- t* ...) terms ...) (minus? #'-) - (f #'(terms ...) terms+ - (append terms- (parse-terms #'(t* ...))))])))) - - (define partition-ntspecs - (lambda (ntspecs terminal-meta*) - (let f ([ntspecs ntspecs] [ntspecs+ '()] [ntspecs- '()]) - (if (null? ntspecs) - (values ntspecs+ ntspecs-) ;; lists returned are reversed (okay?) - (let ([ntspec (car ntspecs)] [ntspecs (cdr ntspecs)]) - (let g ([alts (cddr ntspec)] [alts+ '()] [alts- '()]) - (syntax-case alts () - [() (let ([name (car ntspec)] [metas (cadr ntspec)]) - (f ntspecs - (if (null? alts+) - ntspecs+ - (cons (make-ntspec name metas alts+) - ntspecs+)) - (if (null? alts-) - ntspecs- - (cons (make-ntspec name metas alts-) - ntspecs-))))] - [((+ a* ...) alts ...) (plus? #'+) - (g #'(alts ...) (append alts+ (parse-alts #'(a* ...) terminal-meta*)) - alts-)] - [((- a* ...) alts ...) (minus? #'-) - (g #'(alts ...) alts+ - (append alts- (parse-alts #'(a* ...) terminal-meta*)))]))))))) - - (define parse-alts - (lambda (alt* terminal-meta*) - (define make-alt - (lambda (syn pretty pretty-procedure?) - (syntax-case syn () - [(s s* ...) (make-pair-alt #'(s s* ...) pretty pretty-procedure?)] - [(s s* ... . sr) (make-pair-alt #'(s s* ... . sr) pretty pretty-procedure?)] - [s - (identifier? #'s) - (if (memq (meta-var->raw-meta-var (syntax->datum #'s)) terminal-meta*) - (make-terminal-alt #'s pretty pretty-procedure?) - (make-nonterminal-alt #'s pretty pretty-procedure?))]))) - (let f ([alt* alt*]) - (syntax-case alt* () - [() '()] - [((=> syn pretty) . alt*) (double-arrow? #'=>) - (cons (make-alt #'syn #'pretty #f) (f #'alt*))] - [(syn => pretty . alt*) (double-arrow? #'=>) - (cons (make-alt #'syn #'pretty #f) (f #'alt*))] - [((-> syn prettyf) . alt*) (arrow? #'->) - (with-implicit (-> with-extended-quasiquote) - (cons (make-alt #'syn #'(with-extended-quasiquote prettyf) #t) (f #'alt*)))] - [(syn -> prettyf . alt*) (arrow? #'->) - (with-implicit (-> with-extended-quasiquote) - (cons (make-alt #'syn #'(with-extended-quasiquote prettyf) #t) (f #'alt*)))] - [(syn . alt*) (cons (make-alt #'syn #f #f) (f #'alt*))] - [_ (syntax-violation 'define-language "unexpected alt" alt*)])))) - - (define parse-terms - (lambda (term*) - (syntax-case term* () - [() '()] - [((=> (t (tmeta* ...)) handler) term* ...) (double-arrow? #'=>) - (cons (make-tspec #'t #'(tmeta* ...) #'handler) - (parse-terms #'(term* ...)))] - [((t (tmeta* ...)) => handler term* ...) (double-arrow? #'=>) - (cons (make-tspec #'t #'(tmeta* ...) #'handler) - (parse-terms #'(term* ...)))] - [((t (tmeta* ...)) term* ...) - (cons (make-tspec #'t #'(tmeta* ...)) - (parse-terms #'(term* ...)))]))) - - (define parse-language-and-finish - (lambda (name ldef) - (define parse-clauses - (lambda (ldef) - (let f ([ldef ldef] [base-lang #f] [found-entry #f] - [entry-ntspec #f] [first-ntspec #f] [terms '()] [ntspecs '()] [nongen-id #f]) - (syntax-case ldef (extends entry terminals nongenerative-id) - [() (values base-lang (if base-lang entry-ntspec (or entry-ntspec first-ntspec)) terms (reverse ntspecs) nongen-id)] - [((nongenerative-id ?id) . rest) - (identifier? #'?id) - (begin - (when nongen-id - (syntax-violation 'define-language - "only one nongenerative-id clause allowed in language definition" - #'(nongenerative-id ?id) name)) - (f #'rest base-lang found-entry entry-ntspec first-ntspec terms ntspecs #'?id))] - [((extends ?L) . rest) - (identifier? #'?L) - (begin - (when base-lang - (syntax-violation 'define-language - "only one extends clause allowed in language definition" - #'(extends ?L) name)) - (f #'rest #'?L found-entry entry-ntspec first-ntspec terms ntspecs nongen-id))] - [((entry ?P) . rest) - (identifier? #'?P) - (begin - (when found-entry - (syntax-violation 'define-language - "only one entry clause allowed in language definition" - #'(entry ?P) entry-ntspec)) - (f #'rest base-lang #t #'?P first-ntspec terms ntspecs nongen-id))] - [((terminals ?t* ...) . rest) - (f #'rest base-lang found-entry entry-ntspec first-ntspec - (append terms #'(?t* ...)) ntspecs nongen-id)] - [((ntspec (meta* ...) a a* ...) . rest) - (and (identifier? #'ntspec) (map identifier? #'(meta* ...))) - (f #'rest base-lang found-entry - entry-ntspec - (if first-ntspec first-ntspec #'ntspec) - terms (cons (cons* #'ntspec #'(meta* ...) #'a #'(a* ...)) ntspecs) - nongen-id)] - [(x . rest) (syntax-violation 'define-language "unrecognized clause" #'x)] - [x (syntax-violation 'define-language - "unrecognized rest of language clauses" #'x)])))) - (let-values ([(base-lang entry-ntspec terms ntspecs nongen-id) (parse-clauses ldef)]) - (with-compile-time-environment (r) - (if base-lang - (let ([base-pair (r base-lang)]) - (unless (and (pair? base-pair) - (language? (car base-pair)) - (procedure? (cdr base-pair))) - (syntax-violation 'define-language - "unrecognized base language" base-lang x)) - (let ([base (car base-pair)]) - (let ([entry-ntspec (or entry-ntspec (language-entry-ntspec base))]) - (finish r nongen-id entry-ntspec name name - (let-values ([(terms+ terms-) (partition-terms terms)]) - (let* ([tspecs (freshen-tspecs (language-tspecs base) terms-)] - [tspecs (add-tspecs tspecs terms+)] - [terminal-meta* (extract-terminal-metas tspecs)]) - (let-values ([(ntspecs+ ntspecs-) (partition-ntspecs ntspecs terminal-meta*)]) - (let* ([ntspecs (freshen-ntspecs (language-ntspecs base) ntspecs-)] - [ntspecs (add-ntspecs ntspecs ntspecs+)]) - (make-language name entry-ntspec tspecs ntspecs nongen-id))))))))) - (let* ([tspecs (parse-terms terms)] - [terminal-meta* (extract-terminal-metas tspecs)]) - (finish r nongen-id entry-ntspec name name - (make-language name - entry-ntspec - tspecs - (map (lambda (ntspec) - (make-ntspec (car ntspec) (cadr ntspec) - (parse-alts (cddr ntspec) terminal-meta*))) - ntspecs) - nongen-id)))))))) - - (define extract-terminal-metas - (lambda (tspecs) - (fold-left (lambda (metas tspec) - (append (syntax->datum (tspec-meta-vars tspec)) metas)) - '() tspecs))) - - (define finish - (lambda (r nongen-id ntname lang id desc) ; constructs the output - (annotate-language! r desc id) - (with-syntax ([(records ...) (language->lang-records desc)] - [(predicates ...) (language->lang-predicates desc)] - [unparser-name (construct-id id "unparse-" lang)] - [meta-parser (make-meta-parser desc)]) - #;(pretty-print (list 'unparser (syntax->datum lang) (syntax->datum #'unparser))) - #;(pretty-print (list 'meta-parser (syntax->datum lang) (syntax->datum #'meta-parser))) - #`(begin - records ... - predicates ... - (define-syntax #,lang - (make-compile-time-value - (cons '#,desc meta-parser))) - #;(define-property #,lang meta-parser-property meta-parser) - (define-unparser unparser-name #,lang))))) - - (syntax-case x () - [(_ ?L ?rest ...) - (identifier? #'?L) - (parse-language-and-finish #'?L #'(?rest ...))] - [(_ (?L ?nongen-id) ?rest ...) - (and (identifier? #'?L) (identifier? #'?nongen-id)) - (parse-language-and-finish #'?L #'(?rest ...))]))) - - (define-syntax language->s-expression - (lambda (x) - (define who 'language->s-expression) - (define doit - (lambda (lang handler?) - (define tspec->s-expression - (lambda (t) - (if (and handler? (tspec-handler t)) - #`(=> (#,(tspec-type t) #,(tspec-meta-vars t)) - #,(tspec-handler t)) - #`(#,(tspec-type t) #,(tspec-meta-vars t))))) - (define alt->s-expression - (lambda (a) - (if (and handler? (alt-pretty a)) - #`(=> #,(alt-syn a) #,(alt-pretty a)) - (alt-syn a)))) - (define ntspec->s-expression - (lambda (p) - #`(#,(ntspec-name p) #,(ntspec-meta-vars p) - #,@(map alt->s-expression (ntspec-alts p))))) - (lambda (env) - (let ([lang-pair (env lang)]) - (unless lang-pair (syntax-violation who "language not found" lang)) - (let ([lang (car lang-pair)]) - (with-syntax ([(ng ...) (let ([nongen-id (language-nongenerative-id lang)]) - (if nongen-id - #`((nongenerative-id #,nongen-id)) - #'()))]) - #`'(define-language #,(language-name lang) - ng ... - (entry #,(language-entry-ntspec lang)) - (terminals #,@(map tspec->s-expression (language-tspecs lang))) - #,@(map ntspec->s-expression (language-ntspecs lang))))))))) - (syntax-case x () - [(_ lang) (identifier? #'lang) (doit #'lang #f)] - [(_ lang handler?) (identifier? #'lang) (doit #'lang (syntax->datum #'handler?))]))) - - (define-syntax diff-languages - (lambda (x) - (define who 'diff-languages) - (define combine - (lambda (same removed added) - (if (null? removed) - (if (null? added) - '() - #`((+ #,@added))) - (if (null? added) - #`((- #,@removed)) - #`((- #,@removed) (+ #,@added)))))) - (define tspec->syntax - (lambda (tspec) - #`(#,(tspec-type tspec) #,(tspec-meta-vars tspec)))) - (define ntspec->syntax - (lambda (ntspec) - #`(#,(ntspec-name ntspec) #,(ntspec-meta-vars ntspec) #,@(map alt-syn (ntspec-alts ntspec))))) - (define diff-meta-vars - (lambda (mv0* mv1*) - mv1* - #;(let f ([mv0* mv0*] [mv1* mv1*] [same '()] [removed '()] [added '()]) - (cond - [(and (null? mv0*) (null? mv1*)) (combine same removed added)] - [(null? mv0*) (f mv0* (cdr mv1*) same removed (cons (car mv1*) added))] - [else - (let* ([mv0 (car mv0*)] [mv0-sym (syntax->datum mv0)]) - (cond - [(find (lambda (mv1) (eq? (syntax->datum mv1) mv0-sym)) mv1*) => - (lambda (mv1) (f (cdr mv0*) (remq mv1 mv1*) (cons mv1 same) removed added))] - [else (f (cdr mv0*) mv1* same (cons mv0 removed) added)]))])))) - (define diff-terminals - (lambda (t0* t1*) - (let f ([t0* t0*] [t1* t1*] [same '()] [removed '()] [added '()]) - (cond - [(and (null? t0*) (null? t1*)) (combine same removed added)] - [(null? t0*) (f t0* (cdr t1*) same removed (cons (tspec->syntax (car t1*)) added))] - [else - (let* ([t0 (car t0*)] [t0-type (tspec-type t0)] [t0-type-sym (syntax->datum t0-type)]) - (cond - [(find (lambda (t1) (eq? (syntax->datum (tspec-type t1)) t0-type-sym)) t1*) => - (lambda (t1) - (with-syntax ([(meta-vars ...) (diff-meta-vars (tspec-meta-vars t0) (tspec-meta-vars t1))]) - (f (cdr t0*) (remq t1 t1*) (cons #`(#,t0-type (meta-vars ...)) same) removed added)))] - [else (f (cdr t0*) t1* same (cons (tspec->syntax t0) removed) added)]))])))) - (define diff-alts - (lambda (a0* a1*) - (let f ([a0* a0*] [a1* a1*] [same '()] [removed '()] [added '()]) - (cond - [(and (null? a0*) (null? a1*)) (combine same removed added)] - [(null? a0*) (f a0* (cdr a1*) same removed (cons (alt-syn (car a1*)) added))] - [else - (let* ([a0 (car a0*)] [a0-syn (alt-syn a0)] [a0-syn-s-expr (syntax->datum a0-syn)]) - (cond - [(find (lambda (a1) (equal? (syntax->datum (alt-syn a1)) a0-syn-s-expr)) a1*) => - (lambda (a1) (f (cdr a0*) (remq a1 a1*) (cons a0-syn same) removed added))] - [else (f (cdr a0*) a1* same (cons (alt-syn a0) removed) added)]))])))) - (define diff-nonterminals - (lambda (nt0* nt1*) - (let f ([nt0* nt0*] [nt1* nt1*] [updated '()]) - (cond - [(and (null? nt0*) (null? nt1*)) updated] - [(null? nt0*) - (f nt0* (cdr nt1*) - (let ([nt1 (car nt1*)]) - (cons #`(#,(ntspec-name nt1) #,(ntspec-meta-vars nt1) (+ #,@(map alt-syn (ntspec-alts nt1)))) - updated)))] - [else - (let* ([nt0 (car nt0*)] [nt0-name (ntspec-name nt0)] [nt0-name-sym (syntax->datum nt0-name)]) - (cond - [(find (lambda (nt1) (eq? (syntax->datum (ntspec-name nt1)) nt0-name-sym)) nt1*) => - (lambda (nt1) - (f (cdr nt0*) (remq nt1 nt1*) - (let ([alts (diff-alts (ntspec-alts nt0) (ntspec-alts nt1))]) - (syntax-case alts () - [() updated] - [(alts ...) - (with-syntax ([(meta-vars ...) (diff-meta-vars (ntspec-meta-vars nt0) (ntspec-meta-vars nt1))]) - (cons #`(#,nt0-name (meta-vars ...) alts ...) updated))]))))] - [else (f (cdr nt0*) nt1* (cons #`(#,nt0-name #,(ntspec-meta-vars nt0) (- #,@(map alt-syn (ntspec-alts nt0)))) updated))]))])))) - (syntax-case x () - [(_ lang0 lang1) - (with-compile-time-environment (r) - (let ([l0-pair (r #'lang0)] [l1-pair (r #'lang1)]) - (unless l0-pair (syntax-violation who "language not found" #'lang0)) - (unless l1-pair (syntax-violation who "language not found" #'lang1)) - (let ([l0 (car l0-pair)] [l1 (car l1-pair)]) - (with-syntax ([l1-entry (language-entry-ntspec l1)] - [(term ...) (diff-terminals (language-tspecs l0) (language-tspecs l1))] - [(nonterm ...) (diff-nonterminals (language-ntspecs l0) (language-ntspecs l1))] - [(ng ...) (let ([nongen-id (language-nongenerative-id l1)]) - (if nongen-id - #`((nongenerative-id #,nongen-id)) - #'()))]) - (syntax-case #'(term ...) () - [() #''(define-language lang1 (extends lang0) - ng ... - (entry l1-entry) - nonterm ...)] - [(term ...) #''(define-language lang1 (extends lang0) - ng ... - (entry l1-entry) - (terminals term ...) - nonterm ...)])))))]))) - (define-syntax prune-language - (lambda (x) - (define who 'prune-language) - (syntax-case x () - [(_ L) - (with-compile-time-environment (r) - (let ([l-pair (r #'L)]) - (unless l-pair (syntax-violation who "language not found" #'L)) - (let ([l (car l-pair)]) - (with-syntax ([((ts ...) (nts ...)) (prune-language-helper l)] - [entry-nt (language-entry-ntspec l)]) - (syntax-case #'(ts ...) () - [() #''(define-language L - (entry entry-nt) - nts ...)] - [(ts ...) #''(define-language L - (entry entry-nt) - (terminals ts ...) - nts ...)])))))]))) - - (define-syntax define-pruned-language - (lambda (x) - (define who 'define-pruned-language) - (syntax-case x () - [(_ L new-name) - (with-compile-time-environment (r) - (let ([l-pair (r #'L)]) - (unless l-pair (syntax-violation who "language not found" #'L)) - (let ([l (car l-pair)]) - (with-syntax ([((ts ...) (nts ...)) (prune-language-helper l)] - [entry-nt (language-entry-ntspec l)]) - #'(define-language new-name - (entry entry-nt) - (terminals ts ...) - nts ...)))))])))) - diff --git a/ta6ob/nanopass/nanopass/meta-parser.ss b/ta6ob/nanopass/nanopass/meta-parser.ss deleted file mode 100644 index 5ed82b6..0000000 --- a/ta6ob/nanopass/nanopass/meta-parser.ss +++ /dev/null @@ -1,410 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (nanopass meta-parser) - (export make-meta-parser rhs-in-context-quasiquote meta-parse-term - make-quasiquote-transformer make-in-context-transformer - output-records->syntax parse-cata) - (import (rnrs) - (nanopass helpers) - (nanopass records) - (nanopass syntaxconvert) - (nanopass meta-syntax-dispatch)) - - (define make-ntspec-meta-parser-assoc - (lambda (tid) - (lambda (ntspec) - (cons ntspec (construct-unique-id tid "meta-parse-" (ntspec-name ntspec)))))) - - (define make-meta-parser - (lambda (desc) - (let* ([lang-name (language-name desc)] - [ntspecs (language-ntspecs desc)] - [tspecs (language-tspecs desc)] - [ntspec-meta-parsers (map (make-ntspec-meta-parser-assoc lang-name) ntspecs)]) - (define lookup-meta-parser - (lambda (ntspec) - (cond - [(assq ntspec ntspec-meta-parsers) => cdr] - [else (syntax-violation 'define-language - (format "unexpected nonterminal ~s in langauge ~s while building meta-parser, expected on of ~s" - (syntax->datum (ntspec-name ntspec)) (syntax->datum lang-name) - (map (lambda (nt) (syntax->datum (ntspec-name nt))) ntspecs)) - lang-name)]))) - (define make-meta-parse-proc - (lambda (ntspec cata?) - (define parse-field - (lambda (m level maybe?) - (cond - [(meta-name->tspec m tspecs) => - (lambda (name) - (let f ([level level] [x m]) - (if (= level 0) - #`(meta-parse-term '#,name #,x #,cata? #,maybe?) - #`(map (lambda (x) - (if (nano-dots? x) - (make-nano-dots #,(f (- level 1) - #'(nano-dots-x x))) - #,(f (- level 1) #'x))) - #,x))))] - [(meta-name->ntspec m ntspecs) => - (lambda (spec) - (with-syntax ([proc-name (lookup-meta-parser spec)]) - (let f ([level level] [x m]) - (if (= level 0) - #`(proc-name #,x #t #t #,maybe?) - #`(map (lambda (x) - (if (nano-dots? x) - (make-nano-dots #,(f (- level 1) - #'(nano-dots-x x))) - #,(f (- level 1) #'x))) - #,x)))))] - [else (syntax-violation 'define-language - (format "unrecognized meta variable ~s in language ~s, when building meta parser" m lang-name) - lang-name)]))) - (define make-term-clause - (lambda (x) - (lambda (alt) - #`[(memq (meta-var->raw-meta-var (syntax->datum #,x)) - (quote #,(tspec-meta-vars (terminal-alt-tspec alt)))) - (make-nano-meta '#,alt (list (make-nano-unquote #,x)))]))) - (define make-nonterm-unquote - (lambda (x) - (lambda (alt) - #`[(memq (meta-var->raw-meta-var (syntax->datum #,x)) - (quote #,(ntspec-meta-vars (nonterminal-alt-ntspec alt)))) - (make-nano-meta '#,alt (list (make-nano-unquote #,x)))]))) - (define make-nonterm-clause - (lambda (x maybe?) - (lambda (alt) - #`(#,(lookup-meta-parser (nonterminal-alt-ntspec alt)) #,x #f nested? maybe?)))) - (define make-pair-clause - (lambda (stx first-stx rest-stx) - (lambda (alt) - (with-syntax ([(field-var ...) (pair-alt-field-names alt)]) - (with-syntax ([(parsed-field ...) - (map parse-field #'(field-var ...) - (pair-alt-field-levels alt) - (pair-alt-field-maybes alt))] - [field-pats (datum->syntax #'* (pair-alt-pattern alt))]) - #`[#,(if (pair-alt-implicit? alt) - #`(meta-syntax-dispatch #,stx 'field-pats) - #`(and (eq? (syntax->datum #,first-stx) '#,(car (alt-syn alt))) - (meta-syntax-dispatch #,rest-stx 'field-pats))) - => (lambda (ls) - (apply - (lambda (field-var ...) - (make-nano-meta '#,alt (list parsed-field ...))) - ls))]))))) - (define separate-syn - (lambda (ls) - (let loop ([ls ls] [pair* '()] [pair-imp* '()] [term* '()] [imp* '()] [nonimp* '()]) - (if (null? ls) - (values (reverse pair*) (reverse pair-imp*) (reverse term*) (reverse imp*) (reverse nonimp*)) - (let ([v (car ls)]) - (cond - [(nonterminal-alt? v) - (if (has-implicit-alt? (nonterminal-alt-ntspec v)) - (loop (cdr ls) pair* pair-imp* term* (cons v imp*) nonimp*) - (loop (cdr ls) pair* pair-imp* term* imp* (cons v nonimp*)))] - [(terminal-alt? v) (loop (cdr ls) pair* pair-imp* (cons v term*) imp* nonimp*)] - [(pair-alt-implicit? v) (loop (cdr ls) pair* (cons v pair-imp*) term* imp* nonimp*)] - [else (loop (cdr ls) (cons v pair*) pair-imp* term* imp* nonimp*)])))))) - (let-values ([(pair-alt* pair-imp-alt* term-alt* nonterm-imp-alt* nonterm-nonimp-alt*) - (separate-syn (ntspec-alts ntspec))]) - #`(lambda (stx error? nested? maybe?) - (or (syntax-case stx (unquote) - [(unquote id) - (identifier? #'id) - (if nested? - (make-nano-unquote #'id) - (cond - #,@(map (make-term-clause #'#'id) term-alt*) - ; TODO: right now we can match the meta for this item, but we - ; cannot generate the needed nano-meta because we have no - ; alt record to put into it. (perhaps the current model is - ; just pushed as far as it can be right now, and we need to - ; rework it.) - #,@(map (make-nonterm-unquote #'#'id) nonterm-imp-alt*) - #,@(map (make-nonterm-unquote #'#'id) nonterm-nonimp-alt*) - [else #f]))] - [(unquote x) - (if nested? - (if #,cata? - (parse-cata #'x '#,(ntspec-name ntspec) maybe?) - (make-nano-unquote #'x)) - (syntax-violation #f "cata unsupported at top-level of pattern" stx))] - [_ #f]) - #,@(map (make-nonterm-clause #'stx #'maybe?) nonterm-nonimp-alt*) - (syntax-case stx () - [(a . d) - (cond - #,@(map (make-pair-clause #'stx #'#'a #'#'d) pair-alt*) - #,@(map (make-pair-clause #'stx #'#'a #'#'d) pair-imp-alt*) - [else #f])] - ; if we find something here that is not a pair, assume it should - ; be treated as a quoted constant, and will be checked appropriately - ; by the run-time constructor check - [atom (make-nano-quote #''atom)]) - #,@(map (make-nonterm-clause #'stx #'maybe?) nonterm-imp-alt*) - (and error? (syntax-violation who "unrecognized pattern or template" stx))))))) - (with-syntax ([cata? (gentemp)]) - (with-syntax ([(ntspec-id ...) (map ntspec-name ntspecs)] - [(parse-name ...) (map cdr ntspec-meta-parsers)] - [(parse-proc ...) - (map (lambda (ntspec) (make-meta-parse-proc ntspec #'cata?)) ntspecs)]) - #`(lambda (ntspec-name stx input?) - (let ([cata? input?]) - (define-who parse-name parse-proc) ... - (case ntspec-name - [(ntspec-id) (parse-name stx #t (not input?) #f)] ... - [else (syntax-violation '#,(construct-id lang-name "meta-parse-" lang-name) - (format "unexpected nonterminal ~s passed to meta parser for language ~s while meta-parsing, expected one of ~s" - ntspec-name '#,lang-name '#,(map ntspec-name ntspecs)) - stx)])))))))) - - ;; used to handle output of meta-parsers - (define meta-parse-term - (lambda (tname stx cata? maybe?) - (syntax-case stx (unquote) - [(unquote x) - (if (and cata? (not (identifier? #'x))) - (parse-cata #'x (tspec-type tname) maybe?) - (make-nano-unquote #'x))] - [(a . d) - (syntax-violation 'meta-parse-term "invalid pattern or template" stx)] - [stx - ; treat everything else we find as ,'foo because if we don't - ; `(primapp void) is interpreted as: - ; `(primapp #) - ; instead we want it to treat it as: - ; `(primapp ,'void) - ; which is how it would have to be written without this. - ; Note that we don't care what literal expression we find here - ; because at runtime it will be checked like every other element - ; used to construct the output record, and anything invalid will - ; be caught then. (If we check earlier, then it forces us to use - ; the terminal predicates at compile-time, which means that can't - ; be in the same library, and that is a bummer for other reasons, - ; so better to be flexible and let something invalid go through - ; here to be caught later.) - (make-nano-quote #''stx)]))) - - ;; used in the input meta parser to parse cata syntax - ;; TODO: support for multiple input terms. - (define parse-cata - ; should be more picky if nonterminal is specified--see 10/08/2007 NOTES - (lambda (x itype maybe?) - (define (serror) (syntax-violation 'define-pass "invalid cata syntax" x)) - (define (s0 stuff) - (syntax-case stuff () - [(: . stuff) (colon? #':) (s2 #f #'stuff)] - [(-> . stuff) (arrow? #'->) (s4 #f #f '() #'stuff)] - [(e . stuff) (s1 #'e #'stuff)] - [() (make-nano-cata itype x #f #f '() maybe?)] - [_ (serror)])) - (define (s1 e stuff) - (syntax-case stuff () - [(: . stuff) (colon? #':) (s2 e #'stuff)] - [(-> . stuff) - (and (arrow? #'->) (identifier? e)) - (s4 #f (list e) '() #'stuff)] - [(expr . stuff) - ; it is pre-mature to check for identifier here since these could be input exprs - #;(and (identifier? #'id) (identifier? e)) - (identifier? e) - (s3 #f (list #'expr e) #'stuff)] - [() (identifier? e) (make-nano-cata itype x #f #f (list e) maybe?)] - [_ (serror)])) - (define (s2 f stuff) - (syntax-case stuff () - [(-> . stuff) - (arrow? #'->) - (s4 f #f '() #'stuff)] - [(id . stuff) - (identifier? #'id) - (s3 f (list #'id) #'stuff)] - [_ (serror)])) - (define (s3 f e* stuff) - (syntax-case stuff () - [(-> . stuff) - (arrow? #'->) - (s4 f (reverse e*) '() #'stuff)] - [(e . stuff) - ; this check is premature, since these could be input expressions - #;(identifier? #'id) - (s3 f (cons #'e e*) #'stuff)] - [() - ; now we want to check if these are identifiers, because they are our return ids - (for-all identifier? e*) - (make-nano-cata itype x f #f (reverse e*) maybe?)] - [_ (serror)])) - (define (s4 f maybe-inid* routid* stuff) - (syntax-case stuff () - [(id . stuff) - (identifier? #'id) - (s4 f maybe-inid* (cons #'id routid*) #'stuff)] - [() (make-nano-cata itype x f maybe-inid* (reverse routid*) maybe?)] - [_ (serror)])) - (syntax-case x () - [(stuff ...) (s0 #'(stuff ...))]))) - - ;; used in the output of the input metaparser and in the output of - ;; define-pass - (define rhs-in-context-quasiquote - (lambda (id type omrec ometa-parser body) - (if type - (with-syntax ([quasiquote (datum->syntax id 'quasiquote)] - [in-context (datum->syntax id 'in-context)]) - #`(let-syntax ([quasiquote - '#,(make-quasiquote-transformer id type omrec ometa-parser)] - [in-context - '#,(make-in-context-transformer id omrec ometa-parser)]) - #,body)) - (with-syntax ([in-context (datum->syntax id 'in-context)]) - #`(let-syntax ([in-context - '#,(make-in-context-transformer id omrec ometa-parser)]) - #,body))))) - - ;; Done to do allow a programmer to specify what the context for - ;; their quasiquote is, incase it is different from the current - ;; expression. - ;; bug fix #8 (not sure what this refers to) - (define make-in-context-transformer - (lambda (pass-name omrec ometa-parser) - (lambda (x) - (syntax-case x () - [(_ ntname stuff ...) - (with-syntax ([quasiquote (datum->syntax pass-name 'quasiquote)]) - #`(let-syntax ([quasiquote '#,(make-quasiquote-transformer - pass-name #'ntname - omrec ometa-parser)]) - stuff ...))])))) - - ;; Used to make quasiquote transformers in the in-context transformer - ;; and in the normal right hand side transformer in do-define-pass and - ;; make-rhs - (define make-quasiquote-transformer - (lambda (pass-name ntname omrec ometa-parser) - (lambda (x) - (syntax-case x () - [(_ stuff) - ; TODO move error message like this into wherever the template doesn't match is - (output-records->syntax pass-name ntname omrec ometa-parser - (ometa-parser (syntax->datum ntname) #'stuff #f)) - #;(let ([stx #f]) - (trace-let quasiquote-transformer ([t (syntax->datum #'stuff)]) - (let ([t (output-records->syntax pass-name ntname omrec ometa-parser - (ometa-parser (syntax->datum ntname) #'stuff #f))]) - (set! stx t) - (syntax->datum t))) - stx)])))) - - ;; helper function used by the output metaparser in the meta-parsing - ;; two step - ;; TODO: - ;; - defeated (for now) at getting rid of the unnecessary bindings. still convinced this is possible and to be fixed. - ;; - we are using bound-id-union to append lists of variables that are unique by construction (unless I am misreading the code) this is pointless. - ;; - we are mapping over the field-names to find the specs for the fields. this seems waistful in a small way (building an unnecessary list) and a big way (lookup something that could be cached) - ;; - we are always building the checking version of the pair-alt constructor here, but could probably be avoiding that. - (define output-records->syntax - (lambda (pass-name ntname omrec ometa-parser rhs-rec) - (define id->msg - (lambda (id) - (cond - [(fx=? (optimize-level) 3) #f] - [(syntax->source-info id) => - (lambda (si) (format "expression ~s ~a" (syntax->datum id) si))] - [else (format "expression ~s" (syntax->datum id))]))) - (define process-nano-fields - (lambda (elt* spec* binding*) - (if (null? elt*) - (values '() '() '() binding*) - (let-values ([(elt elt-id elt-var* binding*) (process-nano-elt (car elt*) (car spec*) binding*)]) - (let-values ([(elt* elt*-id elt*-var* binding*) - (process-nano-fields (cdr elt*) (cdr spec*) binding*)]) - (values (cons elt elt*) (cons elt-id elt*-id) (bound-id-union elt-var* elt*-var*) binding*)))))) - (define process-nano-dots - (lambda (orig-elt spec binding*) - ; ought to check that each of var* are bound to proper lists - ; and that they have the same lengths - (let-values ([(elt id var* binding*) (process-nano-elt (nano-dots-x orig-elt) spec binding*)]) - (if (null? var*) - ; TODO: store original syntax object in nano-dots record and use it here - (syntax-violation (syntax->datum pass-name) - "no variables within ellipsis pattern" - (let f ([elt (nano-dots-x orig-elt)]) - (cond - [(nano-meta? elt) (map f (nano-meta-fields elt))] - [(nano-quote? elt) (cadr (nano-quote-x elt))] - [(nano-unquote? elt) (nano-unquote-x elt)] - [(nano-cata? elt) (nano-cata-syntax elt)] - [(list? elt) (map f elt)] - [else elt]))) - (values - (if (null? (cdr var*)) - (let ([t (car var*)]) - (if (eq? t elt) - t - #`(map (lambda (#,t) #,elt) #,t))) - #`(map (lambda #,var* #,elt) #,@var*)) - id var* binding*))))) - (define process-nano-list - (lambda (elt* spec binding*) - (let f ([elt* elt*] [binding* binding*]) - (if (null? elt*) - (values #''() '() '() binding*) - (let ([elt (car elt*)] [elt* (cdr elt*)]) - (if (nano-dots? elt) - (if (null? elt*) - (process-nano-dots elt spec binding*) - (let-values ([(elt elt-id elt-var* binding*) - (process-nano-dots elt spec binding*)]) - (let-values ([(elt* elt*-id* elt*-var* binding*) (f elt* binding*)]) - (values #`(append #,elt #,elt*) - (cons elt-id elt*-id*) - (bound-id-union elt-var* elt*-var*) - binding*)))) - (let-values ([(elt elt-id elt-var* binding*) (process-nano-elt elt spec binding*)]) - (let-values ([(elt* elt*-id* elt*-var* binding*) (f elt* binding*)]) - (values #`(cons #,elt #,elt*) - (cons elt-id elt*-id*) - (bound-id-union elt-var* elt*-var*) - binding*))))))))) - (define process-nano-meta - (lambda (x binding*) - (let ([prec-alt (nano-meta-alt x)]) - (let-values ([(field* id* var* binding*) - (process-nano-fields (nano-meta-fields x) - (map (lambda (x) (find-spec x omrec)) (pair-alt-field-names prec-alt)) - binding*)]) - (values - #`(#,(pair-alt-maker prec-alt) '#,pass-name #,@field* #,@(map id->msg id*)) - #f var* binding*))))) - (define process-nano-elt - (lambda (elt spec binding*) - (cond - [(nano-meta? elt) - (assert (pair-alt? (nano-meta-alt elt))) - (process-nano-meta elt binding*)] - [(nano-quote? elt) (let ([x (nano-quote-x elt)]) (values x x '() binding*))] - [(nano-unquote? elt) - (let ([x (nano-unquote-x elt)]) - (with-syntax ([expr (if (ntspec? spec) - ; TODO: when we eventually turn these processors into named entities (either - ; directly with meta define, define-syntax or some sort of property, replace - ; this with the appropriate call. In the meantime this should allow us to - ; remove some of our in-contexts - (with-syntax ([quasiquote (datum->syntax pass-name 'quasiquote)]) - #`(let-syntax ([quasiquote '#,(make-quasiquote-transformer - pass-name (spec-type spec) - omrec ometa-parser)]) - #,x)) - x)] - [tmp (car (generate-temporaries '(x)))]) - (values #'tmp x (list #'tmp) (cons #'(tmp expr) binding*))))] - [(list? elt) (process-nano-list elt spec binding*)] - [else (values elt elt '() binding*)]))) - (let-values ([(elt id var* binding*) - (process-nano-elt rhs-rec (nonterm-id->ntspec 'define-pass ntname (language-ntspecs omrec)) '())]) - #`(let #,binding* #,elt))))) diff --git a/ta6ob/nanopass/nanopass/meta-syntax-dispatch.ss b/ta6ob/nanopass/nanopass/meta-syntax-dispatch.ss deleted file mode 100644 index abb659e..0000000 --- a/ta6ob/nanopass/nanopass/meta-syntax-dispatch.ss +++ /dev/null @@ -1,145 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (nanopass meta-syntax-dispatch) - (export meta-syntax-dispatch) - (import (rnrs) - (nanopass helpers) - (nanopass records)) - - ;; (fields->patterns '(e0 e1 e2)) => (any any any) - ;; (fields->patterns '(e0 ...)) => ((each+ any () ())) - ;; (fields->patterns '(e0 ... e1)) => ((each+ any (any) ())) - ;; (fields->patterns '(e0 ... e1 e2)) => ((each+ any (any any) ())) - ;; (fields->patterns '(([x e0] ...) e1 e2 ...)) => - ;; ((each+ (any any) () ())) any (each+ (any) () ())) - - ;;; syntax-dispatch expects an expression and a pattern. If the expression - ;;; matches the pattern a list of the matching expressions for each - ;;; "any" is returned. Otherwise, #f is returned. - - ;;; The expression is matched with the pattern as follows: - - ;;; p in pattern: matches: - ;;; () empty list - ;;; any anything - ;;; (p1 . p2) pair (list) - ;;; each-any any proper list - ;;; #(each p) (p*) - ;;; #(each+ p1 (p2_1 ... p2_n) p3) (p1* (p2_n ... p2_1) . p3) - - (define match-each - (lambda (e p) - (syntax-case e () - [(a dots . d) - (and (not (ellipsis? #'a)) (not (unquote? #'a)) (ellipsis? #'dots)) - (let ([first (match #'a p '())]) - (and first - (let ([rest (match-each #'d p)]) - (and rest (cons (map make-nano-dots first) rest)))))] - [(a . d) - (and (not (ellipsis? #'a)) (not (unquote? #'a))) - (let ([first (match #'a p '())]) - (and first - (let ([rest (match-each #'d p)]) - (and rest (cons first rest)))))] - [() '()] - [else #f]))) - - (define match-each+ - (lambda (e x-pat y-pat z-pat r) - (let f ([e e]) - (syntax-case e () - [(a dots . d) - (and (not (ellipsis? #'a)) (not (unquote? #'a)) (ellipsis? #'dots)) - (let-values ([(xr* y-pat r) (f #'d)]) - (if r - (if (null? y-pat) - (let ([xr (match #'a x-pat '())]) - (if xr - (values (cons (map make-nano-dots xr) xr*) y-pat r) - (values #f #f #f))) - (values '() (cdr y-pat) (match #'a (car y-pat) r))) - (values #f #f #f)))] - [(a . d) - (and (not (ellipsis? #'a)) (not (unquote? #'a))) - (let-values ([(xr* y-pat r) (f #'d)]) - (if r - (if (null? y-pat) - (let ([xr (match #'a x-pat '())]) - (if xr - (values (cons xr xr*) y-pat r) - (values #f #f #f))) - (values '() (cdr y-pat) (match #'a (car y-pat) r))) - (values #f #f #f)))] - [_ (values '() y-pat (match e z-pat r))])))) - - (define match-each-any - (lambda (e) - (syntax-case e () - [(a dots . d) - (and (not (ellipsis? #'a)) (not (unquote? #'a)) (ellipsis? #'dots)) - (let ([l (match-each-any #'d)]) - (and l (cons (make-nano-dots #'a) l)))] - [(a . d) - (and (not (ellipsis? #'a)) (not (unquote? #'a))) - (let ([l (match-each-any #'d)]) - (and l (cons #'a l)))] - [() '()] - [_ #f]))) - - (define match-empty - (lambda (p r) - (cond - [(null? p) r] - [(eq? p 'any) (cons '() r)] - [(pair? p) (match-empty (car p) (match-empty (cdr p) r))] - [(eq? p 'each-any) (cons '() r)] - [else - (case (vector-ref p 0) - [(each) (match-empty (vector-ref p 1) r)] - [(each+) (match-empty - (vector-ref p 1) - (match-empty - (reverse (vector-ref p 2)) - (match-empty (vector-ref p 3) r)))])]))) - - (define match* - (lambda (e p r) - (cond - [(null? p) (syntax-case e () [() r] [_ #f])] - [(pair? p) - (syntax-case e () - [(a . d) (match #'a (car p) (match #'d (cdr p) r))] - [_ #f])] - [(eq? p 'each-any) - (let ([l (match-each-any e)]) (and l (cons l r)))] - [else - (case (vector-ref p 0) - [(each) - (syntax-case e () - [() (match-empty (vector-ref p 1) r)] - [_ (let ([r* (match-each e (vector-ref p 1))]) - (and r* (combine r* r)))])] - [(each+) - (let-values ([(xr* y-pat r) - (match-each+ e (vector-ref p 1) (vector-ref p 2) - (vector-ref p 3) r)]) - (and r (null? y-pat) - (if (null? xr*) - (match-empty (vector-ref p 1) r) - (combine xr* r))))])]))) - - (define match - (lambda (e p r) - (cond - [(not r) #f] - [(eq? p 'any) - (and (not (ellipsis? e)) - (not (unquote? e)) ; avoid matching unquote - (cons e r))] - [else (match* e p r)]))) - - (define meta-syntax-dispatch - (lambda (e p) - (match e p '())))) diff --git a/ta6ob/nanopass/nanopass/nano-syntax-dispatch.ss b/ta6ob/nanopass/nanopass/nano-syntax-dispatch.ss deleted file mode 100644 index 6c7a95a..0000000 --- a/ta6ob/nanopass/nanopass/nano-syntax-dispatch.ss +++ /dev/null @@ -1,99 +0,0 @@ -;;; Copyright (c) 2000-2020 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (nanopass nano-syntax-dispatch) - (export nano-syntax-dispatch) - (import (rnrs) (nanopass helpers)) - - (define-syntax match-each - (syntax-rules () - [(_ ?e p) - (let f ([e ?e]) - (cond - [(pair? e) (match (car e) p (f (cdr e)))] - [(null? e) '()] - [else #f]))])) - - (define-syntax match-remainder - (syntax-rules () - [(_ ?e () z-pat ?r) - (let loop ([e ?e] [re* '()]) - (if (pair? e) - (loop (cdr e) (cons (car e) re*)) - (values re* (match e z-pat ?r))))] - [(_ ?e (y-pat . y-pat-rest) z-pat ?r) - (let-values ([(re* r) (match-remainder ?e y-pat-rest z-pat ?r)]) - (if r - (if (null? re*) - (values #f #f) - (values (cdr re*) (match (car re*) y-pat r))) - (values #f #f)))])) - - (define-syntax match-each+ - (syntax-rules () - [(_ e x-pat y-pat z-pat ?r) - (let-values ([(re* r) (match-remainder e y-pat z-pat ?r)]) - (if r - (let loop ([re* re*] [xr* '()]) - (if (null? re*) - (values xr* r) - (let ([xr (match (car re*) x-pat '())]) - (if xr - (loop (cdr re*) (cons xr xr*)) - (values #f #f))))) - (values #f #f)))])) - - (define-syntax match-each-any - (syntax-rules () - [(_ ?e) - (let f ([e ?e]) - (cond - [(pair? e) - (let ([l (f (cdr e))]) - (and l (cons (car e) l)))] - [(null? e) '()] - [else #f]))])) - - (define-syntax match-empty - (lambda (x) - (syntax-case x (any each-any each each+) - [(_ () r) #'r] - [(_ any r) #'(cons '() r)] - [(_ (a . d) r) #'(match-empty a (match-empty d r))] - [(_ each-any r) #'(cons '() r)] - [(_ #(each p1) r) #'(match-empty p1 r)] - [(_ #(each+ p1 (p2 ...) p3) r) - (with-syntax ([(rp2 ...) (reverse #'(p2 ...))]) - #'(match-empty p1 (match-empty (rp2 ...) (match-empty p3 r))))]))) - - (define-syntax match - (syntax-rules (any) - [(_ e any r) (and r (cons e r))] - [(_ e p r) (and r (match* e p r))])) - - (define-syntax match* - (syntax-rules (any each-any each each+) - [(_ e () r) (and (null? e) r)] - [(_ e (a . d) r) (and (pair? e) (match (car e) a (match (cdr e) d r)))] - [(_ e each-any r) (let ([l (match-each-any e)]) (and l (cons l r)))] - [(_ e #(each p1) ?r) - (if (null? e) - (match-empty p1 ?r) - (let ([r* (match-each e p1)]) - (and r* (let combine ([r* r*] [r ?r]) - (if (null? (car r*)) - r - (cons (map car r*) (combine (map cdr r*) r)))))))] - [(_ e #(each+ p1 p2 p3) ?r) - (let-values ([(xr* r) (match-each+ e p1 p2 p3 ?r)]) - (and r (if (null? xr*) - (match-empty p1 r) - (let combine ([r* xr*] [r r]) - (if (null? (car r*)) - r - (cons (map car r*) (combine (map cdr r*) r)))))))])) - - (define-syntax nano-syntax-dispatch - (syntax-rules (any) - [(_ e any) (list e)] - [(_ e p) (match* e p '())]))) diff --git a/ta6ob/nanopass/nanopass/parser.ss b/ta6ob/nanopass/nanopass/parser.ss deleted file mode 100644 index fe07857..0000000 --- a/ta6ob/nanopass/nanopass/parser.ss +++ /dev/null @@ -1,172 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details -(library (nanopass parser) - (export define-parser trace-define-parser) - (import (rnrs) - (nanopass helpers) - (nanopass records) - (nanopass syntaxconvert) - (nanopass nano-syntax-dispatch)) - - (define-syntax np-parse-fail-token - (let ([sym (datum->syntax #'* (gensym "np-parse-fail-token"))]) - (make-variable-transformer - (lambda (x) - (syntax-case x () - [id (identifier? #'id) (with-syntax ([sym sym]) #''sym)] - [(set! _ e) (syntax-violation 'np-parse-fail-token "misplaced use of keyword" x)] - [(_ e ...) (syntax-violation 'np-parse-fail-token "misplaced use of keyword" x)]))))) - - (define-syntax parse-or - (syntax-rules (on-error) - [(_ (on-error ?err0)) ?err0] - [(_ (on-error ?err0) ?e0 . ?e1) - (let ([t0 ?e0]) - (if (eq? t0 np-parse-fail-token) - (parse-or (on-error ?err0) . ?e1) - t0))])) - - (define-syntax define-parser - (syntax-rules () - [(_ . rest) (x-define-parser . rest)])) - - (define-syntax trace-define-parser - (syntax-rules () - [(_ . rest) (x-define-parser trace . rest)])) - - (define-syntax x-define-parser - (lambda (x) - (define make-parser-name-assoc - (lambda (tid) - (lambda (ntspec) - (let ([name-sym (syntax->datum (ntspec-name ntspec))]) - (cons name-sym (construct-unique-id tid "parse-" name-sym)))))) - (define make-parser - (lambda (parser-name lang trace?) - (with-compile-time-environment (r) - (let ([who (if trace? 'trace-define-parser 'define-parser)] - [desc-pair (guard (c [else #f]) (r lang))]) - (unless desc-pair - (syntax-violation who - (format "unknown language ~s" (syntax->datum lang)) - parser-name x)) - (let* ([desc (car desc-pair)] - [lang-name (language-name desc)] - [ntspecs (language-ntspecs desc)] - [tspecs (language-tspecs desc)] - [parser-names (map (make-parser-name-assoc parser-name) ntspecs)]) - (define lookup-parser-name - (lambda (name) - (cond - [(assq (syntax->datum name) parser-names) => cdr] - [else (syntax-violation who - (format "unexpected nonterminal ~s in language ~s, expected one of ~s" - (syntax->datum name) (syntax->datum lang-name) - (map (lambda (nt) (syntax->datum (ntspec-name nt))) ntspecs)) - parser-name x)]))) - (define make-parse-proc - (lambda (desc tspecs ntspecs ntspec lang-name) - (define parse-field - (lambda (m level maybe?) - (cond - [(meta-name->tspec m tspecs) m] - [(meta-name->ntspec m ntspecs) => - (lambda (spec) - (with-syntax ([proc-name (lookup-parser-name (ntspec-name spec))]) - (let f ([level level] [x m]) - (if (= level 0) - (if maybe? #`(and #,x (proc-name #,x #t)) #`(proc-name #,x #t)) - #`(map (lambda (x) #,(f (- level 1) #'x)) #,x)))))] - [else (syntax-violation who - (format "unrecognized meta-variable ~s in language ~s" - (syntax->datum m) (syntax->datum lang-name)) - parser-name x)]))) - (define make-term-clause - (lambda (alt) - (with-syntax ([term-pred? - (cond - [(meta-name->tspec (alt-syn alt) tspecs) => tspec-pred] - [else (syntax-violation who - (format "unrecognized terminal meta-variable ~s in language ~s" - (syntax->datum (alt-syn alt)) (syntax->datum lang-name)) - parser-name x)])]) - #'[(term-pred? s-exp) s-exp]))) - - (define make-nonterm-clause - (lambda (alt) - (let ([spec (meta-name->ntspec (alt-syn alt) ntspecs)]) - (unless spec - (syntax-violation who - (format "unrecognized nonterminal meta-variable ~s in language ~s" - (syntax->datum (alt-syn alt)) (syntax->datum lang-name)) - parser-name x)) - (with-syntax ([proc-name (lookup-parser-name (ntspec-name spec))]) - #`(proc-name s-exp #f))))) - - (define make-pair-clause - (lambda (alt) - (with-syntax ([maker (pair-alt-maker alt)] - [(field-var ...) (pair-alt-field-names alt)]) - (with-syntax ([(parsed-field ...) - (map parse-field #'(field-var ...) - (pair-alt-field-levels alt) - (pair-alt-field-maybes alt))] - [(msg ...) (map (lambda (x) #f) #'(field-var ...))] - [field-pats (datum->syntax #'* (pair-alt-pattern alt))]) - #`[#,(if (pair-alt-implicit? alt) - #'(nano-syntax-dispatch s-exp field-pats) - (with-syntax ([key (car (alt-syn alt))]) - #'(and (eq? 'key (car s-exp)) - (nano-syntax-dispatch (cdr s-exp) field-pats)))) - => - (lambda (ls) - (apply - (lambda (field-var ...) - (let ([field-var parsed-field] ...) - (maker who field-var ... msg ...))) ls))])))) - - (partition-syn (ntspec-alts ntspec) - ([term-alt* terminal-alt?] - [nonterm-alt* nonterminal-alt?] - [pair-imp-alt* pair-alt-implicit?] - [pair-alt* otherwise]) - (partition-syn nonterm-alt* - ([nonterm-imp-alt* (lambda (alt) (has-implicit-alt? (nonterminal-alt-ntspec alt)))] - [nonterm-nonimp-alt* otherwise]) - #`(lambda (s-exp at-top-parse?) - (parse-or - (on-error - (if at-top-parse? - (error who (format "invalid syntax ~s" s-exp)) - np-parse-fail-token)) - #,@(map make-nonterm-clause nonterm-nonimp-alt*) - (if (pair? s-exp) - (cond - #,@(map make-pair-clause pair-alt*) - #,@(map make-pair-clause pair-imp-alt*) - [else np-parse-fail-token]) - (cond - #,@(map make-term-clause term-alt*) - [else np-parse-fail-token])) - #,@(map make-nonterm-clause nonterm-imp-alt*))))))) - (with-syntax ([(parse-name ...) (map cdr parser-names)] - [(parse-proc ...) - (map (lambda (ntspec) - (make-parse-proc desc tspecs ntspecs ntspec lang-name)) - ntspecs)]) - (with-syntax ([entry-proc-name (lookup-parser-name (language-entry-ntspec desc))] - [parser-name parser-name]) - (with-syntax ([(lam-exp ...) (if trace? #'(trace-lambda parser-name) #'(lambda))] - [def (if trace? #'trace-define #'define)]) - #'(define-who parser-name - (lam-exp ... (s-exp) - (def parse-name parse-proc) - ... - (entry-proc-name s-exp #t))))))))))) - (syntax-case x (trace) - [(_ parser-name lang) - (and (identifier? #'parser-name) (identifier? #'lang)) - (make-parser #'parser-name #'lang #f)] - [(_ trace parser-name lang) - (and (identifier? #'parser-name) (identifier? #'lang)) - (make-parser #'parser-name #'lang #t)])))) diff --git a/ta6ob/nanopass/nanopass/pass.ss b/ta6ob/nanopass/nanopass/pass.ss deleted file mode 100644 index e7db51f..0000000 --- a/ta6ob/nanopass/nanopass/pass.ss +++ /dev/null @@ -1,1624 +0,0 @@ -;;; Copyright (c) 2000-2018 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -;;; TODO: -;;; 1. write make-processors (based on make-processor, currently in meta-parsers -;;; 2. add else clause to processors -;;; Make sure the following are obeyed: -;;; 1. allow ir to be named -;;; 2. loosen up form of pass body -;;; 3. don't require () in pass body -;;; 4. add else clause -;;; 5. support Datum output -;;; 6. don't bind quasiquote with Datum output -;;; 7. make cata work with Datum output - -(library (nanopass pass) - (export define-pass trace-define-pass echo-define-pass with-output-language - nanopass-case pass-input-parser pass-output-unparser - pass-identifier? pass-input-language pass-output-language) - (import (rnrs) - (nanopass helpers) - (nanopass records) - (nanopass syntaxconvert) - (nanopass meta-parser) - (nanopass parser) - (nanopass unparser) - (rnrs mutable-pairs)) - - (define-syntax pass-input-parser - (lambda (x) - (syntax-case x () - [(_ pass-name) - (with-compile-time-environment (rho) - (let ([pass-info (rho #'pass-name #'define-pass)]) - (if pass-info - (let ([Lid (pass-info-input-language pass-info)]) - (if Lid - (with-syntax ([Lid Lid]) - #'(let () - (define-parser parse-Lid Lid) - parse-Lid)) - #'(lambda (x . rest) x))) - #'#f)))]))) - - (define-syntax pass-output-unparser - (lambda (x) - (syntax-case x () - [(_ pass-name) - (with-compile-time-environment (rho) - (let ([pass-info (rho #'pass-name #'define-pass)]) - (if pass-info - (let ([Lid (pass-info-output-language pass-info)]) - (if Lid - (with-syntax ([Lid Lid]) - #'(let () - (define-unparser unparse-Lid Lid) - unparse-Lid)) - #'(lambda (x . rest) x))) - #f)))]))) - - (define pass-identifier? - (lambda (id rho) - (and (rho id #'define-pass) #t))) - - (define pass-input-language - (lambda (id rho) - (let ([pass-info (rho id #'define-pass)]) - (and pass-info (pass-info-input-language pass-info))))) - - (define pass-output-language - (lambda (id rho) - (let ([pass-info (rho id #'define-pass)]) - (and pass-info (pass-info-output-language pass-info))))) - - ;; NOTE: the following is less general then the with-output-language because it does not - ;; support multiple return values. It also generates nastier code for the expander to deal - ;; with, though cp0 should clean it up. It is possible that in the long run, we'll want to - ;; have a separate pass-lambda form, or that we'll loosen up the body further to return - ;; multiple values even when they aren't specified. For now, this is moth-balled. - #;(define-syntax with-output-language - (lambda (x) - (syntax-case x () - [(k (lang type) b b* ...) - (with-syntax ([pass (datum->syntax #'k 'pass)]) - #'(let () - (define-pass pass : * () -> (lang type) () (begin b b* ...)) - (pass)))] - [(k lang b b* ...) - (with-syntax ([pass (datum->syntax #'k 'pass)]) - #'(let () - (define-pass pass : * () -> lang () (begin b b* ...)) - (pass)))]))) - - (define-syntax with-output-language - (lambda (x) - (with-compile-time-environment (r) - (syntax-case x () - [(id (lang type) b b* ...) - (let* ([olang-pair (r #'lang)] - [olang (and olang-pair (car olang-pair))] - [meta-parser (and olang-pair (cdr olang-pair))]) - (unless (language? olang) - (syntax-violation 'with-output-language "unrecognized language" #'lang)) - (unless (procedure? meta-parser) - (syntax-violation 'with-output-language "missing meta parser for language" #'lang)) - (with-syntax ([in-context (datum->syntax #'id 'in-context)] - [quasiquote (datum->syntax #'id 'quasiquote)]) - #`(let-syntax ([quasiquote '#,(make-quasiquote-transformer - #'id #'type olang - meta-parser)] - [in-context '#,(make-in-context-transformer - #'id olang - meta-parser)]) - b b* ...)))] - [(id lang b b* ...) - (let* ([olang-pair (r #'lang)] - [olang (and olang-pair (car olang-pair))] - [meta-parser (and olang-pair (cdr olang-pair))]) - (unless (language? olang) - (syntax-violation 'with-output-language "unrecognized language" #'lang)) - (unless (procedure? meta-parser) - (syntax-violation 'with-output-language "missing meta parser for language" #'lang)) - (with-syntax ([in-context (datum->syntax #'id 'in-context)]) - #`(let-syntax - ([in-context '#,(make-in-context-transformer #'id olang - meta-parser)]) - b b* ...)))])))) - - (define-syntax nanopass-case - ; (nanopass-case (lang type) id ---) rebinds id so that it always holds the - ; current ir even through cata recursion - (lambda (x) - (syntax-case x (else) - [(k (lang type) x cl ... [else b0 b1 ...]) - (identifier? #'x) - (with-syntax ([quasiquote (datum->syntax #'k 'quasiquote)]) ; if we were in a rhs, pick-up the output quasiquote - #'(let () - (define-pass p : (lang type) (x) -> * (val) - (proc : type (x) -> * (val) cl ... [else b0 b1 ...]) - (proc x)) - (p x)))] - [(k (lang type) e cl ... [else b0 b1 ...]) - #'(let ([ir e]) (k (lang type) ir cl ... [else b0 b1 ...]))] - [(k (lang type) e cl ...) - #`(k (lang type) e cl ... - [else (error 'nanopass-case - ; TODO: we were using $strip-wrap here, should be something like - ; $make-source-oops, but at least pseudo r6rs portable if possible - #,(let ([si (syntax->source-info x)]) - (if si - (format "empty else clause hit ~s ~a" - (syntax->datum x) si) - (format "empty else clause hit ~s" - (syntax->datum x)))))])]))) - - (define-syntax trace-define-pass - (lambda (x) - (define unparser - (lambda (lang) - (cond - [(eq? (syntax->datum lang) '*) #f] - [(identifier? lang) (construct-id lang "unparse-" lang)] - [else (syntax-case lang () - [(lang type) (construct-id #'lang "unparse-" #'lang)])]))) - (syntax-case x () - [(_ name ?colon ilang (id ...) ?arrow olang (xtra ...) . body) - (and (identifier? #'name) (eq? (datum ?arrow) '->) (eq? (datum ?colon) ':) - (for-all identifier? #'(id ...))) - (let ([iunparser (unparser #'ilang)] [ounparser (unparser #'olang)]) - #`(define name - (lambda (id ...) - (define-pass name ?colon ilang (id ...) ?arrow olang (xtra ...) . body) - (let ([tpass name]) - #,(if iunparser - (if ounparser - (with-syntax ([(ot xvals ...) (generate-temporaries #'(name xtra ...))] - [(tid xargs ...) (generate-temporaries #'(id ...))] - [(id id* ...) #'(id ...)]) - #`(let ([result #f]) - (trace-let name ([tid (#,iunparser id #t)] [xargs id*] ...) - (let-values ([(ot xvals ...) (tpass id id* ...)]) - (set! result (list ot xvals ...)) - (values (#,ounparser ot #t) xvals ...))) - (apply values result))) - (with-syntax ([(xvals ...) (generate-temporaries #'(xtra ...))] - [(tid xargs ...) (generate-temporaries #'(id ...))] - [(id id* ...) #'(id ...)]) - #`(trace-let name ([tid (#,iunparser id #t)] [xargs id*] ...) - (tpass id id* ...)))) - (if ounparser - (with-syntax ([(ot xvals ...) (generate-temporaries #'(name xtra ...))]) - #`(let ([result #f]) - (trace-let name ([id id] ...) - (let-values ([(ot xvals ...) (tpass id ...)]) - (set! result (list ot xvals ...)) - (values (#,ounparser ot #t) xvals ...))) - (apply values result))) - #`(trace-let name ([id id] ...) - (tpass id ...))))))))]))) - - (define-syntax define-pass - (syntax-rules () - [(_ . more) (x-define-pass . more)])) - - (define-syntax echo-define-pass - (lambda (x) - (define parse-options - (lambda (body) - (let loop ([rest body] [defn #f] [pass-options '()]) - (syntax-case rest () - [() (if defn - #`(#,pass-options #,defn) - #`(#,pass-options))] - [((definitions . defn) . rest) - (eq? (datum definitions) 'definitions) - (loop #'rest #'(definitions . defn) pass-options)] - [((?pass-options ?options ...) . rest) - (eq? (datum ?pass-options) 'pass-options) - (loop #'rest defn #'(?options ...))] - [_ (if defn - #`(#,pass-options #,defn . #,rest) - #`(#,pass-options . #,rest))])))) - (syntax-case x () - [(_ name ?colon ilang (fml ...) ?arrow olang (xval ...) . body) - (and (identifier? #'name) - (eq? (datum ?colon) ':) - (or (identifier? #'ilang) - (syntax-case #'ilang () - [(ilang itype) (and (identifier? #'ilang) (identifier? #'itype))] - [_ #f])) - (or (identifier? #'olang) - (syntax-case #'olang () - [(olang otype) (and (identifier? #'olang) (identifier? #'otype))] - [_ #f])) - (for-all identifier? #'(fml ...))) - (with-syntax ([((options ...) . body) (parse-options #'body)]) - #'(x-define-pass name ?colon ilang (fml ...) ?arrow olang (xval ...) - (pass-options (echo #t) options ...) . body))]))) - - (define-syntax x-define-pass - (lambda (x) - (define who 'define-pass) - - (define-record-type pass-options - (nongenerative) - (fields echo? generate-transformers?) - (protocol - (lambda (new) - (case-lambda - [() (new #f #t)] - [(options) - (let loop ([options options] [echo? #f] [gt? #t]) - (syntax-case options () - [() (new echo? gt?)] - [((?echo ?bool) . options) - (and (identifier? #'?echo) - (eq? (datum ?echo) 'echo) - (boolean? (datum ?bool))) - (loop #'options (datum ?bool) gt?)] - [((?generate-transformers ?bool) . options) - (and (identifier? #'?generate-transformers) - (eq? (datum ?generate-transformers) 'generate-transformers) - (boolean? (datum ?bool))) - (loop #'options echo? (datum ?bool))] - [(opt . options) (syntax-violation who "invalid pass option" x #'opt)]))])))) - - (define-record-type pass-desc - (nongenerative) - (fields name maybe-ilang maybe-olang (mutable pdesc*))) - - (define-record-type pdesc - (nongenerative) - (fields name maybe-itype fml* dflt* maybe-otype xval* body trace? echo?)) - - (define-record-type pclause - (nongenerative) - (fields lhs guard id rhs-arg* rhs-lambda - (mutable used? pclause-used? pclause-used-set!) - (mutable related-alt*)) - (protocol - (lambda (new) - (lambda (lhs guard id rhs-arg* rhs-lambda) - (new lhs guard id rhs-arg* rhs-lambda #f '()))))) - - (define make-processors - (lambda (pass-desc pass-options maybe-imeta-parser maybe-ometa-parser) - (let loop ([pdesc* (pass-desc-pdesc* pass-desc)] [processor* '()]) - (if (null? pdesc*) - (let ([pdesc* (let ([ls (pass-desc-pdesc* pass-desc)]) - (list-head ls (fx- (length ls) (length processor*))))]) - (if (null? pdesc*) - processor* - (loop pdesc* processor*))) - (loop (cdr pdesc*) - (cons (make-processor pass-desc pass-options maybe-imeta-parser maybe-ometa-parser (car pdesc*)) - processor*)))))) - - (define make-processor - (lambda (pass-desc pass-options maybe-imeta-parser maybe-ometa-parser pdesc) - (define echo-processor - (lambda (result) - (when (pdesc-echo? pdesc) - (printf "~s in pass ~s expanded into:\n" - (syntax->datum (pdesc-name pdesc)) - (syntax->datum (pass-desc-name pass-desc))) - (pretty-print (syntax->datum result))) - result)) - (with-syntax ([lambda-expr (make-processor-lambda pass-desc pass-options maybe-imeta-parser maybe-ometa-parser pdesc)] - [name (pdesc-name pdesc)]) - (echo-processor - #`(define name - #,(if (pdesc-trace? pdesc) - (let ([maybe-ilang (pass-desc-maybe-ilang pass-desc)] - [maybe-olang (pass-desc-maybe-olang pass-desc)]) - (let ([iunparser (and maybe-ilang (pdesc-maybe-itype pdesc) - (let ([ilang (language-name maybe-ilang)]) - (construct-id ilang "unparse-" ilang)))] - [ounparser (and maybe-olang (pdesc-maybe-otype pdesc) - (let ([olang (language-name maybe-olang)]) - (construct-id olang "unparse-" olang)))]) - (if iunparser - (if ounparser - (with-syntax ([(fml fml* ...) (generate-temporaries (pdesc-fml* pdesc))] - [(ot xrt ...) (generate-temporaries (cons 'ot (pdesc-xval* pdesc)))] - [(tot txrt ...) (generate-temporaries (cons 'tot (pdesc-xval* pdesc)))]) - #`(lambda (fml fml* ...) - (let ([tproc lambda-expr]) - (let ([ot #f] [xrt #f] ...) - (trace-let name ([t (#,iunparser fml #t)] [fml* fml*] ...) - (let-values ([(tot txrt ...) (tproc fml fml* ...)]) - (set! ot tot) - (set! xrt txrt) ... - (values (#,ounparser tot #t) txrt ...))) - (values ot xrt ...))))) - (with-syntax ([(fml fml* ...) (generate-temporaries (pdesc-fml* pdesc))]) - #`(lambda (fml fml* ...) - (let ([tproc lambda-expr]) - (trace-let name ([t (#,iunparser fml #t)] [fml* fml*] ...) - (tproc fml fml* ...)))))) - (if ounparser - (with-syntax ([(fml ...) (generate-temporaries (pdesc-fml* pdesc))] - [(ot xrt ...) (generate-temporaries (cons 'ot (pdesc-xval* pdesc)))] - [(tot txrt ...) (generate-temporaries (cons 'tot (pdesc-xval* pdesc)))]) - #`(lambda (fml ...) - (let ([tproc lambda-expr]) - (let ([ot #f] [xrt #f] ...) - (trace-let name ([fml fml] ...) - (let-values ([(tot txrt ...) (tproc fml ...)]) - (set! ot tot) - (set! xrt txrt) ... - (values (#,ounparser tot #t) txrt ...))) - (values ot xrt ...))))) - (with-syntax ([(fml ...) (generate-temporaries (pdesc-fml* pdesc))]) - #'(lambda (fml ...) - (let ([tproc lambda-expr]) - (trace-let name ([fml fml] ...) - (tproc fml ...))))))))) - #'lambda-expr)))))) - - (define make-processor-lambda - (lambda (pass-desc pass-options maybe-imeta-parser maybe-ometa-parser pdesc) - (let ([maybe-olang (pass-desc-maybe-olang pass-desc)] - [maybe-otype (pdesc-maybe-otype pdesc)] ; HERE - [tfml (car (generate-temporaries '(x)))] - [fml* (pdesc-fml* pdesc)]) - #`(lambda #,fml* - (let ([#,tfml #,(car fml*)]) - #,@((lambda (forms) - (if maybe-olang - (list - (rhs-in-context-quasiquote (pass-desc-name pass-desc) - maybe-otype maybe-olang maybe-ometa-parser #`(begin #,@forms))) - forms)) - (if (let ([maybe-itype (pdesc-maybe-itype pdesc)]) - (and maybe-itype (nonterm-id->ntspec? maybe-itype - (language-ntspecs - (pass-desc-maybe-ilang pass-desc))))) - (let-values ([(body defn*) - (syntax-case (pdesc-body pdesc) () - [((definitions defn* ...) . body) - (eq? (datum definitions) 'definitions) - (values #'body #'(defn* ...))] - [body (values #'body '())])]) - #`(#,@defn* - #,(make-processor-clauses pass-desc pass-options tfml maybe-imeta-parser maybe-ometa-parser pdesc body))) - (pdesc-body pdesc)))))))) - - (define make-processor-clauses - (lambda (pass-desc pass-options tfml imeta-parser maybe-ometa-parser pdesc cl*) - (let* ([itype (pdesc-maybe-itype pdesc)] ; HERE - [ilang (pass-desc-maybe-ilang pass-desc)] - [intspec* (language-ntspecs ilang)] - [maybe-otype (pdesc-maybe-otype pdesc)] ; HERE - [maybe-olang (pass-desc-maybe-olang pass-desc)] - [maybe-ontspec* (and maybe-otype (language-ntspecs maybe-olang))] - [fml* (pdesc-fml* pdesc)] - [fml tfml] - [xfml* (cdr fml*)]) - (define match-xfml* (match-extra-formals xfml*)) - (define parse-clauses - (lambda (cl*) - (define nano-meta->fml* - (lambda (cl nm) - (let f ([nrec* (nano-meta-fields nm)] [fml* '()]) - (fold-right - (rec g - (lambda (nrec fml*) - (cond - [(nano-dots? nrec) (g (nano-dots-x nrec) fml*)] - [(nano-unquote? nrec) (cons (nano-unquote-x nrec) fml*)] - [(nano-cata? nrec) - (let ([fml* (append - (let ([outid* (nano-cata-outid* nrec)]) - (if (and maybe-olang (not (null? outid*)) - (eq? (syntax->datum (car outid*)) '*)) - (cdr outid*) - outid*)) - fml*)] - [maybe-inid* (nano-cata-maybe-inid* nrec)]) - (if (and maybe-inid* - (let ([id (car maybe-inid*)]) - (and (identifier? id) - (not (memp (lambda (fml) - (free-identifier=? fml id)) - fml*))))) - (cons (car maybe-inid*) fml*) - fml*))] - [(nano-meta? nrec) (f (nano-meta-fields nrec) fml*)] - [(list? nrec) (f nrec fml*)] - [(nano-quote? nrec) (syntax-violation who (format "quoted terminals (~s) currently unsupported in match patterns" (nano-quote-x nrec)) (nano-quote-x nrec) cl)] - [else (error who "unrecognized nano-rec" nrec)]))) - fml* nrec*)))) - (define (helper cl lhs guard rhs rhs*) - (let ([nano-meta (imeta-parser itype lhs #t)]) - (let ([fml* (nano-meta->fml* cl nano-meta)]) - (unless (all-unique-identifiers? fml*) - (syntax-violation who "pattern binds one or more identifiers more then once" lhs)) - (make-pclause nano-meta guard - (datum->syntax #'* (gensym "rhs")) - fml* #`(lambda #,fml* #,rhs #,@rhs*))))) - (let f ([cl* cl*] [pclause* '()]) - (if (null? cl*) - (values (reverse pclause*) #f #f) - (syntax-case (car cl*) (guard else) - [[else rhs0 rhs1 ...] - (null? (cdr cl*)) - (values (reverse pclause*) - #'else-th #'(lambda () (begin rhs0 rhs1 ...)))] - [[lhs (guard g0 g1 ...) rhs0 rhs1 ...] - (f (cdr cl*) - (cons (helper (car cl*) #'lhs #'(and g0 g1 ...) #'rhs0 #'(rhs1 ...)) pclause*))] - [[lhs rhs0 rhs1 ...] - (f (cdr cl*) (cons (helper (car cl*) #'lhs #t #'rhs0 #'(rhs1 ...)) pclause*))] - [_ (syntax-violation (syntax->datum (pass-desc-name pass-desc)) - "invalid processor clause" (pdesc-name pdesc) (car cl*))]))))) - (module (make-clause generate-system-clauses) - (define make-system-clause - (lambda (alt) - (define genmap - (lambda (callee-pdesc level maybe? arg args) - (if (fx=? level 0) - (build-call callee-pdesc (cons arg args) maybe?) - (with-syntax ([arg arg]) - (let loop ([proc (with-syntax ([(t) (generate-temporaries '(t))]) - #`(lambda (t) #,(build-call callee-pdesc (cons #'t args) maybe?)))] - [level level]) - (with-syntax ([proc proc]) - (if (fx=? level 0) - #'(proc arg) - (loop #'(lambda (x) (map proc x)) (fx- level 1))))))))) - (define-who process-alt - (lambda (in-altrec out-altrec) - (define process-alt-field - (lambda (level maybe? fname aname ofname) - (let ([callee-pdesc - (find-proc pass-desc pass-options (pdesc-name pdesc) - (syntax->datum (spec-type (find-spec fname ilang))) - (syntax->datum (spec-type (find-spec ofname maybe-olang))) - (and (nonterminal-meta? fname intspec*) - (nonterminal-meta? ofname maybe-ontspec*)) - match-xfml* no-xval?)]) ; punting when there are return values for now - (if callee-pdesc - (genmap callee-pdesc level maybe? #`(#,aname #,fml) xfml*) - (begin - (when (or (nonterminal-meta? fname intspec*) - (nonterminal-meta? ofname maybe-ontspec*)) - (syntax-violation who - (format "unable to automatically translate ~s in ~s to ~s in ~s" - (syntax->datum fname) (syntax->datum (alt-syn in-altrec)) - (syntax->datum ofname) (syntax->datum (alt-syn out-altrec))) - (pass-desc-name pass-desc) (pdesc-name pdesc))) - #`(#,aname #,fml)))))) - (cond - [(pair-alt? in-altrec) - (let* ([in-field-level* (pair-alt-field-levels in-altrec)] - [in-field-maybe* (pair-alt-field-maybes in-altrec)] - [in-acc* (pair-alt-accessors in-altrec)] - [in-field-name* (pair-alt-field-names in-altrec)] - [out-field-name* (pair-alt-field-names out-altrec)] - [out-field* - (map process-alt-field - in-field-level* - in-field-maybe* - in-field-name* - in-acc* - out-field-name*)]) - ; always using the non-checking form here, because we are simply rebuilding; - ; TODO: terminals should be checked to be matching from the input language - ; to the output language, otherwise a check should be made here or the - ; checking version of the maker should be used. - ; AWK: this has been changed to use the checking alt, because we cannot - ; assume that other transformers will always create a valid element for - ; sub-parts of this particular maker. - ; TODO: Need to find a way to give a better error message in the checking maker - #`(#,(pair-alt-maker out-altrec) - '#,(pass-desc-name pass-desc) - #,@out-field* - #,@(map (lambda (x) (format "~s" x)) (syntax->datum in-field-name*))))] - [(terminal-alt? in-altrec) (error who "unexpected terminal alt" in-altrec)] - [(nonterminal-alt? in-altrec) (error who "unexpected nonterminal alt" in-altrec)] - [else (errorf who "unexpected alt: ~s" alt)]))) - (cond - [(nonterminal-alt? alt) - (build-subtype-call (syntax->datum (ntspec-name (nonterminal-alt-ntspec alt))))] - [(terminal-alt? alt) - (let ([xval* (pdesc-xval* pdesc)]) - (cond - [(find-proc pass-desc pass-options (pdesc-name pdesc) - (syntax->datum (tspec-type (terminal-alt-tspec alt))) - maybe-otype #f match-xfml* (length-matches xval*)) => - (lambda (callee-pdesc) (build-call callee-pdesc fml*))] - [(null? xval*) fml] - [else #`(values #,fml #,@xval*)]))] - [else - (let ([oalt (exists-alt? alt (nonterm-id->ntspec who maybe-otype maybe-ontspec*))]) - (if oalt - (let ([alt-code (process-alt alt oalt)] - [xval* (pdesc-xval* pdesc)]) - (if (null? xval*) - alt-code - #`(values #,alt-code #,@xval*))) - ; TODO: if there were no user provided clauses for this input alt, - ; we could raise a compile time error here, otherwise we have to rely - ; on the runtime error - #`(error '#,(pass-desc-name pass-desc) - (format "no matching clause for input ~s in processor ~s" - '#,(alt-syn alt) - '#,(pdesc-name pdesc)) - #,fml)))]))) - - (define gen-binding (lambda (t v) (if (eq? t v) '() (list #`(#,t #,v))))) - (define gen-t (lambda (acc) (if (identifier? acc) acc (gentemp)))) - (define gen-let1 - (lambda (t v e) - (cond [(eq? t v) e] - [(eq? e #t) #t] - [else #`(let ([#,t #,v]) #,e)]))) - ;; Note: gen-and DOES NOT actually function like and. For instance, - ;; normally (and exp #t) would return #t, but with gen-and we get exp - ;; so if exp does not evaluate to #t, the result is different. - ;; This is used in the generated results. - (define gen-and - (lambda (e1 e2) - (cond [(eq? e1 #t) e2] [(eq? e2 #t) e1] [else #`(and #,e1 #,e2)]))) - (define gen-for-all - (lambda (t v e) - (if (eq? e #t) #t #`(for-all (lambda (#,t) #,e) #,v)))) - - ; TODO: Right now process-nano-fields and its helpers are generating a predicate - ; on incoming records, and two bindings for each user specified unquote expression. - ; I think the infrastructure should be assuming that the input is well structured - ; (i.e. it should rely on the builder of the structure to do the checking and not - ; check on input, and hence should not generate the temporary bindings, or the - ; checks.) - (define process-nano-fields - (lambda (elt* acc-id aname* itype*) - (if (null? elt*) - (values #t '() '() '()) - (let-values - ([(elt-ipred elt-tbinding* elt-ibinding* elt-obinding*) - (process-nano-elt (car elt*) #`(#,(car aname*) #,acc-id) - (car itype*))] - [(rest-ipred rest-tbinding* rest-ibinding* rest-obinding*) - (process-nano-fields (cdr elt*) acc-id (cdr aname*) - (cdr itype*))]) - (values - (gen-and elt-ipred rest-ipred) - (append elt-tbinding* rest-tbinding*) - (append elt-ibinding* rest-ibinding*) - (append elt-obinding* rest-obinding*)))))) - - (define gen-mvmap - (lambda (who ids proc arg . args) - (with-syntax ([who who] [proc proc] [arg arg]) - (with-syntax ([(arg* ...) args] - [(ls2 ...) (generate-temporaries args)] - [(id ...) (generate-temporaries ids)] - [(id* ...) (generate-temporaries ids)]) - (with-syntax ([(ls ...) #'(ls1 ls2 ...)]) - #'(let ([p proc] [ls1 arg] [ls2 arg*] ...) - (unless (list? ls) (error 'who "not a proper list" ls)) - ... - (let ([n (length ls1)]) - (unless (and (= (length ls2) n) ...) - (error 'who "mismatched list lengths" ls1 ls2 ...))) - (let f ([ls1 ls1] [ls2 ls2] ...) - (if (null? ls1) - (let ([id '()] ...) (values id ...)) - (let-values ([(id ...) (p (car ls1) (car ls2) ...)] - [(id* ...) (f (cdr ls1) (cdr ls2) ...)]) - (values (cons id id*) ...)))))))))) - - (define process-nano-dots - (lambda (elt acc itype) - (let ([map-t (gentemp)]) - (let-values ([(ipred tbinding* ibinding* obinding*) - (process-nano-elt elt map-t itype)]) - (let ([ls-t (gen-t acc)]) - (values - (gen-for-all map-t acc ipred) - (gen-binding ls-t acc) - (map - (lambda (ibinding) - (syntax-case ibinding () - [(id expr) - (if (and (identifier? #'expr) (eq? map-t #'expr)) - #`(id #,ls-t) - #`(id (map (lambda (#,map-t) - #,(if (null? tbinding*) - #'expr - #`(let* #,tbinding* expr))) - #,ls-t)))])) - ibinding*) - (map - (lambda (obinding) - ;; TODO: rather than tearing apart the code we've constructed - ;; in the nano-cata case to support dotted cata, the nano-cata - ;; should be constructed to just build the correct code in the first - ;; place. - (syntax-case obinding () - [(ids (procexpr var args ...)) ;; contains expr itself - #`(ids ((let ([p (let ([p procexpr]) (lambda (m) (p m args ...)))]) - (lambda (x) - #,(cond - [(null? #'ids) #'(begin (for-each p x) (values))] - [(null? (cdr #'ids)) #'(map p x)] - [else (gen-mvmap (pass-desc-name pass-desc) - #'ids #'p #'x)]))) - var))])) - obinding*))))))) - - (define process-nano-list - (lambda (elt* acc itype) - (define helper - (lambda (elt* tail-acc) - (if (null? elt*) - (values #t '() '() '() 0 #f) - (let ([elt (car elt*)]) - (if (nano-dots? elt) - (let ([t (gen-t tail-acc)] [n (length (cdr elt*))]) - (let-values - ([(elt-ipred elt-tbinding* elt-ibinding* elt-obinding*) - (process-nano-dots (nano-dots-x elt) - (if (fx=? n 0) - t - #`(list-head #,t (fx- (length #,t) #,n))) - itype)] - [(rest-ipred rest-tbinding* rest-ibinding* - rest-obinding* i dots?) - (helper (cdr elt*) - (if (fx=? n 0) - t - #`(list-tail #,t (fx- (length #,t) #,n))))]) - (values - (gen-let1 t tail-acc - (gen-and elt-ipred rest-ipred)) - (append (gen-binding t tail-acc) - elt-tbinding* rest-tbinding*) - (append elt-ibinding* rest-ibinding*) - (append elt-obinding* rest-obinding*) - i #t))) - (let ([t (gen-t tail-acc)]) - (let-values - ([(elt-ipred elt-tbinding* elt-ibinding* elt-obinding*) - (process-nano-elt elt #`(car #,t) itype)] - [(rest-ipred rest-tbinding* rest-ibinding* - rest-obinding* i dots?) - (helper (cdr elt*) #`(cdr #,t))]) - (values - (gen-let1 t tail-acc - (gen-and elt-ipred rest-ipred)) - (append (gen-binding t tail-acc) - elt-tbinding* rest-tbinding*) - (append elt-ibinding* rest-ibinding*) - (append elt-obinding* rest-obinding*) - (fx+ i 1) dots?)))))))) - (let ([t (gen-t acc)]) - (let-values ([(ipred tbinding* ibinding* obinding* i dots?) - (helper elt* t)]) - (values - (gen-let1 t acc - (if dots? - (if (fx=? i 0) - ipred - (gen-and #`(fx>=? (length #,t) #,i) ipred)) - (gen-and #`(fx=? (length #,t) #,i) ipred))) - (append (gen-binding t acc) tbinding*) - ibinding* obinding*))))) - - (define build-meta-variable-check - (lambda (id acc itype) - (let ([spec (find-spec id ilang)]) - ;; SYMBOLIC - (cond - [(eq? (syntax->datum (spec-type spec)) (syntax->datum itype)) #t] - [(nonterm-id->ntspec? itype (language-ntspecs ilang)) => - (lambda (ntspec) - (if (subspec? spec ntspec) - #`(#,(spec-all-pred spec) #,acc) - (syntax-violation - (syntax->datum (pass-desc-name pass-desc)) - (format - "expected meta-variable for nonterminal ~s, but got" - (syntax->datum itype)) - id)))] - [(term-id->tspec? itype (language-tspecs ilang)) => - (lambda (tspec) - (syntax-violation - (syntax->datum (pass-desc-name pass-desc)) - (format - "expected meta-variable for terminal ~s, but got" - (syntax->datum itype)) - id))] - [else (syntax-violation - (syntax->datum (pass-desc-name pass-desc)) - (format - "NANOPASS INTERNAL ERROR: unable to find spec for type ~s" - (syntax->datum itype)) - id)])))) - - (define process-nano-elt - (lambda (elt acc itype) - (cond - [(nano-meta? elt) - (let ([t (gen-t acc)]) - (let-values ([(ipred tbinding* ibinding* obinding*) - (process-nano-meta elt t)]) - (values - (gen-let1 t acc - (gen-and - ;; TODO: if the nt here doesn't have any terminals, then we only - ;; need to do the tag comparison. - #;#`(eqv? (nanopass-record-tag #,t) #,(pair-alt-tag (nano-meta-alt elt))) - #`(#,(pair-alt-pred (nano-meta-alt elt)) #,t) - ipred)) - (append (gen-binding t acc) tbinding*) - ibinding* obinding*)))] - [(nano-quote? elt) - (syntax-violation (syntax->datum (pass-desc-name pass-desc)) - "quoted items are currently unsupported in patterns" - (nano-quote-x elt))] - [(nano-unquote? elt) - ; TODO: will break if two ids are same - (let ([id (nano-unquote-x elt)]) - (values - (build-meta-variable-check id acc itype) - '() - (list #`(#,id #,acc)) - '()))] - [(nano-cata? elt) - ; TODO: will break if two ids are same - ; HERE: if this is a cata for a (maybe x) field, it needs to not bother - ; parsing the #f - (let* ([maybe-inid* (nano-cata-maybe-inid* elt)] - [t (or (and maybe-inid* (car maybe-inid*)) (gentemp))] - [maybe? (nano-cata-maybe? elt)] - [itype (syntax->datum itype)]) - (let-values ([(maybe-otype outid*) - (let ([outid* (nano-cata-outid* elt)]) - (if maybe-olang - (if (null? outid*) - (values #f outid*) - (if (eq? (syntax->datum (car outid*)) '*) - (values #f (cdr outid*)) - (values - (syntax->datum - (spec-type - (find-spec (car outid*) maybe-olang))) - outid*))) - (values #f outid*)))]) - (define build-cata-call-1 - (lambda (itype maybe-otype inid* outid*) - (build-call-with-arguments - (find-proc pass-desc pass-options (nano-cata-syntax elt) itype maybe-otype #t - (lambda (id* dflt*) - (fx= itype and pdesc-otype <= otype - (define pdesc-ok? - (lambda (pdesc outid*) - (and (for-all - (lambda (req) (memp (lambda (x) (bound-identifier=? req x)) fml*)) - (list-head xfml* (fx- (length xfml*) (length (pdesc-dflt* pdesc))))) - (fx=? (length (pdesc-xval* pdesc)) - ; TODO: when we don't have an otype for a processor, we may not have an otype here - ; we should check this out to be sure. - (length (if itype (cdr outid*) outid*)))))) - (define build-cata-call-2 - (lambda (callee-pdesc t) - (build-call callee-pdesc (cons t xfml*) maybe?))) - (define build-cata-call-3 - (lambda (itype maybe-otype t outid*) - (build-call - (find-proc pass-desc pass-options (nano-cata-syntax elt) itype maybe-otype #t - match-xfml* (length-matches (if maybe-otype (cdr outid*) outid*))) - (cons t xfml*) maybe?))) - ; check number of arguments when we have a maybe - (when (and maybe? (not (fx=? (length outid*) 1))) - (syntax-violation who - "cannot use cata-morphism that returns multiple values with a maybe field" - (nano-cata-syntax elt))) - (let ([procexpr (nano-cata-procexpr elt)]) - (define build-procexpr-call - (lambda () - (let ([inid* (or maybe-inid* (list t))]) - (if maybe? - (with-syntax ([(t t* ...) (generate-temporaries inid*)]) - #`((lambda (t t* ...) (and t (#,procexpr t t* ...))) #,@inid*)) - #`(#,procexpr #,@inid*))))) - #;(unless procexpr - (unless (nonterm-id->ntspec? itype (language-ntspecs ilang)) - (syntax-violation who - "cannot use cata-morphism without specifying a procedure to call for an input terminal field" - (nano-cata-syntax elt)))) - #;(when maybe-otype - (unless (or procexpr (nonterm-id->ntspec? maybe-otype (language-ntspecs maybe-olang))) - (syntax-violation who - "cannot use cata-morphism without specifying a procedure to call for an output terminal field" - (nano-cata-syntax elt)))) - ; when we are not given a processor, make sure our itype is valid - (values - ; input predicate check - (if maybe-inid* - (build-meta-variable-check (car maybe-inid*) - acc (nano-cata-itype elt)) - #t) - ; binding of temporaries - '() - ; binding of input variable from language record - (list #`(#,t #,acc)) - ; binding of output variable(s) - (if maybe-inid* - (if procexpr - (list #`[#,outid* #,(build-procexpr-call)]) - (list #`[#,outid* #,(build-cata-call-1 itype maybe-otype maybe-inid* outid*)])) - (cond - [(and (identifier? procexpr) - (find (lambda (pdesc) - (bound-identifier=? procexpr (pdesc-name pdesc))) - (pass-desc-pdesc* pass-desc))) => - (lambda (callee-pdesc) - (if (pdesc-ok? callee-pdesc outid*) - (list #`[#,outid* #,(build-cata-call-2 callee-pdesc t)]) - (syntax-violation (syntax->datum (pass-desc-name pass-desc)) - (format "incorrect arguments for ~s in cata" (syntax->datum procexpr)) - (nano-cata-syntax elt))))] - [procexpr (list #`[#,outid* #,(build-procexpr-call)])] - [else (list #`[#,outid* #,(build-cata-call-3 itype maybe-otype t outid*)])]))))))] - [(list? elt) (process-nano-list elt acc itype)] - [else (values #`(equal? #,acc #,elt) '() '() '())]))) - - (define-who process-nano-meta - (lambda (x acc-id) - (let ([prec-alt (nano-meta-alt x)]) - (if (pair-alt? prec-alt) - (process-nano-fields (nano-meta-fields x) acc-id - (pair-alt-accessors prec-alt) - (map (lambda (x) (spec-type (find-spec x ilang))) - (pair-alt-field-names prec-alt))) - (let ([elt (car (nano-meta-fields x))]) - ; TODO: we'd like to more generally support cata for terminal and nonterminal-alt and - ; this code will have to change to support that. - (assert (nano-unquote? elt)) - (let ([id (nano-unquote-x elt)]) - (values #t '() (list #`(#,id #,acc-id)) '()))))))) - - (define find-eq-constraints - (lambda (ibinding*) - (let f ([ibinding* ibinding*] [id* '()]) - (if (null? ibinding*) - (values '() #t) - (let* ([ibinding (car ibinding*)] [id (car ibinding)]) - (if (bound-id-member? id id*) - (syntax-violation who "eq constraints are not supported" id) - #;(let-values ([(ibinding* ieqpred) - (f (cdr ibinding*) id*)]) - (let ([t (gentemp)]) - (values - #`((#,t #,(cadr ibinding)) #,@ibinding*) - (gen-and #`(nano-equal? #,t #,id) ieqpred)))) - (let-values ([(ibinding* ieqpred) - (f (cdr ibinding*) (cons id id*))]) - (values #`(#,ibinding #,@ibinding*) ieqpred)))))))) - - (define make-user-clause - (lambda (pclause k) - (let ([lhs-rec (pclause-lhs pclause)] - [guard-code (pclause-guard pclause)] - [rhs-id (pclause-id pclause)] - [rhs-arg* (pclause-rhs-arg* pclause)]) - (let-values ([(ipred tbinding* ibinding* obinding*) - (process-nano-meta lhs-rec fml)]) - (let-values ([(ibinding* ieqpred) - (find-eq-constraints ibinding*)]) - (let ([guard-code (gen-and guard-code ieqpred)] - [body-code #`(let-values #,obinding* (#,rhs-id #,@rhs-arg*))]) - (if (eq? ipred #t) - #`(let* (#,@tbinding* #,@ibinding*) - #,(if (eq? guard-code #t) - body-code - #`(if #,guard-code #,body-code #,(k)))) - (if (eq? guard-code #t) - #`(if #,ipred - (let* (#,@tbinding* #,@ibinding*) - #,body-code) - #,(k)) - #`(let ([next-th (lambda () #,(k))]) - (if #,ipred - (let* (#,@tbinding* #,@ibinding*) - (if #,guard-code #,body-code (next-th))) - (next-th))))))))))) - - (define generate-system-clauses - (lambda (alt*) - ; NB: don't use variants here to see how that impacts performance for testing purposes. - #;(let f ([alt* alt*] [rcond-cl* '()]) - (if (null? alt*) - (reverse rcond-cl*) - (let* ([alt (car alt*)] [alt (if (pair? alt) (car alt) alt)]) - (f (cdr alt*) - (cons - #`[(#,(cond - [(pair-alt? alt) (pair-alt-pred alt)] - [(terminal-alt? alt) (tspec-pred (terminal-alt-tspec alt))] - [else (ntspec-all-pred (nonterminal-alt-ntspec alt))]) - #,fml) - #,(make-clause alt '() #f)] - rcond-cl*))))) - (let f ([alt* alt*] [rcond-rec-cl* '()] [rcond-case-cl* '()]) - (if (null? alt*) - (values (reverse rcond-rec-cl*) (reverse rcond-case-cl*)) - (let* ([alt (car alt*)] [alt (if (pair? alt) (car alt) alt)]) - (with-syntax ([body (make-clause alt '() #f)]) - (cond - [(pair-alt? alt) - (f (cdr alt*) rcond-rec-cl* - (cons #`[(eqv? tag #,(pair-alt-tag alt)) body] rcond-case-cl*))] - [(terminal-alt? alt) - (let* ([tspec (terminal-alt-tspec alt)] [ttag (tspec-tag tspec)]) - (if ttag - (f (cdr alt*) rcond-rec-cl* - (cons - (if (tspec-parent? tspec) - #`[(not (fxzero? (fxand tag #,ttag))) body] - #`[(eqv? tag #,ttag) body]) - rcond-case-cl*)) - (f (cdr alt*) - (cons - #`[(#,(tspec-pred (terminal-alt-tspec alt)) #,fml) body] - rcond-rec-cl*) - rcond-case-cl*)))] - [else - (let ([ntspec (nonterminal-alt-ntspec alt)]) - (let ([maybe-term-pred? (ntspec-all-term-pred ntspec)]) - (f (cdr alt*) - (if maybe-term-pred? - (cons #`[(#,maybe-term-pred? #,fml) body] rcond-rec-cl*) - rcond-rec-cl*) - (with-syntax ([(all-tag ...) (ntspec-all-tag ntspec)]) - (cons #`[(let ([t (fxand tag #,(language-tag-mask ilang))]) (or (fx=? t all-tag) ...)) body] rcond-case-cl*)))))]))))))) - - (define build-subtype-call - (lambda (itype) - (build-call - (find-proc pass-desc pass-options (pdesc-name pdesc) itype maybe-otype #t - match-xfml* (length-matches (pdesc-xval* pdesc))) - fml*))) - - (define make-clause - (lambda (alt pclause* else-id) - (let f ([pclause* pclause*]) - (if (null? pclause*) - (cond - [else-id #`(#,else-id)] - ; TODO: Consider dropping the (not maybe-olang) and - ; building the subtype call even if there is no otype - ; for this. (Need to make sure build-subtype-call - ; can handle this appropriately (possibly also need - ; to decide if a user-supplied sub-type call with an - ; output type is okay to call).) - [(and (or (and maybe-olang maybe-otype) (not maybe-olang)) (nonterminal-alt? alt)) - (build-subtype-call (syntax->datum (ntspec-name (nonterminal-alt-ntspec alt))))] - [(and maybe-olang maybe-otype) - (make-system-clause alt)] - [else - (syntax-violation (syntax->datum (pass-desc-name pass-desc)) - (format "missing ~s clause cannot be generated with no output type" - (syntax->datum (alt-syn alt))) - (pdesc-name pdesc))]) - (let ([pclause (car pclause*)] [pclause* (cdr pclause*)]) - (pclause-used-set! pclause #t) - (make-user-clause pclause (lambda () (f pclause*))))))))) - - (define maybe-add-lambdas - (lambda (pclause* else-id else-body body) - (with-syntax ([((id* rhs-body*) ...) - (fold-left (lambda (ls pclause) - (if (pclause-used? pclause) - (cons (list (pclause-id pclause) - (pclause-rhs-lambda pclause)) - ls) - ls)) - (if else-id - (list (list else-id else-body)) - '()) - pclause*)]) - #`(let ([id* rhs-body*] ...) #,body)))) - ; note: assumes grammar nonterminal clauses form a DAG - ; TODO: reject grammars that have nonterminal clauses that don't form DAG - ; TODO: should we build this structure up front? also is there a better DS for us - ; to figure out how the various pclauses are interrelated while we process them - (define-record-type nt-alt-info - (fields alt (mutable up*) (mutable down*)) - (nongenerative) - (protocol - (lambda (new) - (lambda (alt) - (new alt '() '()))))) - - (define build-ntspec-ht - (lambda (ntspec) - (let ([ht (make-eq-hashtable)]) - (define set-cons (lambda (item ls) (if (memq item ls) ls (cons item ls)))) - (define set-append - (lambda (ls1 ls2) - (cond - [(null? ls1) ls2] - [(null? ls2) ls1] - [else (fold-left (lambda (ls item) (set-cons item ls)) ls2 ls1)]))) - (define discover-nt-alt-info! - (lambda (alt up*) - (let ([nt-alt-info (or (eq-hashtable-ref ht alt #f) - (let ([nt-alt-info (make-nt-alt-info alt)]) - (eq-hashtable-set! ht alt nt-alt-info) - nt-alt-info))]) - (nt-alt-info-up*-set! nt-alt-info - (set-append up* (nt-alt-info-up* nt-alt-info))) - (let ([up* (cons alt up*)]) - (let ([down* (fold-left - (lambda (down* alt) - (set-append (discover-nt-alt-info! alt up*) down*)) - (nt-alt-info-down* nt-alt-info) - (filter nonterminal-alt? (ntspec-alts (nonterminal-alt-ntspec alt))))]) - (nt-alt-info-down*-set! nt-alt-info down*) - (cons alt down*)))))) - (for-each (lambda (alt) (discover-nt-alt-info! alt '())) - (filter nonterminal-alt? (ntspec-alts ntspec))) - ht))) - (define build-alt-tree - (lambda (ntspec) - (let f ([alt* (ntspec-alts ntspec)] [ralt* '()]) - (if (null? alt*) - (reverse ralt*) - (f (cdr alt*) - (cons - (let ([alt (car alt*)]) - (if (nonterminal-alt? alt) - (cons alt (f (ntspec-alts (nonterminal-alt-ntspec alt)) '())) - alt)) - ralt*)))))) - (define alt-tree->s-expr - (lambda (tree) - (let f ([alt* tree]) - (if (null? alt*) - '() - (let ([alt (car alt*)]) - (if (pair? alt) - (cons (f alt) (f (cdr alt*))) - (cons (syntax->datum (alt-syn alt)) (f (cdr alt*))))))))) - (define remove-alt - (lambda (covered-alt alt*) - (let f ([alt* alt*]) - (if (null? alt*) - '() - (let ([alt (car alt*)] [alt* (cdr alt*)]) - (if (pair? alt) - (if (eq? (car alt) covered-alt) - alt* - (let ([calt* (f (cdr alt))]) - (if (null? calt*) - alt* - (cons (cons (car alt) calt*) (f alt*))))) - (if (eq? alt covered-alt) - alt* - (cons alt (f alt*))))))))) - (define handle-pclause* - (lambda (pclause* else-id alt-tree ht) - (define partition-pclause* - (lambda (alt pclause pclause*) - (if (nonterminal-alt? alt) - (let* ([nt-alt-info (eq-hashtable-ref ht alt #f)] - [this-and-down* (cons alt (nt-alt-info-down* nt-alt-info))] - [up* (nt-alt-info-up* nt-alt-info)]) - (let-values ([(matching-pclause* other-pclause*) - (partition (lambda (pclause) - (memq (nano-meta-alt (pclause-lhs pclause)) this-and-down*)) - pclause*)]) - (let ([related-pclause* (filter (lambda (pclause) - (memq (nano-meta-alt (pclause-lhs pclause)) up*)) - other-pclause*)]) - (values (cons pclause (append matching-pclause* related-pclause*)) other-pclause*)))) - (let-values ([(matching-pclause* other-pclause*) - (partition (lambda (pclause) (eq? (nano-meta-alt (pclause-lhs pclause)) alt)) - pclause*)]) - (let ([related-pclause* (filter - (let ([nt-alt* (pclause-related-alt* pclause)]) - (lambda (pclause) - (memq (nano-meta-alt (pclause-lhs pclause)) nt-alt*))) - pclause*)]) - (values (cons pclause (append matching-pclause* related-pclause*)) other-pclause*)))))) - #;(let f ([pclause* pclause*] [alt-tree alt-tree] [rcond-cl* '()]) - (if (null? pclause*) - (values (reverse rcond-cl*) alt-tree) - (let* ([pclause (car pclause*)] [alt (nano-meta-alt (pclause-lhs pclause))]) - (let-values ([(related-pclause* other-pclause*) - (partition-pclause* alt pclause (cdr pclause*))]) - (f other-pclause* - (remove-alt alt alt-tree) - (cons - #`[(#,(cond - [(pair-alt? alt) (pair-alt-pred alt)] - [(terminal-alt? alt) (tspec-pred (terminal-alt-tspec alt))] - [else (ntspec-all-pred (nonterminal-alt-ntspec alt))]) - #,fml) - #,(make-clause alt related-pclause* else-id)] - rcond-cl*)))))) - (let f ([pclause* pclause*] [alt-tree alt-tree] [rcond-rec-cl* '()] [rcond-case-cl* '()]) - (if (null? pclause*) - (values (reverse rcond-rec-cl*) (reverse rcond-case-cl*) alt-tree) - (let* ([pclause (car pclause*)] [alt (nano-meta-alt (pclause-lhs pclause))]) - (let-values ([(related-pclause* other-pclause*) - (partition-pclause* alt pclause (cdr pclause*))]) - (with-syntax ([body (make-clause alt related-pclause* else-id)]) - (cond - [(pair-alt? alt) - (f other-pclause* (remove-alt alt alt-tree) rcond-rec-cl* - (cons #`[(eqv? tag #,(pair-alt-tag alt)) body] rcond-case-cl*))] - [(terminal-alt? alt) - (let* ([tspec (terminal-alt-tspec alt)] [ttag (tspec-tag tspec)]) - (if ttag - (f other-pclause* (remove-alt alt alt-tree) rcond-rec-cl* - (cons - (if (tspec-parent? tspec) - #`[(not (fxzero? (fxand tag #,ttag))) body] - #`[(eqv? tag #,ttag) body]) - rcond-case-cl*)) - (f other-pclause* (remove-alt alt alt-tree) - (cons #`[(#,(tspec-pred (terminal-alt-tspec alt)) #,fml) body] rcond-rec-cl*) - rcond-case-cl*)))] - [else - (let ([ntspec (nonterminal-alt-ntspec alt)]) - (let ([maybe-term-pred? (ntspec-all-term-pred ntspec)]) - (f other-pclause* (remove-alt alt alt-tree) - (if maybe-term-pred? - (cons #`[(#,maybe-term-pred? #,fml) body] rcond-rec-cl*) - rcond-rec-cl*) - (with-syntax ([(all-tag ...) (ntspec-all-tag ntspec)]) - (cons #`[(let ([t (fxand tag #,(language-tag-mask ilang))]) (or (fx=? t all-tag) ...)) body] rcond-case-cl*)))))])))))))) - (define annotate-pclause*! - (lambda (pclause* ntspec ht) - (let f ([pclause* pclause*] - [alt* (filter nonterminal-alt? (ntspec-alts ntspec))] - [curr-alt #f]) - (if (or (null? alt*) (null? pclause*)) - pclause* - (let ([alt (car alt*)]) - (if (nonterminal-alt? alt) - (f (f pclause* (ntspec-alts (nonterminal-alt-ntspec alt)) alt) (cdr alt*) curr-alt) - (let-values ([(matching-pclause* other-pclause*) - (partition (lambda (pclause) - (eq? (nano-meta-alt (pclause-lhs pclause)) alt)) - pclause*)]) - (for-each - (lambda (pclause) - (pclause-related-alt*-set! pclause - (cons curr-alt (nt-alt-info-up* (eq-hashtable-ref ht curr-alt #f))))) - matching-pclause*) - (f other-pclause* (cdr alt*) curr-alt)))))))) - (let-values ([(pclause* else-id else-body) (parse-clauses cl*)]) - (let ([ntspec (nonterm-id->ntspec who itype intspec*)]) - (maybe-add-lambdas pclause* else-id else-body - (let ([ht (build-ntspec-ht ntspec)]) - (annotate-pclause*! pclause* ntspec ht) - #;(let-values ([(user-clause* alt*) - (handle-pclause* pclause* else-id - (if else-id '() (build-alt-tree ntspec)) - ht)]) - (let ([system-clause* (if else-id '() (generate-system-clauses alt*))]) - #`(cond - #,@user-clause* - #,@system-clause* - [else #,(if else-id - #`(#,else-id) - #`(error '#,(pass-desc-name pass-desc) - #,(format "unexpected ~s" (syntax->datum itype)) - #,fml))]))) - (let-values ([(user-rec-clause* user-case-clause* alt*) - (handle-pclause* pclause* else-id - (if else-id '() (build-alt-tree ntspec)) - ht)]) - (let-values ([(system-rec-clause* system-case-clause*) - (if else-id - (values - (if (ntspec-all-term-pred ntspec) - #`([(not (nanopass-record? #,fml)) (#,else-id)]) - '()) - '()) - (generate-system-clauses alt*))]) - #`(cond - #,@user-rec-clause* - #,@system-rec-clause* - [else - (let ([tag (nanopass-record-tag #,fml)]) - (cond - #,@user-case-clause* - #,@system-case-clause* - [else #,(if else-id - #`(#,else-id) - #`(error '#,(pass-desc-name pass-desc) - #,(format "unexpected ~s" (syntax->datum itype)) - #,fml))]))])))))))))) - - ; build-call, build-call-with-arguments, and find-proc need to work in - ; concert, so they are located near eachother to increase the chance that - ; we actually remember to alter both of them when the interface is - ; effected by changing one. - (module (build-call build-call-with-arguments) - (define $build-call - (lambda (fn arg* maybe?) - (with-syntax ([fn fn] [(arg* ...) arg*]) - (if maybe? - (with-syntax ([(t t* ...) (generate-temporaries #'(arg* ...))]) - #'((lambda (t t* ...) (and t (fn t t* ...))) arg* ...)) - #'(fn arg* ...))))) - (define build-args-from-fmls - (lambda (id* dflt* fml*) - (cons (car fml*) - (let ([id* (cdr id*)] [xfml* (cdr fml*)]) - (let ([n (fx- (length id*) (length dflt*))]) - #`(#,@(list-head id* n) - #,@(map (lambda (id dflt) - (if (memp (lambda (x) (bound-identifier=? id x)) xfml*) - id - dflt)) - (list-tail id* n) - dflt*))))))) - (define build-call - (case-lambda - [(callee-pdesc fml*) (build-call callee-pdesc fml* #f)] - [(callee-pdesc fml* maybe?) - ($build-call (pdesc-name callee-pdesc) - (build-args-from-fmls (pdesc-fml* callee-pdesc) (pdesc-dflt* callee-pdesc) fml*) - maybe?)])) - (define build-full-args-from-args - (lambda (callee-fml* callee-init* arg*) - (let f ([required-cnt (fx- (length callee-fml*) (length callee-init*))] - [callee-fml* callee-fml*] [callee-init* callee-init*] [arg* arg*]) - (cond - [(null? callee-fml*) '()] - [(and (fxzero? required-cnt) (null? arg*)) - (cons (car callee-init*) - (f required-cnt (cdr callee-fml*) (cdr callee-init*) arg*))] - [(fxzero? required-cnt) - (cons (car arg*) - (f required-cnt (cdr callee-fml*) (cdr callee-init*) (cdr arg*)))] - [else (cons (car arg*) - (f (fx- required-cnt 1) (cdr callee-fml*) callee-init* (cdr arg*)))])))) - (define build-call-with-arguments - (lambda (callee-pdesc arg* maybe?) - ($build-call (pdesc-name callee-pdesc) - (build-full-args-from-args (pdesc-fml* callee-pdesc) (pdesc-dflt* callee-pdesc) arg*) - maybe?)))) - - ;; matcher helpers for use with find-proc. - (define match-extra-formals - (lambda (xfml*) - (lambda (id* dflt*) - (for-all - (lambda (req) - (memp (lambda (x) (bound-identifier=? req x)) xfml*)) - (list-head id* (fx- (length id*) (length dflt*))))))) - - (define no-xval? null?) - (define length-matches - (lambda (expected-xval*) - (lambda (xval*) - (fx=? (length xval*) (length expected-xval*))))) - - (define find-proc - ; will never be asked to find a proc without an itype, so itype is never #f - (lambda (pass-desc pass-options src-stx itype maybe-otype try-to-generate? xfmls-ok? xvals-ok?) - (define (try-to-generate) - (if (pass-options-generate-transformers? pass-options) - (begin - (unless (and (xfmls-ok? '() '()) (xvals-ok? '())) - (syntax-violation who - (format "cannot find a transformer from ~s to ~s, \ - and cannot generate one with extra formals or return values" - itype maybe-otype) - (pass-desc-name pass-desc) src-stx)) - (unless (and (nonterm-id->ntspec? itype (language-ntspecs (pass-desc-maybe-ilang pass-desc))) - (nonterm-id->ntspec? maybe-otype (language-ntspecs (pass-desc-maybe-olang pass-desc)))) - (syntax-violation who - (format "cannot find a transformer from ~s to ~s, \ - and cannot generate one when either the input or output type is a terminal" - itype maybe-otype) - (pass-desc-name pass-desc) src-stx)) - (let ([pdesc (make-pdesc (datum->syntax #'* (gensym (format "~s->~s" itype maybe-otype))) - itype (list #'ir) '() maybe-otype '() '() #f #f)]) - (pass-desc-pdesc*-set! pass-desc - (cons pdesc (pass-desc-pdesc* pass-desc))) - pdesc)) - (syntax-violation who - (format "cannot find a transformer from ~s to ~s that matches the expected signature" - itype maybe-otype) - (pass-desc-name pass-desc) src-stx))) - (define find-subspecs - (lambda (ospec sub-ospec*) - (if (ntspec? ospec) - (let f ([alt* (ntspec-alts ospec)] [sub-ospec* sub-ospec*]) - (if (null? alt*) - sub-ospec* - (let ([alt (car alt*)]) - (cond - [(nonterminal-alt? alt) - (f (cdr alt*) (cons (nonterminal-alt-ntspec alt) sub-ospec*))] - [(terminal-alt? alt) - (f (cdr alt*) (cons (terminal-alt-tspec alt) sub-ospec*))] - [else (f (cdr alt*) sub-ospec*)])))) - sub-ospec*))) - (define find-candidate - (lambda (maybe-otype) - (let loop ([pdesc* (pass-desc-pdesc* pass-desc)] [candidate #f]) - (if (null? pdesc*) - candidate - (loop (cdr pdesc*) - (let ([pdesc (car pdesc*)]) - (if (and (eq? (pdesc-maybe-itype pdesc) itype) ; HERE - (eq? (pdesc-maybe-otype pdesc) maybe-otype) ; HERE - (xfmls-ok? (cdr (pdesc-fml* pdesc)) (pdesc-dflt* pdesc)) - (xvals-ok? (pdesc-xval* pdesc))) - (if candidate - (syntax-violation who - (format "ambiguous target for implicit processor call from ~s to ~s" - itype maybe-otype) - (pass-desc-name pass-desc) src-stx) - pdesc) - candidate))))))) - (when (identifier? maybe-otype) - (syntax-violation 'find-proc "expected symbol otype, got identifier" maybe-otype)) - ; doing a breadth-first search of maybe-otype and its subtypes - ; could go up to parent itype(s) on itype as well - #;(printf "entering with itype ~s to otype ~s in ~s\n" itype maybe-otype - (map (lambda (x) (list (syntax->datum (pdesc-name x)) ': (pdesc-maybe-itype x) '-> (pdesc-maybe-otype x))) - (pass-desc-pdesc* pass-desc))) - (if maybe-otype - (let ospec-loop ([ospec* (list (id->spec maybe-otype (pass-desc-maybe-olang pass-desc)))] - [sub-ospec* '()]) - (if (null? ospec*) - (if (null? sub-ospec*) - (and try-to-generate? (try-to-generate)) - (ospec-loop sub-ospec* '())) - (or (find-candidate (syntax->datum (spec-type (car ospec*)))) - (ospec-loop (cdr ospec*) (find-subspecs (car ospec*) sub-ospec*))))) - (or (find-candidate #f) - (syntax-violation who - (format "cannot find a processor that accepts input type ~s and no output type" itype) - (pass-desc-name pass-desc) src-stx))))) - - (define parse-proc - (lambda (pass-name ilang olang) - (lambda (x) - (let loop ([x x] [trace? #f] [echo? #f]) - (syntax-case x () - [(?echo ?not-colon . rest) - (and (eq? (datum ?echo) 'echo) (not (eq? (datum ?not-colon) ':))) - (loop #'(?not-colon . rest) trace? #t)] - [(?trace ?not-colon . rest) - (and (eq? (datum ?trace) 'trace) (not (eq? (datum ?not-colon) ':))) - (loop #'(?not-colon . rest) #t echo?)] - [(proc-name ?colon itype (arg ...) ?arrow otype (rv ...) body ...) - (let ([squawk (lambda (msg what) (syntax-violation (syntax->datum pass-name) msg what))]) - (unless (identifier? #'proc-name) (squawk "invalid processor name" #'proc-name)) - (unless (eq? (datum ?colon) ':) (squawk "expected colon" #'?colon)) - (let ([maybe-itype - (syntax-case #'itype () - [* (eq? (datum *) '*) #f] - [id - (identifier? #'id) - (if ilang - (if (or (nonterm-id->ntspec? #'id (language-ntspecs ilang)) - (term-id->tspec? #'id (language-tspecs ilang))) - (syntax->datum #'id) - (squawk "unrecognized input non-terminal" #'id)) - (squawk "specified input non-terminal without input language" #'id))] - [_ (squawk "invalid input type specifier" #'itype)])]) - (let ([arg* #'(arg ...)]) - (when maybe-itype - (when (null? arg*) (squawk "expected non-empty argument list" arg*)) - (unless (identifier? (car arg*)) (squawk "invalid first argument" (car arg*)))) - (let-values ([(fml* init*) - (let f ([arg* arg*] [dflt? #f]) - (if (null? arg*) - (values '() '()) - (syntax-case (car arg*) () - [id - (identifier? #'id) - (if dflt? - (squawk "unexpected non-default formal after start of default formals" #'id) - (let-values ([(fml* init*) (f (cdr arg*) #f)]) - (values (cons #'id fml*) init*)))] - [[id expr] - (identifier? #'id) - (let-values ([(fml* init*) (f (cdr arg*) #t)]) - (values (cons #'id fml*) (cons #'expr init*)))] - [arg (squawk "invalid argument specifier" #'arg)])))]) - (unless (eq? (datum ?arrow) '->) (squawk "expected arrow" #'?arrow)) - (let ([maybe-otype (syntax-case #'otype () - [* (eq? (datum *) '*) #f] - [id - (identifier? #'id) - (if olang - (if (or (nonterm-id->ntspec? #'id (language-ntspecs olang)) - (term-id->tspec? #'id (language-tspecs olang))) - (syntax->datum #'id) - (squawk "unrecognized output non-terminal" #'id)) - (squawk "specified output non-terminal without output language" #'id))] - [_ (squawk "invalid output-type specifier" #'otype)])]) - (make-pdesc #'proc-name maybe-itype fml* init* - maybe-otype #'(rv ...) #'(body ...) trace? echo?))))))]))))) - - (define lookup-lang - (lambda (pass-name r maybe-name) - (if maybe-name - (let* ([olang-pair (r maybe-name)] - [lang (and olang-pair (car olang-pair))] - [meta-parser (and olang-pair (cdr olang-pair))]) - (unless (language? lang) - (syntax-violation (syntax->datum pass-name) "unrecognized language" maybe-name)) - (unless (procedure? meta-parser) - (syntax-violation (syntax->datum pass-name) "missing meta parser for language" maybe-name)) - (values lang meta-parser)) - (values #f #f)))) - - (define build-checked-body - (lambda (pass-desc pass-options maybe-fml extra-fml* xval* maybe-itype maybe-otype maybe-ometa-parser maybe-body) - (define generate-output-check - (lambda (type x ntspec*) - ((lambda (ls) (if (null? (cdr ls)) (car ls) #`(or #,@ls))) - (let f ([ntspec (nonterm-id->ntspec who type ntspec*)] [test* '()]) - (cons #`(#,(ntspec-all-pred ntspec) #,x) - (fold-left - (lambda (test* alt) - (if (nonterminal-alt? alt) - (f (nonterminal-alt-ntspec alt) test*) - test*)) - test* (ntspec-alts ntspec))))))) - (define generate-body - (lambda (maybe-olang maybe-otype) - (cond - [(and maybe-body maybe-otype) - (rhs-in-context-quasiquote (pass-desc-name pass-desc) maybe-otype - maybe-olang maybe-ometa-parser maybe-body)] - [maybe-body] - [else - (unless (null? xval*) - (syntax-violation who "cannot auto-generate body for pass with extra return values" - (pass-desc-name pass-desc))) - (let ([ilang (pass-desc-maybe-ilang pass-desc)]) - (unless ilang - (syntax-violation who "cannot auto-generate body without input language" - (pass-desc-name pass-desc))) - (let ([itype (or maybe-itype (syntax->datum (language-entry-ntspec ilang)))]) - (let ([pdesc (find-proc pass-desc pass-options (pass-desc-name pass-desc) itype maybe-otype #t - (match-extra-formals extra-fml*) - ; punting when there are return values for now --- matches rejecting auto generation when xval* is not null - no-xval?)]) - (let ([rv* (pdesc-xval* pdesc)]) - (if (null? rv*) - (build-call pdesc (cons maybe-fml extra-fml*)) - #`(let-values ([(result #,@(generate-temporaries rv*)) - #,(build-call pdesc (cons maybe-fml extra-fml*))]) - result))))))]))) - (let ([olang (pass-desc-maybe-olang pass-desc)]) - (if olang - (let ([otype (or maybe-otype (syntax->datum (language-entry-ntspec olang)))]) - (with-syntax ([checked-body - #`(unless #,(generate-output-check otype #'x (language-ntspecs olang)) - (error '#,(pass-desc-name pass-desc) - (format "expected ~s but got ~s" '#,(datum->syntax #'* otype) x)))]) - (if (null? xval*) - #`(let ([x #,(generate-body olang otype)]) - checked-body - x) - (with-syntax ([(res* ...) (generate-temporaries xval*)]) - #`(let-values ([(x res* ...) #,(generate-body olang otype)]) - checked-body - (values x res* ...)))))) - (generate-body #f #f))))) - - (define do-define-pass - (lambda (pass-name pass-options maybe-iname maybe-itype fml* maybe-oname maybe-otype xval* defn* p* maybe-body) - (define echo-pass - (lambda (x) - (when (pass-options-echo? pass-options) - (printf "pass ~s expanded into:\n" (syntax->datum pass-name)) - (pretty-print (syntax->datum x)) - (newline)) - x)) - (with-compile-time-environment (r) - #;(unless (and maybe-iname (not (null? fml*))) - (syntax-violation who "can't yet handle \"*\" iname" pass-name)) - (let-values ([(maybe-ilang maybe-imeta-parser) (lookup-lang pass-name r maybe-iname)] - [(maybe-olang maybe-ometa-parser) (lookup-lang pass-name r maybe-oname)]) - (when (and maybe-itype (not (nonterm-id->ntspec? maybe-itype (language-ntspecs maybe-ilang)))) - (syntax-violation who "unrecognized pass input non-terminal" pass-name maybe-itype)) - (when (and maybe-otype (not (nonterm-id->ntspec? maybe-otype (language-ntspecs maybe-olang)))) - (syntax-violation who "unrecognized pass output non-terminal" pass-name maybe-otype)) - (let* ([pdesc* (map (parse-proc pass-name maybe-ilang maybe-olang) p*)] - [pass-desc (make-pass-desc pass-name maybe-ilang maybe-olang pdesc*)] - [body (build-checked-body pass-desc pass-options (and (pair? fml*) (car fml*)) (if (pair? fml*) (cdr fml*) '()) - xval* (syntax->datum maybe-itype) - (syntax->datum maybe-otype) maybe-ometa-parser maybe-body)]) - (echo-pass - (with-syntax ([who (datum->syntax pass-name 'who)]) - #`(begin - (define #,pass-name - (lambda #,fml* - (define who '#,pass-name) - (define-nanopass-record) - #,@defn* - #,@(make-processors pass-desc pass-options maybe-imeta-parser maybe-ometa-parser) - #,body)) - (define-property #,pass-name define-pass - (make-pass-info - #,(and maybe-iname #`#'#,maybe-iname) - #,(and maybe-oname #`#'#,maybe-oname))))))))))) - - (syntax-case x () - [(_ pass-name ?colon iname (fml ...) ?arrow oname (xval ...) stuff ...) - (let ([squawk (lambda (msg what) (syntax-violation who msg x what))]) - (unless (identifier? #'pass-name) (squawk "invalid pass name" #'pass-name)) - (unless (eq? (datum ?colon) ':) (squawk "expected colon" #'?colon)) - (let-values ([(maybe-iname maybe-itype) - (syntax-case #'iname () - [* (eq? (datum *) '*) (values #f #f)] - [iname (identifier? #'iname) (values #'iname #f)] - [(iname itype) - (and (identifier? #'iname) (identifier? #'itype)) - (values #'iname #'itype)] - [_ (squawk "invalid input language specifier" #'iname)])]) - (let ([fml* #'(fml ...)]) - (unless (for-all identifier? fml*) (squawk "expected list of identifiers" fml*)) - (when (and maybe-iname (null? fml*)) (squawk "expected non-empty list of formals" fml*)) - (unless (eq? (datum ?arrow) '->) (squawk "expected arrow" #'?arrow)) - (let-values ([(maybe-oname maybe-otype) - (syntax-case #'oname () - [* (eq? (datum *) '*) (values #f #f)] - [id (identifier? #'id) (values #'id #f)] - [(oname otype) - (and (identifier? #'oname) (identifier? #'otype)) - (values #'oname #'otype)] - [_ (squawk "invalid output-language specifier" #'oname)])]) - (define (s1 stuff* defn* processor* pass-options) - (if (null? stuff*) - (s2 defn* processor* #f pass-options) - (let ([stuff (car stuff*)]) - (if (let processor? ([stuff stuff] [mcount 0]) - (syntax-case stuff () - [(pname ?colon itype (fml ...) ?arrow otype (xval ...) . more) - (and (eq? (datum ?colon) ':) - (eq? (datum ?arrow) '->) - (identifier? #'itype) - (identifier? #'otype) - (for-all (lambda (fml) - (or (identifier? fml) - (syntax-case fml () - [[fml exp-val] (identifier? #'fml)]))) - #'(fml ...)) - #t)] - [(?modifier ?not-colon . more) - (and (memq (datum ?modifier) '(trace echo)) - (not (eq? (datum ?not-colon) ':)) - (< mcount 2)) - (processor? #'(?not-colon . more) (fx+ mcount 1))] - [_ #f])) - (s1 (cdr stuff*) defn* (cons stuff processor*) pass-options) - (s2 defn* processor* #`(begin #,@stuff*) pass-options))))) - (define (s2 defn* processor* maybe-body pass-options) - (do-define-pass #'pass-name pass-options maybe-iname maybe-itype fml* - maybe-oname maybe-otype #'(xval ...) defn* (reverse processor*) maybe-body)) - (let s0 ([stuff* #'(stuff ...)] [defn* '()] [pass-options #f]) - (if (null? stuff*) - (s1 stuff* defn* '() (or pass-options (make-pass-options))) - (syntax-case (car stuff*) () - [(definitions defn ...) - (eq? (datum definitions) 'definitions) - (s0 (cdr stuff*) #'(defn ...) pass-options)] - [(?pass-options . ?options) - (eq? (datum ?pass-options) 'pass-options) - (s0 (cdr stuff*) defn* (make-pass-options #'?options))] - [_ (s1 stuff* defn* '() (or pass-options (make-pass-options)))])))))))] - [(_ . rest) (syntax-violation who "invalid syntax" #'(define-pass . rest))])))) diff --git a/ta6ob/nanopass/nanopass/prefix-matcher.ss b/ta6ob/nanopass/nanopass/prefix-matcher.ss deleted file mode 100644 index d94b2cf..0000000 --- a/ta6ob/nanopass/nanopass/prefix-matcher.ss +++ /dev/null @@ -1,98 +0,0 @@ -(library (nanopass prefix-matcher) - (export empty-prefix-tree insert-prefix match-prefix) - (import (chezscheme)) - - (define-record-type prefix-node - (nongenerative) - (sealed #t) - (fields str start end result next*)) - - (define substring=? - (lambda (str0 str1 s e) - (let loop ([i s]) - (or (fx= i e) - (and (char=? (string-ref str0 i) (string-ref str1 i)) - (loop (fx+ i 1))))))) - - (define empty-prefix-tree (lambda () '())) - - (define match-prefix - (case-lambda - [(pt str) (match-prefix pt str (lambda (str s e) #t))] - [(pt str ok-suffix?) - (let ([len (string-length str)]) - (let loop ([pt pt] [curr-result #f] [curr-end 0]) - (if (null? pt) - (and curr-result (ok-suffix? (substring str curr-end len)) curr-result) - (let ([node (car pt)] [pt (cdr pt)]) - (let ([end (prefix-node-end node)]) - (if (fx> end len) - (loop pt curr-result curr-end) - (let ([node-str (prefix-node-str node)]) - (if (substring=? node-str str (prefix-node-start node) end) - (cond - [(fx= end len) - (or (prefix-node-result node) - (and curr-result (ok-suffix? (substring str curr-end len)) curr-result))] - [(prefix-node-result node) - (loop (prefix-node-next* node) (prefix-node-result node) end)] - [else (loop (prefix-node-next* node) curr-result curr-end)]) - (loop pt curr-result curr-end)))))))))])) - - ;; NB: the following assumes that no one will be mutating the strings put into this tree - (define insert-prefix - (lambda (pt str result) - (let ([len (string-length str)]) - (let f ([pt pt] [start 0]) - (if (null? pt) - (list (make-prefix-node str start len result '())) - (let* ([node (car pt)] [pt (cdr pt)] [node-str (prefix-node-str node)]) - (when (string=? node-str str) (errorf 'add-prefix "prefix already in tree")) - (let loop ([offset start]) - (if (fx= offset len) - (cons - (make-prefix-node node-str start offset #f - (cons (make-prefix-node str offset len result '()) - (make-prefix-node node-str offset (prefix-node-end node) - (prefix-node-result node) (prefix-node-next* node)))) - pt) - (let ([end (prefix-node-end node)]) - (cond - [(fx= offset end) - (cons (make-prefix-node node-str start (prefix-node-end node) - (prefix-node-result node) - (f (prefix-node-next* node) offset)) - pt)] - [(char=? (string-ref str offset) (string-ref node-str offset)) (loop (fx+ offset 1))] - [(fx= offset start) (cons node (f pt start))] - [else (cons (make-prefix-node node-str start offset #f - (list (make-prefix-node node-str offset end - (prefix-node-result node) (prefix-node-next* node)) - (make-prefix-node str offset len result '()))) - pt)])))))))))) - (define remove-prefix - (lambda (pt str) - #| - (let ([len (string-length str)]) - (let f ([pt pt]) - (if (null? pt) - pt - (let ([node (car pt)] [pt (cdr pt)]) - (let ([end (prefix-node-end node)]) - (if (fx> end len) - pt - (let ([node-str (prefix-node-str node)]) - (if (substring=? node-str str (prefix-node-str node) end) - (if (fx= end len) - (let ([next* (prefix-node-next* node)]) - (cond - [(null? next*) pt] - [(fx= (length next*) 1) - (let ([next (car next*)]) - (make-prefix-node (prefix-node-str next) (prefix-node-start node) - (prefix-node-end next) (prefix-node-result next) (prefix-node-next* next)))] - [else (make-prefix-node (prefix-node-str (car next*)) - (prefix-node-start node) (prefix-node - |# - (errorf 'remove-prefix "not yet implemented"))) - ) diff --git a/ta6ob/nanopass/nanopass/records.ss b/ta6ob/nanopass/nanopass/records.ss deleted file mode 100644 index fb997a3..0000000 --- a/ta6ob/nanopass/nanopass/records.ss +++ /dev/null @@ -1,804 +0,0 @@ -;;; Copyright (c) 2000-2018 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (nanopass records) - (export find-spec nonterminal-meta? - nonterm-id->ntspec? nonterm-id->ntspec id->spec term-id->tspec? - - meta-name->tspec meta-name->ntspec - - make-nano-dots nano-dots? nano-dots-x - - make-nano-quote nano-quote? nano-quote-x - - make-nano-unquote nano-unquote? nano-unquote-x - - make-nano-meta nano-meta? nano-meta-alt nano-meta-fields - - make-nano-cata nano-cata? nano-cata-itype nano-cata-syntax - nano-cata-procexpr nano-cata-maybe-inid* nano-cata-outid* - nano-cata-maybe? - - make-language language? language-name language-entry-ntspec - language-tspecs language-ntspecs - language-tag-mask language-nongenerative-id - - make-tspec tspec-meta-vars tspec-type tspec-pred - tspec-handler tspec? tspec-tag tspec-parent? - - ntspec? make-ntspec ntspec-name ntspec-meta-vars - ntspec-alts ntspec-pred ntspec-all-pred - ntspec-tag ntspec-all-tag ntspec-all-term-pred - - alt? alt-syn alt-pretty alt-pretty-procedure? - make-pair-alt pair-alt? pair-alt-pattern - pair-alt-field-names pair-alt-field-levels pair-alt-field-maybes - pair-alt-accessors pair-alt-implicit? pair-alt-pred pair-alt-maker - pair-alt-tag - make-terminal-alt terminal-alt? terminal-alt-tspec - make-nonterminal-alt nonterminal-alt? nonterminal-alt-ntspec - - has-implicit-alt? - spec-all-pred - spec-type - - subspec? - - annotate-language! - language->lang-records - language->lang-predicates - - define-nanopass-record - - #;define-nanopass-record-types - - exists-alt? - - make-pass-info pass-info? pass-info-input-language - pass-info-output-language) - (import (rnrs) (nanopass helpers) (nanopass syntaxconvert)) - - (define-nanopass-record) - - #;(define-syntax *nanopass-record-tag* (lambda (x) (syntax-violation #f "invalid syntax" x))) - #;(define-syntax *nanopass-record-is-parent* (lambda (x) (syntax-violation #f "invalid syntax" x))) - #;(define-syntax *nanopass-record-bits* (lambda (x) (syntax-violation #f "invalid syntax" x))) - - #;(define-syntax define-nanopass-record-types - (lambda (x) - (define-record-type np-rec - (fields name maker pred parent sealed? fields protocol (mutable tag) (mutable bp) (mutable c*)) - (nongenerative) - (protocol - (lambda (new) - (lambda (name maker pred parent fields protocol) - (new name maker pred parent (syntax->datum parent) fields protocol #f #f '()))))) - (define high-bit (fx- (fixnum-width) 2)) ; need to figure out how to use the high bit - (define figure-bits-out! - (lambda (np-rec*) - ; NB. currently does not support a hierarchy, but could be extended - ; NB. to support this by having the first bit in the tag indicate the - ; NB. grand parent and a following specifier bit for the parent and finally - ; NB. a count for the children. (partition, will become more compilcated) - (let-values ([(c* p*) (partition np-rec-sealed? np-rec*)]) - (let-values ([(env bits) - (let f ([p* p*] [bp high-bit] [env '()]) - (if (null? p*) - (values env (fx- high-bit bp)) - (let ([p (car p*)]) - (np-rec-tag-set! p (fxarithmetic-shift-left 1 bp)) - (np-rec-bp-set! p bp) - (f (cdr p*) (fx- bp 1) - (cons (cons (syntax->datum (np-rec-name p)) p) env)))))]) - (for-each - (lambda (c) - (cond - [(assq (syntax->datum (np-rec-parent c)) env) => - (lambda (a) (let ([p (cdr a)]) (np-rec-c*-set! p (cons c (np-rec-c* p)))))] - [else (syntax-violation 'define-nanopass-record-types - "nanopass record parent not named in this form" - (np-rec-parent c))])) - c*) - (for-each - (lambda (p) - (let ([parent-tag (np-rec-tag p)]) - (let f ([c* c*] [count 0]) - (if (null? c*) - (fx- (fxfirst-bit-set (fxreverse-bit-field count 0 (fx- (fixnum-width) 1))) bits) - (let ([count (fx+ count 1)]) - (let ([shift-cnt (f (cdr c*) count)] [c (car c*)]) - (np-rec-tag-set! c (fxior (fxarithmetic-shift-left count shift-cnt) parent-tag)) - shift-cnt)))))) - p*) - bits)))) - (syntax-case x () - [(_ [name maker pred rent flds pfunc] ...) - (let ([np-rec* (map make-np-rec #'(name ...) #'(maker ...) #'(pred ...) #'(rent ...) #'(flds ...) #'(pfunc ...))]) - (let ([bits (figure-bits-out! np-rec*)]) - #`(begin - (define-property nanopass-record *nanopass-record-bits* #,bits) - #,@(if (null? np-rec*) - '() - (let f ([np-rec (car np-rec*)] [np-rec* (cdr np-rec*)]) - (let ([e #`(begin - (define-record-type (#,(np-rec-name np-rec) #,(np-rec-maker np-rec) #,(np-rec-pred np-rec)) - (nongenerative) - #,@(if (np-rec-sealed? np-rec) - #`((sealed #t) (parent #,(np-rec-parent np-rec))) - #`((parent nanopass-record))) - (fields #,@(np-rec-fields np-rec)) - #,(if (np-rec-sealed? np-rec) - #`(protocol - (let ([p #,(np-rec-protocol np-rec)]) - (lambda (pargs->new) - (lambda args - (apply (p pargs->new) #,(np-rec-tag np-rec) args))))) - #`(protocol #,(np-rec-protocol np-rec)))) - (define-property #,(np-rec-name np-rec) *nanopass-record-tag* #,(np-rec-tag np-rec)) - #,@(if (np-rec-bp np-rec) - #`((define-property #,(np-rec-name np-rec) *nanopass-record-is-parent* #,(np-rec-tag np-rec))) - #'()))]) - (if (null? np-rec*) - (list e) - (cons e (f (car np-rec*) (cdr np-rec*))))))))))]))) - - (define-record-type language - (fields name entry-ntspec tspecs ntspecs (mutable rtd) (mutable rcd) (mutable tag-mask) nongenerative-id) - (nongenerative) - (protocol - (lambda (new) - (lambda (name entry-ntspec tspecs ntspecs nongen-id) - (define check-meta! - (let () - (define (spec-meta-vars spec) (if (ntspec? spec) (ntspec-meta-vars spec) (tspec-meta-vars spec))) - (define (spec-name spec) (if (ntspec? spec) (ntspec-name spec) (tspec-type spec))) - (lambda (lang-name tspecs ntspecs) - (let f ([specs (append tspecs ntspecs)]) - (unless (null? specs) - (let ([test-spec (car specs)]) - (for-each - (lambda (mv) - (let ([mv-sym (syntax->datum mv)]) - (for-each - (lambda (spec) - (when (memq mv-sym (syntax->datum (spec-meta-vars spec))) - (syntax-violation 'define-language - (format "the forms ~s and ~s in language ~s uses the same meta-variable" - (syntax->datum (spec-name test-spec)) - (syntax->datum (spec-name spec)) (syntax->datum lang-name)) - mv))) - (cdr specs)))) - (spec-meta-vars test-spec))) - (f (cdr specs))))))) - (check-meta! name tspecs ntspecs) - (new name entry-ntspec tspecs ntspecs #f #f #f nongen-id))))) - - (define-record-type tspec - (fields meta-vars type handler (mutable pred) (mutable tag) (mutable parent?)) - (nongenerative) - (protocol - (lambda (new) - (case-lambda - [(type meta-vars) (new meta-vars type #f #f #f #f)] - [(type meta-vars handler) (new meta-vars type handler #f #f #f)])))) - - (define-record-type ntspec - (fields name meta-vars alts - (mutable rtd) - (mutable rcd) - (mutable tag) - (mutable pred) ; this record? - (mutable all-pred) ; this record or valid sub-grammar element - ; e.g., if Rhs -> Triv, Triv -> Lvalue, and Lvalue -> var, - ; then all-pred returns true for any Rhs, Triv, Lvalue, or var - (mutable all-term-pred) ; this record's term sub-grammar elements - (mutable all-tag)) ; tag for this record logor all sub grammar elements - ; following all-pred order - (nongenerative) - (protocol - (lambda (new) - (lambda (name meta-vars alts) - (new name meta-vars alts #f #f #f #f #f #f #f))))) - - (define-record-type alt - (fields syn pretty pretty-procedure?) - (nongenerative)) - - (define-record-type pair-alt - (parent alt) - (fields - (mutable rtd) - (mutable pattern) - (mutable field-names) - (mutable field-levels) - (mutable field-maybes) - (mutable implicit? pair-alt-implicit? pair-alt-implicit-set!) - (mutable tag) - (mutable pred) - (mutable maker) - (mutable accessors)) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (syn pretty pretty-procedure?) - ((pargs->new syn pretty pretty-procedure?) - #f #f #f #f #f #f #f #f #f #f))))) - - (define-record-type terminal-alt - (parent alt) - (fields (mutable tspec)) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (syn pretty pretty-procedure?) - ((pargs->new syn pretty pretty-procedure?) #f))))) - - (define-record-type nonterminal-alt - (parent alt) - (fields (mutable ntspec)) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (syn pretty pretty-procedure?) - ((pargs->new syn pretty pretty-procedure?) #f))))) - - (define-who spec-all-pred - (lambda (x) - (cond - [(tspec? x) (tspec-pred x)] - [(ntspec? x) (ntspec-all-pred x)] - [else (error who "unrecognized type" x)]))) - - (define-who spec-type - (lambda (x) - (cond - [(tspec? x) (tspec-type x)] - [(ntspec? x) (ntspec-name x)] - [else (error who "unrecognized type" x)]))) - - ;;; records produced by meta parsers - (define-record-type nano-dots (fields x) (nongenerative) (sealed #t)) - - (define-record-type nano-quote (fields x) (nongenerative) (sealed #t)) - - (define-record-type nano-unquote (fields x) (nongenerative) (sealed #t)) - - (define-record-type nano-meta (fields alt fields) (nongenerative) (sealed #t)) - - (define-record-type nano-cata - (fields itype syntax procexpr maybe-inid* outid* maybe?) - (nongenerative) - (sealed #t)) - - ;; record helpers - (define find-spec - (lambda (m lang) - (let ([name (meta-var->raw-meta-var (syntax->datum m))]) - (or (find (lambda (ntspec) - (memq name (syntax->datum (ntspec-meta-vars ntspec)))) - (language-ntspecs lang)) - (find (lambda (tspec) - (memq name (syntax->datum (tspec-meta-vars tspec)))) - (language-tspecs lang)) - (syntax-violation #f "meta not found" (language-name lang) m))))) - - (define nonterminal-meta? - (lambda (m ntspec*) - (let ([m (meta-var->raw-meta-var (syntax->datum m))]) - (exists (lambda (x) (memq m (syntax->datum (ntspec-meta-vars x)))) - ntspec*)))) - - (define nonterminal-meta->ntspec - (lambda (meta ntspecs) - (let ([meta (meta-var->raw-meta-var (syntax->datum meta))]) - (find (lambda (x) (memq meta (syntax->datum (ntspec-meta-vars x)))) - ntspecs)))) - - (define terminal-meta->tspec - (lambda (meta tspecs) - (let ([meta (meta-var->raw-meta-var (syntax->datum meta))]) - (find (lambda (x) (memq meta (syntax->datum (tspec-meta-vars x)))) - tspecs)))) - - (define meta->pred - (lambda (m lang) - (let ([name (meta-var->raw-meta-var (syntax->datum m))]) - (or (find (lambda (ntspec) - (and (memq name (syntax->datum (ntspec-meta-vars ntspec))) - (ntspec-all-pred ntspec))) - (language-ntspecs lang)) - (find (lambda (tspec) - (and (memq name (syntax->datum (tspec-meta-vars tspec))) - (tspec-pred tspec))) - (language-tspecs lang)) - (syntax-violation #f "meta not found" (language-name lang) m))))) - - (define id->spec - (lambda (id lang) - (or (nonterm-id->ntspec? id (language-ntspecs lang)) - (term-id->tspec? id (language-tspecs lang))))) - - (define term-id->tspec? - (lambda (id tspecs) - (let ([type (syntax->datum id)]) - (find (lambda (tspec) (eq? (syntax->datum (tspec-type tspec)) type)) - tspecs)))) - - (define nonterm-id->ntspec? - (lambda (id ntspecs) - (let ([ntname (syntax->datum id)]) - (find (lambda (ntspec) (eq? (syntax->datum (ntspec-name ntspec)) ntname)) - ntspecs)))) - - (define-syntax nonterm-id->ntspec - (syntax-rules () - [(_ ?who ?id ?ntspecs) - (let ([id ?id]) - (or (nonterm-id->ntspec? id ?ntspecs) - (syntax-violation ?who "unrecognized non-terminal" id)))])) - - (define-who meta-name->tspec - (lambda (m tspecs) - (let ([m (meta-var->raw-meta-var (syntax->datum m))]) - (find (lambda (tspec) - (memq m (syntax->datum (tspec-meta-vars tspec)))) - tspecs)))) - - (define-who meta-name->ntspec - (lambda (m ntspecs) - (let ([m (meta-var->raw-meta-var (syntax->datum m))]) - (find (lambda (ntspec) - (memq m (syntax->datum (ntspec-meta-vars ntspec)))) - ntspecs)))) - - (define subspec? - (lambda (maybe-subspec spec) - (let loop ([spec* (list spec)] [seen* '()]) - (and (not (null? spec*)) - (let ([spec (car spec*)]) - (or (eq? maybe-subspec spec) - (loop - (if (tspec? spec) - (cdr spec*) - (fold-left - (lambda (spec* alt) - (cond - [(terminal-alt? alt) - (let ([spec (terminal-alt-tspec alt)]) - (if (memq spec seen*) - spec* - (cons spec spec*)))] - [(nonterminal-alt? alt) - (let ([spec (nonterminal-alt-ntspec alt)]) - (if (memq spec seen*) - spec* - (cons spec spec*)))] - [else spec*])) - (cdr spec*) - (ntspec-alts spec))) - (cons spec seen*)))))))) - - (define type->pred-prefixes - (lambda (id mrec) - (define find-related-ntspecs - (lambda (ntspec mrec) - (let ([ntspecs (language-ntspecs mrec)]) - (let f ([alts (ntspec-alts ntspec)] [ls '()]) - (fold-left (lambda (ls alt) - (if (nonterminal-alt? alt) - (let ([ntspec (nonterminal-alt-ntspec alt)]) - (cons ntspec (f (ntspec-alts ntspec) ls))) - ls)) - ls alts))))) - (define find - (lambda (specs) - (cond - [(null? specs) #f] - [(eq? (syntax->datum id) - (syntax->datum - (let ([spec (car specs)]) - (cond - [(tspec? spec) (tspec-type spec)] - [(ntspec? spec) (ntspec-name spec)] - [else (error 'type->pred-prefixes - "unable to find matching spec, wrong type" - spec)])))) - (car specs)] - [else (find (cdr specs))]))) - (let ([found (find (language-tspecs mrec))]) - (if found - (list found) - (let ([found (find (language-ntspecs mrec))]) - (if found - (let ([ntspecs (find-related-ntspecs found mrec)]) - (cons found ntspecs)) - (error 'type->pred-prefixes "unrecognized non-terminal" - id))))))) - - (define has-implicit-alt? - (lambda (ntspec) - (exists - (lambda (alt) - (if (pair-alt? alt) - (pair-alt-implicit? alt) - (and (nonterminal-alt? alt) - (has-implicit-alt? (nonterminal-alt-ntspec alt))))) - (ntspec-alts ntspec)))) - - (define gather-meta - (lambda (lang) - (let ([tmeta (map tspec-meta-vars (language-tspecs lang))] - [pmeta (map ntspec-meta-vars (language-ntspecs lang))]) - (apply append (append tmeta pmeta))))) - - (define annotate-language! - (lambda (r lang id) - (let ([lang-name (language-name lang)] [nongen-id (language-nongenerative-id lang)]) - (let ([lang-rec-id (construct-unique-id id lang-name "-record")] - [tspec* (language-tspecs lang)] - [ntspec* (language-ntspecs lang)] - [np-bits #f #;(r #'nanopass-record #'*nanopass-record-bits*)] - [nongen-sym (and nongen-id (syntax->datum nongen-id))]) - ;; Needs to return #t because it ends up encoded in a field this way - (define meta? - (lambda (m) - (let ([m (meta-var->raw-meta-var (syntax->datum m))]) - (or (exists (lambda (tspec) (memq m (syntax->datum (tspec-meta-vars tspec)))) tspec*) - (exists (lambda (ntspec) (memq m (syntax->datum (ntspec-meta-vars ntspec)))) ntspec*))))) - (define annotate-tspec! - (lambda (tspec-tag-all tspec) - (let ([t (tspec-type tspec)]) - (tspec-pred-set! tspec (construct-id t t "?")) - (let ([tag #f #;(guard (c [else #f]) (r t #'*nanopass-record-tag*))]) - (if tag - (begin - (tspec-tag-set! tspec tag) - (tspec-parent?-set! tspec #f #;(r t #'*nanopass-record-is-parent*)) - (fxior tag tspec-tag-all)) - tspec-tag-all))))) - (define-who annotate-alt*! - (lambda (bits) - (lambda (alt-all-tag ntspec) - (let ([tag (ntspec-tag ntspec)] [nt-rtd (ntspec-rtd ntspec)] [ntname (ntspec-name ntspec)]) - (let ([ntname-sym (syntax->datum ntname)]) - (let f ([alt* (ntspec-alts ntspec)] [next 1] [alt-all-tag alt-all-tag]) - (if (null? alt*) - alt-all-tag - (let ([a (car alt*)] [alt* (cdr alt*)]) - (cond - [(pair-alt? a) - (let* ([syn (alt-syn a)] - [name (car syn)] - [rec-name (unique-name lang-name ntname name)] - [m? (meta? name)]) - (let-values ([(p fields levels maybes) (convert-pattern (if m? syn (cdr syn)))]) - (unless (all-unique-identifiers? fields) - (syntax-violation 'define-language "found one or more duplicate fields in production" syn)) - (let ([tag (fx+ (fxarithmetic-shift-left next bits) tag)]) - (pair-alt-tag-set! a tag) - (pair-alt-rtd-set! a - (make-record-type-descriptor (string->symbol rec-name) nt-rtd - (if nongen-sym - (regensym nongen-sym - (format ":~s:~s" ntname-sym (syntax->datum name)) - (format "-~s" tag)) - (gensym rec-name)) - #t #f - (let loop ([fields fields] [count 0]) - (if (null? fields) - (make-vector count) - (let ([v (loop (cdr fields) (fx+ count 1))]) - (vector-set! v count `(immutable ,(syntax->datum (car fields)))) - v))))) - (pair-alt-pattern-set! a p) - (pair-alt-field-names-set! a fields) - (pair-alt-field-levels-set! a levels) - (pair-alt-field-maybes-set! a maybes) - (pair-alt-implicit-set! a m?) - (pair-alt-accessors-set! a - (map (lambda (field) - (construct-unique-id id rec-name "-" field)) - fields)) - (pair-alt-pred-set! a (construct-unique-id id rec-name "?")) - (pair-alt-maker-set! a (construct-unique-id id "make-" rec-name)) - (f alt* (fx+ next 1) (fxior alt-all-tag tag)))))] - [(nonterminal-alt? a) - (let ([a-ntspec (nonterminal-meta->ntspec (alt-syn a) ntspec*)]) - (unless a-ntspec - (syntax-violation 'define-language "no nonterminal for meta-variable" - lang-name (alt-syn a))) - (nonterminal-alt-ntspec-set! a a-ntspec) - (f alt* next alt-all-tag))] - [(terminal-alt? a) - (let ([tspec (terminal-meta->tspec (alt-syn a) tspec*)]) - (unless tspec - (syntax-violation 'define-language "no terminal for meta-variable" - lang-name (alt-syn a))) - (terminal-alt-tspec-set! a tspec) - (f alt* next alt-all-tag))] - [else (errorf who "unexpected terminal alt ~s" a)]))))))))) - (define annotate-ntspec*! - (lambda (ntspec*) - (let f ([nt-counter 0] [ntspec* ntspec*]) - (if (null? ntspec*) - nt-counter - (let ([ntspec (car ntspec*)] [ntspec* (cdr ntspec*)]) - (let ([nterm (ntspec-name ntspec)]) - (let ([nt-rec-name (unique-name lang-name nterm)]) - (let ([nt-rtd (make-record-type-descriptor - (string->symbol nt-rec-name) - (language-rtd lang) - (if nongen-sym - (regensym nongen-sym - (format ":~s" - (syntax->datum nterm)) - (format "-~d" nt-counter)) - (gensym nt-rec-name)) - #f #f (vector))]) - (ntspec-tag-set! ntspec nt-counter) - (ntspec-rtd-set! ntspec nt-rtd) - (ntspec-rcd-set! ntspec - (make-record-constructor-descriptor nt-rtd - (language-rcd lang) #f)) - (ntspec-pred-set! ntspec (construct-unique-id id nt-rec-name "?")) - (f (fx+ nt-counter 1) ntspec*))))))))) - (define-who annotate-all-pred! - (lambda (ntspec) - (let ([all-pred (ntspec-all-pred ntspec)]) - (cond - [(eq? all-pred 'processing) (syntax-violation 'define-language "found mutually recursive nonterminals" (ntspec-name ntspec))] - [all-pred (values all-pred (ntspec-all-term-pred ntspec) (ntspec-all-tag ntspec))] - [else - (ntspec-all-pred-set! ntspec 'processing) - (let f ([alt* (ntspec-alts ntspec)] [pred* '()] [term-pred* '()] [tag '()]) - (if (null? alt*) - (let ([all-pred (if (null? pred*) - (ntspec-pred ntspec) - #`(lambda (x) - (or (#,(ntspec-pred ntspec) x) - #,@(map (lambda (pred) #`(#,pred x)) pred*))))] - [all-term-pred (cond - [(null? term-pred*) #f] - [(null? (cdr term-pred*)) (car term-pred*)] - [else #`(lambda (x) (or #,@(map (lambda (pred) #`(#,pred x)) term-pred*)))])] - [tag (cons (ntspec-tag ntspec) tag)]) - (ntspec-all-pred-set! ntspec all-pred) - (ntspec-all-term-pred-set! ntspec all-term-pred) - (ntspec-all-tag-set! ntspec tag) - (values all-pred all-term-pred tag)) - (let ([alt (car alt*)]) - (cond - [(pair-alt? alt) (f (cdr alt*) pred* term-pred* tag)] - [(terminal-alt? alt) - (let* ([tspec (terminal-alt-tspec alt)] - [new-tag (tspec-tag tspec)] - [pred (tspec-pred tspec)]) - (f (cdr alt*) (cons pred pred*) - (if #f #;new-tag term-pred* (cons pred term-pred*)) - (if #f #;new-tag (fxior new-tag tag) tag)))] - [(nonterminal-alt? alt) - (let-values ([(pred term-pred new-tag) (annotate-all-pred! (nonterminal-alt-ntspec alt))]) - (f (cdr alt*) (cons pred pred*) - (if term-pred (cons term-pred term-pred*) term-pred*) - (append new-tag tag)))] - [else (errorf who "unexpected alt ~s" alt)]))))])))) - (let ([lang-rtd (make-record-type-descriptor (syntax->datum lang-name) - (record-type-descriptor nanopass-record) - (let ([nongen-id (language-nongenerative-id lang)]) - (if nongen-id - (syntax->datum nongen-id) - (gensym (unique-name lang-name)))) - #f #f (vector))]) - (language-rtd-set! lang lang-rtd) - (language-rcd-set! lang - (make-record-constructor-descriptor lang-rtd - (record-constructor-descriptor nanopass-record) #f))) - (let ([tspec-tag-bits (fold-left annotate-tspec! 0 tspec*)]) - (let ([nt-counter (annotate-ntspec*! ntspec*)]) - (let ([bits (fxlength nt-counter)]) - (unless (fxzero? (fxand tspec-tag-bits (fx- (fxarithmetic-shift-left 1 bits) 1))) - (syntax-violation 'define-language "nanopass-record tags interfere with language production tags" - lang-name)) - (language-tag-mask-set! lang (fx- (fxarithmetic-shift-left 1 bits) 1)) - (let ([ntalt-tag-bits (fold-left (annotate-alt*! bits) 0 ntspec*)]) - (unless (or (not np-bits) - (fxzero? (fxand ntalt-tag-bits - (fxreverse-bit-field (fx- (fxarithmetic-shift-left 1 np-bits) 1) - 0 (fx- (fixnum-width) 1))))) - (syntax-violation 'define-language "language production tags interfere with nanopass-record tags" - lang-name)) - (for-each annotate-all-pred! ntspec*))))))))) - - (define language->lang-records - (lambda (lang) - (let ([ntspecs (language-ntspecs lang)] [tspecs (language-tspecs lang)]) - (define alt->lang-record - (lambda (ntspec alt) - ; TODO: handle fld and msgs that are lists. - (define build-field-check - (lambda (fld msg level maybe?) - (with-values - (cond - [(nonterminal-meta->ntspec fld ntspecs) => - (lambda (ntspec) (values (ntspec-all-pred ntspec) (ntspec-name ntspec)))] - [(terminal-meta->tspec fld tspecs) => - (lambda (tspec) (values (tspec-pred tspec) (tspec-type tspec)))] - [else (syntax-violation 'define-language - (format "unrecognized meta-variable in language ~s" - (syntax->datum (language-name lang))) - fld)]) - (lambda (pred? name) - (define (build-list-of-string level name) - (let loop ([level level] [str ""]) - (if (fx=? level 0) - (string-append str (symbol->string (syntax->datum name))) - (loop (fx- level 1) (string-append str "list of "))))) - (with-syntax ([pred? (if maybe? - #`(lambda (x) (or (eq? x #f) (#,pred? x))) - pred?)]) - #`(#,(let f ([level level]) - (if (fx=? level 0) - #`(lambda (x) - (unless (pred? x) - (let ([msg #,msg]) - (if msg - (errorf who - "expected ~s but received ~s in field ~s of ~s from ~a" - '#,name x '#,fld '#,(alt-syn alt) msg) - (errorf who - "expected ~s but received ~s in field ~s of ~s" - '#,name x '#,fld '#,(alt-syn alt)))))) - #`(lambda (x) - (let loop ([x x]) - (cond - [(pair? x) - (#,(f (fx- level 1)) (car x)) - (loop (cdr x))] - [(null? x)] - [else - (let ([msg #,msg]) - (if msg - (errorf who - "expected ~a but received ~s in field ~s of ~s from ~a" - #,(build-list-of-string level name) x '#,fld '#,(alt-syn alt) msg) - (errorf who - "expected ~a but received ~s in field ~s of ~s" - #,(build-list-of-string level name) x '#,fld '#,(alt-syn alt))))]))))) - #,fld)))))) - (with-syntax ([(fld ...) (pair-alt-field-names alt)]) - (with-syntax ([(msg ...) (generate-temporaries #'(fld ...))] - [(idx ...) (iota (length #'(fld ...)))] - [(accessor ...) (pair-alt-accessors alt)] - [(rtd ...) (make-list (length #'(fld ...)) (pair-alt-rtd alt))]) - #`(begin - (define #,(pair-alt-pred alt) (record-predicate '#,(pair-alt-rtd alt))) - (define #,(pair-alt-maker alt) - (let () - (define rcd - (make-record-constructor-descriptor '#,(pair-alt-rtd alt) - '#,(ntspec-rcd ntspec) - (lambda (pargs->new) - (lambda (fld ...) - ((pargs->new #,(pair-alt-tag alt)) fld ...))))) - (define maker (record-constructor rcd)) - (lambda (who fld ... msg ...) - #,@(if (fx=? (optimize-level) 3) - '() - (map build-field-check #'(fld ...) #'(msg ...) - (pair-alt-field-levels alt) - (pair-alt-field-maybes alt))) - (maker fld ...)))) - (define accessor (record-accessor 'rtd idx)) ...))))) - (define ntspec->lang-record - (lambda (ntspec) - #`(define #,(ntspec-pred ntspec) (record-predicate '#,(ntspec-rtd ntspec))))) - (define ntspecs->lang-records - (lambda (ntspec*) - (let f ([ntspec* ntspec*] [ntrec* '()] [altrec* '()]) - (if (null? ntspec*) - #`(#,ntrec* #,altrec*) - (let ([ntspec (car ntspec*)]) - (let g ([alt* (ntspec-alts ntspec)] [altrec* altrec*]) - (if (null? alt*) - (f (cdr ntspec*) - (cons (ntspec->lang-record ntspec) ntrec*) - altrec*) - (let ([alt (car alt*)]) - (if (pair-alt? alt) - (g (cdr alt*) - (cons (alt->lang-record ntspec alt) altrec*)) - (g (cdr alt*) altrec*)))))))))) - (define ntspecs->indirect-id* - (lambda (ntspec*) - (let f ([ntspec* ntspec*] [id* '()]) - (if (null? ntspec*) - id* - (let ([ntspec (car ntspec*)]) - (let g ([alt* (ntspec-alts ntspec)] [id* id*]) - (if (null? alt*) - (f (cdr ntspec*) (cons (ntspec-pred ntspec) id*)) - (g (cdr alt*) - (let ([alt (car alt*)]) - (if (pair-alt? alt) - (cons* (pair-alt-pred alt) - (pair-alt-maker alt) - (append (pair-alt-accessors alt) id*)) - id*)))))))))) - (with-syntax ([((ntrec ...) (altrec ...)) - (ntspecs->lang-records (language-ntspecs lang))] - [lang-id (language-name lang)] - [(indirect-id* ...) (ntspecs->indirect-id* (language-ntspecs lang))]) - #`(ntrec ... altrec ... (indirect-export lang-id indirect-id* ...)))))) - - (define language->lang-predicates - (lambda (desc) - (let ([name (language-name desc)]) - (let loop ([ntspecs (language-ntspecs desc)] [nt?* '()] [term?* '()]) - (if (null? ntspecs) - (with-syntax ([lang? (construct-id name name "?")] - [(nt? ...) nt?*] - [(term? ...) term?*]) - #`((define lang? - (lambda (x) - (or ((record-predicate '#,(language-rtd desc)) x) (term? x) ...))) - nt? ...)) - (let ([ntspec (car ntspecs)]) - (loop (cdr ntspecs) - (with-syntax ([nt? (construct-id name name "-" (ntspec-name ntspec) "?")] - [lambda-expr (ntspec-all-pred ntspec)]) - (cons #'(define nt? lambda-expr) nt?*)) - (let loop ([alts (ntspec-alts ntspec)] [term?* term?*]) - (if (null? alts) - term?* - (loop (cdr alts) - (let ([alt (car alts)]) - (if (terminal-alt? alt) - (cons (tspec-pred (terminal-alt-tspec alt)) term?*) - term?*)))))))))))) - - ;; utilities moved out of pass.ss - (define-who exists-alt? - (lambda (ialt ntspec) - (define scan-alts - (lambda (pred?) - (let f ([alt* (ntspec-alts ntspec)]) - (if (null? alt*) - #f - (let ([alt (car alt*)]) - (if (nonterminal-alt? alt) - (or (f (ntspec-alts (nonterminal-alt-ntspec alt))) - (f (cdr alt*))) - (if (pred? alt) alt (f (cdr alt*))))))))) - (cond - [(terminal-alt? ialt) - (let ([type (syntax->datum (tspec-type (terminal-alt-tspec ialt)))]) - (scan-alts - (lambda (alt) - (and (terminal-alt? alt) - (eq? (syntax->datum (tspec-type (terminal-alt-tspec alt))) type)))))] - [(pair-alt? ialt) - (if (pair-alt-implicit? ialt) - (let ([pattern (pair-alt-pattern ialt)]) - (scan-alts - (lambda (alt) - (and (pair-alt? alt) - (pair-alt-implicit? alt) - (let ([apattern (pair-alt-pattern alt)]) - (equal? apattern pattern)))))) - (let ([pattern (pair-alt-pattern ialt)]) - (scan-alts - (lambda (alt) - (and (pair-alt? alt) - (not (pair-alt-implicit? alt)) - (let ([apattern (pair-alt-pattern alt)]) - (and (eq? (syntax->datum (car (alt-syn alt))) (syntax->datum (car (alt-syn ialt)))) - (equal? apattern pattern))))))))] - [else (error who "unexpected alt" ialt)]))) - - ;; record type used to transport data in the compile-time environment. - (define-record-type pass-info - (nongenerative) - (fields input-language output-language))) diff --git a/ta6ob/nanopass/nanopass/syntactic-property.sls b/ta6ob/nanopass/nanopass/syntactic-property.sls deleted file mode 100644 index 0a50a3e..0000000 --- a/ta6ob/nanopass/nanopass/syntactic-property.sls +++ /dev/null @@ -1,55 +0,0 @@ -;;; Copyright (c) 2000-2018 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -;; implements a global association list from bound-identifiers to property -;; lists property lists are themselves assogiation lists from free-identifiers -;; to values. -(library (nanopass syntactic-property) - (export syntax-property-set! syntax-property-get) - (import (rnrs)) - - (define-record-type ($box box box?) (nongenerative) (fields (mutable v unbox box-set!))) - - (define props (box '())) - - (define syntax-property-set! - (lambda (id key value) - (box-set! props - (let f ([props (unbox props)]) - (if (null? props) - (list (cons id (list (cons key value)))) - (let ([as (car props)] [props (cdr props)]) - (if (bound-identifier=? (car as) id) - (cons (cons id (cons (cons key value) (cdr as))) props) - (cons as (f props))))))))) - - (define syntax-property-get - (case-lambda - [(id key) - (let loop ([props (unbox props)]) - (if (null? props) - (error 'syntax-property-get "no properties for ~s found" (syntax->datum id)) - (let ([as (car props)] [props (cdr props)]) - (if (bound-identifier=? (car as) id) - (let loop ([ls (cdr as)]) - (if (null? ls) - (error 'syntax-propert-get "no property ~s for ~s found" (syntax->datum key) (syntax->datum id)) - (let ([as (car ls)] [ls (cdr ls)]) - (if (free-identifier=? (car as) key) - (cdr as) - (loop ls))))) - (loop props)))))] - [(id key not-found) - (let loop ([props (unbox props)]) - (if (null? props) - not-found - (let ([as (car props)] [props (cdr props)]) - (if (bound-identifier=? (car as) id) - (let loop ([ls (cdr as)]) - (if (null? ls) - not-found - (let ([as (car ls)] [ls (cdr ls)]) - (if (free-identifier=? (car as) key) - (cdr as) - (loop ls))))) - (loop props)))))]))) diff --git a/ta6ob/nanopass/nanopass/syntaxconvert.ss b/ta6ob/nanopass/nanopass/syntaxconvert.ss deleted file mode 100644 index a312406..0000000 --- a/ta6ob/nanopass/nanopass/syntaxconvert.ss +++ /dev/null @@ -1,45 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (nanopass syntaxconvert) - (export convert-pattern) - (import (rnrs) (nanopass helpers)) - - (define convert-pattern - ; accepts pattern & keys - ; returns syntax-dispatch pattern & ids - (lambda (pattern) - (define cvt* - (lambda (p* n flds lvls maybes) - (if (null? p*) - (values '() flds lvls maybes) - (let-values ([(y flds lvls maybes) (cvt* (cdr p*) n flds lvls maybes)]) - (let-values ([(x flds lvls maybes) (cvt (car p*) n flds lvls maybes)]) - (values (cons x y) flds lvls maybes)))))) - (define cvt - (lambda (p n flds lvls maybes) - (if (identifier? p) - (values 'any (cons p flds) (cons n lvls) (cons #f maybes)) - (syntax-case p () - [(x dots) - (ellipsis? (syntax dots)) - (let-values ([(p flds lvls maybes) (cvt (syntax x) (fx+ n 1) flds lvls maybes)]) - (values (if (eq? p 'any) 'each-any (vector 'each p)) flds lvls maybes))] - [(x dots y ... . z) - (ellipsis? (syntax dots)) - (let-values ([(z flds lvls maybes) (cvt (syntax z) n flds lvls maybes)]) - (let-values ([(y flds lvls maybes) (cvt* (syntax (y ...)) n flds lvls maybes)]) - (let-values ([(x flds lvls maybes) (cvt (syntax x) (fx+ n 1) flds lvls maybes)]) - (values `#(each+ ,x ,(reverse y) ,z) flds lvls maybes))))] - [(maybe x) - (and (identifier? #'x) (eq? (datum maybe) 'maybe)) - (values 'any (cons #'x flds) (cons n lvls) (cons #t maybes))] - [(x . y) - (let-values ([(y flds lvls maybes) (cvt (syntax y) n flds lvls maybes)]) - (let-values ([(x flds lvls maybes) (cvt (syntax x) n flds lvls maybes)]) - (values (cons x y) flds lvls maybes)))] - [() (values '() flds lvls maybes)] - [oth (syntax-violation 'cvt "unable to find match" #'oth)])))) - (cvt pattern 0 '() '() '())))) - - diff --git a/ta6ob/nanopass/nanopass/unparser.ss b/ta6ob/nanopass/nanopass/unparser.ss deleted file mode 100644 index 66aa918..0000000 --- a/ta6ob/nanopass/nanopass/unparser.ss +++ /dev/null @@ -1,150 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (nanopass unparser) - (export define-unparser) - (import (rnrs) - (nanopass helpers) - (nanopass records) - (nanopass syntaxconvert)) - - (define-syntax define-unparser - (lambda (x) - (define make-unparser-name-assoc - (lambda (tid) - (lambda (ntspec) - (cons ntspec (construct-unique-id tid "unparse-" (syntax->datum (ntspec-name ntspec))))))) - (define make-unparse-term-clause-body-assoc - (lambda (tspec) - (cons tspec - (let ([h (tspec-handler tspec)]) - (if h - #`(if raw? ir (#,h ir)) - #'ir))))) - (define make-unparser - (lambda (unparser-name desc) - (let* ([lang-name (language-name desc)] - [ntspecs (language-ntspecs desc)] - [tspecs (language-tspecs desc)] - [unparser-names (map (make-unparser-name-assoc unparser-name) ntspecs)] - [tspec-bodies (map make-unparse-term-clause-body-assoc tspecs)]) - (define (lookup-unparser ntspec) - (cond - [(assq ntspec unparser-names) => cdr] - [else (syntax-violation 'define-unparser - (format "unexpected nonterminal ~s in language ~s, expected one of ~s" - (syntax->datum (ntspec-name ntspec)) (syntax->datum lang-name) - (map (lambda (nt) (syntax->datum (ntspec-name nt))) ntspecs)) - unparser-name x)])) - (define (lookup-tspec-body tspec) - (cond - [(assq tspec tspec-bodies) => cdr] - [else (syntax-violation 'define-unparser - (format "unexpected terminal ~s in language ~s, expected one of ~s" - (syntax->datum (tspec-type tspec)) (syntax->datum lang-name) - (map (lambda (t) (syntax->datum (tspec-type t))) tspecs)) - unparser-name x)])) - (with-syntax ([unparser-name unparser-name] - [(proc-name ...) (map cdr unparser-names)] - [(ntspec? ...) (map ntspec-pred ntspecs)] - [(tspec? ...) (map tspec-pred tspecs)] - [(tspec-body ...) (map cdr tspec-bodies)]) - (define make-unparse-proc - (lambda (ntspec) - ;; handles alts of the form: LambdaExpr where LambdaExpr is another - ;; non-terminal specifier with no surrounding markers. - (define make-nonterm-clause - (lambda (alt) - (let ([ntspec (nonterminal-alt-ntspec alt)]) - (list #`((#,(ntspec-all-pred ntspec) ir) - (#,(lookup-unparser ntspec) ir)))))) - ;; handles alts of the form: x, c where x and c are meta-variables - ;; that refer to terminals, and have no surrounding marker. - (define-who make-term-clause ;; only atom alt cases - (lambda (alt) - (let ([tspec (terminal-alt-tspec alt)]) - #`((#,(tspec-pred tspec) ir) - #,(lookup-tspec-body tspec))))) - - (define strip-maybe - (lambda (tmpl) - (syntax-case tmpl (maybe) - [(maybe x) (and (identifier? #'x) (eq? (datum maybe) 'maybe)) #'x] - [(a . d) (with-syntax ([a (strip-maybe #'a)] [d (strip-maybe #'d)]) #'(a . d))] - [() tmpl] - [oth tmpl]))) - - (define build-accessor-expr - (lambda (acc level maybe?) - (let loop ([level level] [f #`(lambda (t) - #,(if maybe? - #'(and t (unparser-name t raw?)) - #'(unparser-name t raw?)))]) - (if (fx=? level 0) - #`(#,f (#,acc ir)) - (loop (fx- level 1) #`(lambda (t) (map #,f t))))))) - - (define build-template-wrapper - (lambda (tmpl alt) - (with-syntax ([(e ...) (map build-accessor-expr - (pair-alt-accessors alt) - (pair-alt-field-levels alt) - (pair-alt-field-maybes alt))] - [(fld ...) (pair-alt-field-names alt)] - [tmpl tmpl]) - #'(let ([fld e] ...) - (with-extended-quasiquote - (with-auto-unquote (fld ...) `tmpl)))))) - - (define make-pair-clause - (lambda (alt) - (with-syntax ([pred? (pair-alt-pred alt)] - [raw-body (build-template-wrapper (strip-maybe (alt-syn alt)) alt)]) - #`((pred? ir) - #,(let ([pretty (alt-pretty alt)]) - (if pretty - #`(if raw? - raw-body - #,(if (alt-pretty-procedure? alt) - (with-syntax ([(acc ...) (pair-alt-accessors alt)]) - #`(#,pretty unparser-name (acc ir) ...)) - (build-template-wrapper pretty alt))) - #'raw-body)))))) - - ;; When one nonterminalA alternative is another nonterminalB, we - ;; expand all the alternatives of nonterminalB with the alternatives - ;; of nonterminalA However, nonterminalA and nonterminalB cannot - ;; (both) have an implicit case, by design. - (partition-syn (ntspec-alts ntspec) - ([term-alt* terminal-alt?] [nonterm-alt* nonterminal-alt?] [pair-alt* otherwise]) - (partition-syn nonterm-alt* - ([nonterm-imp-alt* (lambda (alt) - (has-implicit-alt? - (nonterminal-alt-ntspec alt)))] - [nonterm-nonimp-alt* otherwise]) - #`(lambda (ir) - (cond - #,@(map make-term-clause term-alt*) - #,@(map make-pair-clause pair-alt*) - ;; note: the following two can potentially be combined - #,@(apply append (map make-nonterm-clause nonterm-nonimp-alt*)) - #,@(apply append (map make-nonterm-clause nonterm-imp-alt*)) - [else (error who "invalid record" ir)])))))) - (with-syntax ([(proc ...) (map make-unparse-proc ntspecs)]) - #'(define-who unparser-name - (case-lambda - [(ir) (unparser-name ir #f)] - [(ir raw?) - (define-who proc-name proc) ... - (cond - [(ntspec? ir) (proc-name ir)] ... - [(tspec? ir) tspec-body] ... - [else (error who "unrecognized language record" ir)])]))))))) - (syntax-case x () - [(_ name lang) - (and (identifier? #'name) (identifier? #'lang)) - (with-compile-time-environment (r) - (let ([l-pair (r #'lang)]) - (unless (pair? l-pair) - (syntax-violation 'define-unparser "unknown language" #'lang x)) - (make-unparser #'name (car l-pair))))])))) diff --git a/ta6ob/nanopass/test-all.ss b/ta6ob/nanopass/test-all.ss deleted file mode 100755 index 9cf0f1a..0000000 --- a/ta6ob/nanopass/test-all.ss +++ /dev/null @@ -1,29 +0,0 @@ -;;; Copyright (c) 2000-2018 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(import (rnrs) (tests compiler-test) (tests helpers) (tests unit-tests) (nanopass helpers)) - -(printf "Running unit tests\n") -(let* ([succeeded? (run-unit-tests)] - [succeeded? (and (run-ensure-correct-identifiers) succeeded?)] - [succeeded? (and (run-maybe-tests) succeeded?)] - [succeeded? (and (run-maybe-dots-tests) succeeded?)] - [succeeded? (and (run-maybe-unparse-tests) succeeded?)] - [succeeded? (and (run-language-dot-support) succeeded?)] - [succeeded? (and (run-argument-name-matching) succeeded?)] - [succeeded? (and (run-error-messages) succeeded?)] - [succeeded? (and (run-pass-parser-unparser) succeeded?)]) - (printf "Compiler loaded, running all tests (quietly)\n") - (time - (begin - (run-all-tests) - (run-all-tests) - (run-all-tests) - (run-all-tests) - (run-all-tests) - (run-all-tests) - (run-all-tests) - (run-all-tests) - (run-all-tests) - (run-all-tests))) - (exit (if succeeded? 0 1))) diff --git a/ta6ob/nanopass/tests/alltests.ss b/ta6ob/nanopass/tests/alltests.ss deleted file mode 100644 index 6617dd8..0000000 --- a/ta6ob/nanopass/tests/alltests.ss +++ /dev/null @@ -1,926 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (tests alltests) - (export main-tests final-tests) - (import (rnrs)) - - (define main-tests - '( - '() - (- 2 4) - (* -6 7) - (cons 0 '()) - (cons (cons 0 '()) (cons 1 '())) - (void) - (if #f 3) - (let ((x 0)) x) - (let ([x 0]) x x) - (let ([q (add1 (add1 2))]) q) - (+ 20 (if #t 122)) - (if #t - (+ 20 - (if #t 122)) - 10000) - (not (if #f #t (not #f))) - (let ([x 0][y 4000]) x) - (begin (if #f 7) 3) - (begin (if (zero? 4) 7) 3) - (let ([x 0]) (begin (if (zero? x) 7) x)) - (let ([x 0]) (begin (if (zero? x) (begin x 7)) x)) - (let ([x 0] [z 9000]) - (begin (if (zero? x) (begin x 7)) z)) - (let ([x 0] [z 9000]) - (begin (if (zero? x) (begin (set! x x) 7)) - (+ x z))) - (let ([x (cons 0 '())]) - (begin (if x (set-car! x (car x))) x)) - (let ([x (cons 0 '())]) - (begin (if x (set-car! x (+ (car x) (car x)))) x)) - (let ([x (cons 0 '())]) - (if (zero? (car x)) (begin (set-car! x x) 7) x)) - (let ([x (cons 0 '())]) - (let ([q x]) (if (zero? (car x)) (begin (set-car! q x) 7) x))) - (let ([x 0]) (if (zero? x) (begin (set! x (+ x 5000)) x) 20)) - (let ([y 0]) (begin (if #t (set! y y)) y)) - (begin (if #t #t #t) #f) - (begin (if (if #t #t #f) (if #t #t #f) (if #t #t #f)) #f) - (let ([x 0] [y 4000] [z 9000]) - (let ((q (+ x z))) - (begin - (if (zero? x) (begin (set! q (+ x x)) 7)) - (+ y y) - (+ x z)))) - (let ([x (let ([y 2]) y)] [y 5]) - (add1 x)) - (let ([y 4000]) (+ y y)) - ((lambda (y) y) 4000) - (let ([f (lambda (x) x)]) - (add1 (f 0))) - (let ([f (lambda (y) y)]) (f (f 4))) - ((lambda (f) (f (f 4))) (lambda (y) y)) - ((let ([a 4000]) - (lambda (b) (+ a b))) - 5000) - (((lambda (a) - (lambda (b) - (+ a b))) - 4000) - 5000) - (let ([f (lambda (x) (add1 x))]) (f (f 0))) - ((lambda (f) (f (f 0))) (lambda (x) (add1 x))) - (let ([x 0] [f (lambda (x) x)]) - (let ([a (f x)] [b (f x)] [c (f x)]) (+ (+ a b) c))) - (let ([x 0][y 1][z 2][f (lambda (x) x)]) - (let ([a (f x)][b (f y)][c (f z)]) - (+ (+ a b) c))) - (let ([f (lambda (x y) x)]) - (f 0 1)) - (let ([f (lambda (x y) x)]) - (let ([a (f 0 1)]) (f a a))) - (let ([x 0] [y 1] [z 2] [f (lambda (x y z) x)]) - (let ([a (f x y z)]) (f a a a))) - (let ([x 0] [y 1] [z 2] [f (lambda (x y z) x)]) - (let ([a (f x y z)] [b y] [c z]) (f a b c))) - (let ([f (lambda (a b c d) - (+ a d))]) - (f 0 1 2 3)) - (let ([f (lambda (x) x)]) - (+ (f 0) - (let ([a 0] [b 1] [c 2]) - (+ (f a) (+ (f b) (f c)))))) - (let ([f (lambda (x) x)]) - (+ (f 0) - (let ([a 0] [b 1] [c 2]) - (add1 (f a))))) - (let ([f (lambda (x) x)]) - (+ (f 0) (let ([a 0][b 1][c 2][d 3]) - (+ (f a) - (+ (f b) - (+ (f c) - (f d))))))) - (let ([a 0])(letrec ([a (lambda () 0)][b (lambda () 11)]) (set! a 11))) - (let ([a 0])(letrec ([a (lambda () (set! a 0))][b 11]) (a))) - (let ([a 0])(let ([a (set! a 0)][b 11]) a)) - (let ([a 5]) (let ([a 0] [b (set! a (+ a 11))]) a)) - (letrec ([a (lambda () 0)]) (a)) - (letrec ([a (lambda () 0)] [b (lambda () 11)]) (a)) - (let ([x 0]) (letrec ([a (lambda () 0)] [b (lambda () 11)]) (set! x 11))) - (let ([a 0]) (let ([b (set! a 0)]) a)) - (let ([a 0])(let ([a (set! a 0)]) (let ([b 11]) a))) - (let ([a 0])(let ([a 0]) (let ([b (set! a 11)]) a))) - (let ([a 0])(let ([a 0]) (let ([b 11]) (set! a 11)))) - (let ([f (let ([x 1]) (lambda (y) (+ x y)))]) - (let ([x 0]) (f (f x)))) - ((let ([t (lambda (x) (+ x 50))]) - (lambda (f) (t (f 1000)))) - (lambda (y) (+ y 2000))) - (let ([x 0]) - (let ([f (let ([x 1] [z x]) - (lambda (y) - (+ x (+ z y))))]) - (f (f x)))) - (((lambda (t) - (lambda (f) (t (f 1000)))) - (lambda (x) (+ x 50))) - (lambda (y) (+ y 2000))) - ((let ([t 50]) - (lambda (f) - (+ t (f)))) - (lambda () 2000)) - (((lambda (t) - (lambda (f) - (+ t (f)))) - 50) - (lambda () 2000)) - ((let ([x 300]) - (lambda (y) (+ x y))) - 400) - (let ([x 3] [f (lambda (x y) x)]) - (f (f 0 0) x)) - (let ([x 3] [f (lambda (x y) x)]) - (if (f 0 0) (f (f 0 0) x) 0)) - (let ([x02 3] [f01 (lambda (x04 y03) x04)]) - (if (not x02) (f01 (f01 0 0) x02) 0)) - (let ((f (lambda (x) (if (if (pair? x) (not (eq? (car x) 0)) #f) x #f)))) - (f (cons 0 0))) - (let ((f (lambda (x) - (if (if x (not (if (pair? x) (not (eq? (car x) 0)) #f)) #f) - x #f)))) - (f 0)) - (let ((f (lambda (x) (if (if (pair? x) #t (null? x)) x '())))) - (f 0)) - (let ([y 4]) - (let ([f (lambda (y) y)]) - (f (f y)))) - (let ([y 4]) - (let ([f (lambda (x y) 0)]) - (f (f y y) (f y y)))) - (let ([y 4]) - (let ([f (lambda (x y) 0)]) - (f (f y y) (f y (f y y))))) - (let ([y 4]) - (let ([f (lambda (x y) 0)]) - (f (f y (f y y)) (f y (f y y))))) - ((lambda (y) ((lambda (f) (f (f y))) (lambda (y) y))) 4) - (let ([f (lambda (x) (+ x x))]) (f 4000)) - (let ((x (if 1000 2000 3000))) x) - (let ([f (lambda (x) x)]) (add1 (if #f 1 (f 22)))) - (let ([f (lambda (x) x)]) (if (f (zero? 23)) 1 22)) - (let ([f (lambda (x) (if x (not x) x))] - [f2 (lambda (x) (* 10 x))] - [x 23]) - (add1 (if (f (zero? x)) 1 (* x (f2 (sub1 x)))))) - (let ([f (lambda () 0)]) - (let ([x (f)]) 1)) - (let ([f (lambda () 0)]) - (begin (f) 1)) - (let ([f (lambda (x) x)]) - (if #t (begin (f 3) 4) 5)) - (let ([f (lambda (x) x)]) - (begin (if #t (f 4) 5) 6)) - (let ([f (lambda (x) x)]) - (begin (if (f #t) - (begin (f 3) (f 4)) - (f 5)) - (f 6))) - (let ([f (lambda (x) (add1 x))]) - (f (let ([f 3]) (+ f 1)))) - (let ((x 15) - (f (lambda (h v) (* h v))) - (k (lambda (x) (+ x 5))) - (g (lambda (x) (add1 x)))) - (k (g (let ((g 3)) (f g x))))) - (let ([x 4]) - (let ([f (lambda () x)]) - (set! x 5) - (f))) - (let ([x (let ([y 2]) y)]) x) - (let ([x (if #t (let ([y 2]) y) 1)]) x) - (let ([x (let ([y (let ([z 3]) z)]) y)]) x) - (let ([x (if #t (let ([y (if #t (let ([z 3]) z) 2)]) y) 1)]) x) - (+ (let ([x 3]) (add1 x)) 4) - (+ (let ([x 3][y 4]) (* x y)) 4) - (let ([x (add1 (let ([y 4]) y))]) x) - (let ([x (add1 (letrec ([y (lambda () 4)]) (y)))]) x) - (let ([x (+ (let ([y 4]) y) (let ([y 4]) y))]) (add1 x)) - (let ([z 0]) (let ([x z]) z x)) - (let ([z 0]) (let ([x (begin (let ([y 2]) (set! z y)) z)]) x)) - (let ([x (begin (let ([y 2]) (set! y y)) (let ([z 3]) z))]) x) - (letrec ([one (lambda (n) (if (zero? n) 1 (one (sub1 n))))]) - (one 13)) - (letrec ((even (lambda (x) (if (zero? x) #t (odd (sub1 x))))) - (odd (lambda (x) (if (zero? x) #f (even (sub1 x)))))) - (odd 13)) - (let ([t #t] [f #f]) - (letrec ((even (lambda (x) (if (zero? x) t (odd (sub1 x))))) - (odd (lambda (x) (if (zero? x) f (even (sub1 x)))))) - (odd 13))) - (let ((even (lambda (x) x))) - (even (letrec ((even (lambda (x) (if (zero? x) #t (odd (sub1 x))))) - (odd (lambda (x) (if (zero? x) #f (even (sub1 x)))))) - (odd 13)))) - (letrec ((fact (lambda (n) (if (zero? n) 1 (* n (fact (sub1 n))))))) - (fact 5)) - (let ([x 5]) - (letrec ([a (lambda (u v w) (if (zero? u) (b v w) (a (- u 1) v w)))] - [b (lambda (q r) - (let ([p (* q r)]) - (letrec - ([e (lambda (n) (if (zero? n) (c p) (o (- n 1))))] - [o (lambda (n) (if (zero? n) (c x) (e (- n 1))))]) - (e (* q r)))))] - [c (lambda (x) (* 5 x))]) - (a 3 2 1))) - (let ([f (lambda () 80)]) (let ([a (f)] [b (f)]) 0)) - (let ([f (lambda () 80)]) (let ([a (f)] [b (f)]) (* a b))) - (let ([f (lambda () 80)] [g (lambda () 80)]) - (let ([a (f)] [b (g)]) - (* a b))) - (let ((f (lambda (x) (add1 x))) - (g (lambda (x) (sub1 x))) - (t (lambda (x) (add1 x))) - (j (lambda (x) (add1 x))) - (i (lambda (x) (add1 x))) - (h (lambda (x) (add1 x))) - (x 80)) - (let ((a (f x)) (b (g x)) (c (h (i (j (t x)))))) - (* a (* b (+ c 0))))) - (let ((x 3000)) - (if (integer? x) - (let ((y (cons x '()))) - (if (if (pair? y) (null? (cdr y)) #f) - (+ x 5000) - (- x 3000))))) - (let ((x (cons 1000 2000))) - (if (pair? x) - (let ((temp (car x))) - (set-car! x (cdr x)) - (set-cdr! x temp) - (+ (car x) (cdr x))) - 10000000)) - (let ((v (make-vector 3))) - (vector-set! v 0 10) - (vector-set! v 1 20) - (vector-set! v 2 30) - (if (vector? v) - (+ (+ (vector-length v) (vector-ref v 0)) - (+ (vector-ref v 1) (vector-ref v 2))) - 10000)) - (let ([fact (lambda (fact n) - (if (zero? n) 1 (* (fact fact (sub1 n)) n)))]) - (fact fact 5)) - (let ([s (make-vector 20)]) - (vector-set! s 19 #\z) - (if (vector? s) - (+ 20 (let ([c #\z]) (if (char? c) 122))) - 10000)) - (let ([s (make-vector 20)]) - (vector-set! s 19 #\z) - (if (vector? s) - (+ (vector-length s) - (let ([c (vector-ref s 19)]) - (if (char? c) - (char->integer (vector-ref s 19))))) - 10000)) - (let ((s (make-vector 20)) (s2 (make-vector 3))) - (vector-set! s 19 #\z) - (vector-set! s 18 #\t) - (vector-set! s2 0 #\a) - (if (vector? s) - (+ (vector-length s) - (let ((c (vector-ref s 18))) - (if (char? c) - (+ (char->integer (vector-ref s 19)) - (char->integer c))))) - 10000)) - (let ([f (lambda (x) (+ x 1000))]) - (if (zero? (f -2)) (f 6000) (f (f 8000)))) - (let ([f (lambda (x) (+ x 1000))]) - (if (zero? (f -1)) (f 6000) (f (f 8000)))) - (let ((f (lambda (x y) (+ x 1000)))) - (+ (if (f 3000 (begin 0 0 0)) (f (f 4000 0) 0) 8000) 2000)) - ((((lambda (x) - (lambda (y) - (lambda (z) - (+ x (+ y (+ z y)))))) - 5) 6) 7) - ((((((lambda (x) - (lambda (y) - (lambda (z) - (lambda (w) - (lambda (u) - (+ x (+ y (+ z (+ w u))))))))) - 5) 6) 7) 8) 9) - (let ((f (lambda (x) x))) - (if (procedure? f) #t #f)) - (let ((sum (lambda (sum ls) - (if (null? ls) 0 (+ (car ls) (sum sum (cdr ls))))))) - (sum sum (cons 1 (cons 2 (cons 3 '()))))) - (let ((v (make-vector 5)) - (w (make-vector 7))) - (vector-set! v 0 #t) - (vector-set! w 3 #t) - (if (boolean? (vector-ref v 0)) - (vector-ref w 3) - #f)) - (let ((a 5) (b 4)) - (if (< b 3) - (eq? a (+ b 1)) - (if (<= b 3) - (eq? (- a 1) b) - (= a (+ b 2))))) - (let ((a 5) (b 4)) - (if #f (eq? a (+ b 1)) (if #f (eq? (- a 1) b) (= a (+ b 2))))) - (((lambda (a) (lambda () (+ a (if #t 200)) 1500)) 1000)) - (((lambda (b) (lambda (a) (set! a (if 1 2)) (+ a b))) 100) 200) - ((((lambda (a) - (lambda (b) - (set! a (if b 200)) - (lambda (c) (set! c (if 300 400)) - (+ a (+ b c))))) - 1000) 2000) 3000) - ((((lambda (a) (lambda (b) (lambda (c) (+ a (+ b c))))) 10) 20) 30) - (+ 2 3) - ((lambda (a) (+ 2 a)) 3) - (((lambda (b) (lambda (a) (+ b a))) 3) 2) - ((lambda (b) ((lambda (a) (+ b a)) 2)) 3) - ((lambda (f) (f (f 5))) (lambda (x) x)) - ((let ((f (lambda (x) (+ x 3000)))) (lambda (y) (f (f y)))) 2000) - (let ((n #\newline) (s #\space) (t #\tab)) - (let ((st (make-vector 5))) - (vector-set! st 0 n) - (vector-set! st 1 s) - (vector-set! st 2 t) - (if (not (vector? st)) - 10000 - (vector-length st)))) - (let ((s (make-vector 1))) - (vector-set! s 0 #\c) - (if (eq? (vector-ref s 0) #\c) 1000 2000)) - (not 17) - (not #f) - (let ([fact (lambda (fact n acc) - (if (zero? n) acc (fact fact (sub1 n) (* n acc))))]) - (fact fact 5 1)) - ((lambda (b c a) - (let ((b (+ b a)) (a (+ a (let ((a (+ b b)) (c (+ c c))) (+ a a))))) - (* a a))) 2 3 4) - (let ((f (lambda (x) (lambda () (x))))) ((f (lambda () 3)))) - (letrec ((f (lambda (x) (if (zero? x) 1 (* x (f (- x 1))))))) - (let ([q 17]) - (let ((g (lambda (a) (set! q 10) (lambda () (a q))))) - ((g f))))) - (letrec ((f (lambda (x) (if (zero? x) 1 (* x (f (- x 1))))))) - (let ((g (lambda (a) (lambda (b) (a b))))) - ((g f) 10))) - (letrec ((f (lambda () (+ a b))) - (g (lambda (y) (set! g (lambda (y) y)) (+ y y))) - (a 17) - (b 35) - (h (cons (lambda () a) (lambda (v) (set! a v))))) - (let ((x1 (f)) (x2 (g 22)) (x3 ((car h)))) - (let ((x4 (g 22))) - ((cdr h) 3) - (let ((x5 (f)) (x6 ((car h)))) - (cons x1 (cons x2 (cons x3 (cons x4 (cons x5 x6))))))))) - (letrec ((f (lambda () (+ a b))) - (a 17) - (b 35) - (h (cons (lambda () a) (lambda () b)))) - (cons (f) (cons a (cons b (cons ((car h)) ((cdr h))))))) - (letrec ((f (lambda (x) (letrec ((x 3)) 3)))) - (letrec ((g (lambda (x) (letrec ((y 14)) (set! y 7) y)))) - (set! g (cons g 3)) - (letrec ((h (lambda (x) x)) (z 42)) - (cons (cdr g) (h z))))) - (let ([t #t] [f #f]) - (let ([bools (cons t f)] [id (lambda (x) (if (not x) f t))]) - (letrec - ([even (lambda (x) (if (zero? x) (id (car bools)) (odd (- x 1))))] - [odd (lambda (y) (if (zero? y) (id (cdr bools)) (even (- y 1))))]) - (odd 5)))) - (letrec ([fib (lambda (x) - (let ([decrx (lambda () (set! x (- x 1)))]) - (if (< x 2) - 1 - (+ (begin (decrx) (fib x)) - (begin (decrx) (fib x))))))]) - (fib 10)) - (letrec ([fib (lambda (x) - (let ([decrx (lambda () (lambda (i) (set! x (- x i))))]) - (if (< x 2) - 1 - (+ (begin ((decrx) 1) (fib x)) - (begin ((decrx) 1) (fib x))))))]) - (fib 10)) - ;; Jie Li - (let ((a 5)) - (let ((b (cons a 6))) - (let ((f (lambda(x) (* x a)))) - (begin (if (- (f a) (car b)) - (begin (set-car! b (if (not a) (* 2 a) (+ 2 a))) - (f a)) - (if (not (not (< (f a) b))) (f a))) - (not 3) - (void) - (f (car b)))))) - (letrec ([f (lambda (x y) - (if (not x) (g (add1 x) (add1 y)) (h (+ x y))))] - [g (lambda (u v) - (let ([a (+ u v)] [b (* u v)]) - (letrec ([e (lambda (d) - (letrec ([p (cons a b)] - [q (lambda (m) - (if (< m u) - (f m d) - (h (car p))))]) - (q (f a b))))]) - (e u))))] - [h (lambda (w) w)]) - (f 4 5)) - (letrec ((f (lambda (x) - (+ x (((lambda (y) - (lambda (z) - (+ y z))) - 6) 7)))) - (g (+ 5 ((lambda (w u) (+ w u)) 8 9)))) - g) - ;; Jordan Johnson - (let ((test (if (not (not 10)) #f 5))) - (letrec ([num 5] - [length - (lambda (ls) - (let ((len (if ((lambda (ck) - (begin ck (set! num test) ck)) - (null? ls)) - (begin num (set! num 0) num) - (begin (length '()) - (set! num 5) - (+ 1 (length (cdr ls))))))) - (if len len)))]) - (length (cons 5 (cons (if (set! num 50) (length (cons test '())) 1) - '()))))) - (letrec ([quotient (lambda (x y) - (if (< x 0) - (- 0 (quotient (- 0 x) y)) - (if (< y 0) - (- 0 (quotient x (- 0 y))) - (letrec ([f (lambda (x a) - (if (< x y) - a - (f (- x y) (+ a 1))))]) - (f x 0)))))]) - (letrec ([sub-interval 1] - [sub-and-continue - (lambda (n acc k) (k (- n sub-interval) (* n acc)))] - [strange-fact - (lambda (n acc) - (if (zero? n) - (lambda (proc) (proc acc)) - (sub-and-continue n acc strange-fact)))]) - (let ([x 20] - [fact (let ((seed 1)) (lambda (n) (strange-fact n seed)))]) - (let ([give-fact5-answer (fact 5)] - [give-fact6-answer (fact 6)] - [answer-user (lambda (ans) (quotient ans x))]) - (set! x (give-fact5-answer answer-user)) - (begin (set! x (give-fact6-answer answer-user)) x))))) - (let ((y '()) (z 10)) - (let ((test-ls (cons 5 y))) - (set! y (lambda (f) - ((lambda (g) (f (lambda (x) ((g g) x)))) - (lambda (g) (f (lambda (x) ((g g) x))))))) - (set! test-ls (cons z test-ls)) - (letrec ((length (lambda (ls) - (if (null? ls) 0 (+ 1 (length (cdr ls))))))) - (let ((len (length test-ls))) - (eq? (begin - (set! length (y (lambda (len) - (lambda (ls) - (if (null? ls) - 0 - (+ 1 (len (cdr ls)))))))) - (length test-ls)) - len))))) - ;; Ryan Newton - (letrec ((loop (lambda () (lambda () (loop))))) (loop) 0) - (letrec ([f (lambda () - (letrec ([loop - (lambda (link) - (lambda () - (link)))]) - (loop (lambda () 668))))]) - ((f))) - ;; AWK - the following test uses the syntax #36rgood and #36rbad, - ;; which the ikarus reader seems to choak on, so I'm commenting out - ;; this test for now. - ; (if (lambda () 1) - ; (let ((a 2)) - ; (if (if ((lambda (x) - ; (let ((x (set! a (set! a 1)))) - ; x)) 1) - ; (if (eq? a (void)) - ; #t - ; #f) - ; #f) - ; #36rgood ; dyb: cannot use symbols, so use radix 36 - ; #36rbad))) ; syntax to make all letters digits - - ; contributed by Ryan Newton - (letrec ([dropsearch - (lambda (cell tree) - (letrec ([create-link - (lambda (node f) - (lambda (g) - (if (not (pair? node)) - (f g) - (if (eq? node cell) - #f - (f (create-link - (car node) - (create-link - (cdr node) g)))))))] - [loop - (lambda (link) - (lambda () - (if link - (loop (link (lambda (v) v))) - #f)))]) - (loop (create-link tree (lambda (x) x)))))] - [racethunks - (lambda (thunkx thunky) - (if (if thunkx thunky #f) - (racethunks (thunkx) (thunky)) - (if thunky - #t - (if thunkx - #f - '()))))] - [higher? (lambda (x y tree) - (racethunks (dropsearch x tree) - (dropsearch y tree)))] - [under? - (lambda (x y tree) - (racethunks (dropsearch x y) - (dropsearch x tree)))] - [explore - (lambda (x y tree) - (if (not (pair? y)) - #t - (if (eq? x y) - #f ; takes out anything pointing to itself - (let ((result (higher? x y tree))) - (if (eq? result #t) - (if (explore y (car y) tree) - (explore y (cdr y) tree) - #f) - (if (eq? result #f) - (process-vertical-jump x y tree) - (if (eq? result '()) - (process-horizontal-jump x y tree) - )))))))] - [process-vertical-jump - (lambda (jumpedfrom jumpedto tree) - (if (under? jumpedfrom jumpedto tree) - #f - (fullfinite? jumpedto)))] - [process-horizontal-jump - (lambda (jumpedfrom jumpedto tree) - (fullfinite? jumpedto))] - [fullfinite? - (lambda (pair) - (if (not (pair? pair)) - #t - (if (explore pair (car pair) pair) - (explore pair (cdr pair) pair) - #f)))]) - (cons (fullfinite? (cons 1 2)) - (cons (fullfinite? (let ((x (cons 1 2))) (set-car! x x) x)) - (cons (fullfinite? - (let ([a (cons 0 0)] [b (cons 0 0)] [c (cons 0 0)]) - (set-car! a b) (set-cdr! a c) (set-cdr! b c) - (set-car! b c) (set-car! c b) (set-cdr! c b) a)) - '())))))) - - (define final-tests - ; extracted tests from assignment writeups - '(75 - (+ 16 32) - (* 16 128) - (let ((x 16) (y 128)) (* x y)) - (let ([x 17]) (+ x x)) (cons 16 32) (cdr (cons 16 32)) - (let ((x (cons 16 32))) (pair? x)) - (let ([x 3]) (let ([y (+ x (quote 4))]) (+ x y))) - (let ([f (lambda (x) x)]) (let ([a 1]) (* (+ (f a) a) a))) - (let ([k (lambda (x y) x)]) - (let ([b 17]) ((k (k k 37) 37) b (* b b)))) - (let ([f (lambda () - (let ([n 256]) - (let ([v (make-vector n)]) - (vector-set! v 32 n) - (vector-ref v 32))))]) - (pair? (f))) - (let ((w 4) (x 8) (y 16) (z 32)) - (let ((f (lambda () - (+ w (+ x (+ y z)))))) - (f))) - (let ((f (lambda (g u) (g (if u (g 37) u))))) - (f (lambda (x) x) 75)) - (let ((f (lambda (h u) (h (if u (h (+ u 37)) u)))) (w 62)) - (f (lambda (x) (- w x)) (* 75 w))) - (let ([t #t] [f #f]) - (let ([bools (cons t f)] [id (lambda (x) (if (not x) f t))]) - (letrec - ([even (lambda (x) (if (id (zero? x)) (car bools) (odd (- x 1))))] - [odd (lambda (y) (if (zero? y) (id (cdr bools)) (even (- y 1))))]) - (odd 5)))) - ((lambda (x y z) - (let ((f (lambda (u v) (begin (set! x u) (+ x v)))) - (g (lambda (r s) (begin (set! y (+ z s)) y)))) - (* (f '1 '2) (g '3 '4)))) - '10 '11 '12) - ((lambda (x y z) - (let ((f '#f) - (g (lambda (r s) (begin (set! y (+ z s)) y)))) - (begin - (set! f - (lambda (u v) (begin (set! v u) (+ x v)))) - (* (f '1 '2) (g '3 '4))))) - '10 '11 '12) - (letrec ((f (lambda (x) (+ x 1))) - (g (lambda (y) (f (f y))))) - (+ (f 1) (g 1))) - (let ((y 3)) - (letrec - ((f (lambda (x) (if (zero? x) (g (+ x 1)) (f (- x y))))) - (g (lambda (x) (h (* x x)))) - (h (lambda (x) x))) - (g 39))) - (letrec ((f (lambda (x) (+ x 1))) (g (lambda (y) (f (f y))))) - (set! f (lambda (x) (- x 1))) - (+ (f 1) (g 1))) - (letrec ([f (lambda () (+ a b))] - [a 17] - [b 35] - [h (cons (lambda () a) (lambda () b))]) - (cons (f) (cons a (cons b (cons ((car h)) ((cdr h))))))) - (let ((v (make-vector 8))) - (vector-set! v 0 '()) - (vector-set! v 1 (void)) - (vector-set! v 2 #f) - (vector-set! v 3 #\a) - (vector-set! v 4 #\z) - (vector-set! v 5 #t) - (vector-set! v 6 2) - (vector-set! v 7 5) - (vector-ref v (vector-ref v 6))) - (let ([x 5] [th (let ((a 1)) (lambda () a))]) - (letrec ([fact (lambda (n th) - (if (zero? n) (th) (* n (fact (- n 1) th))))]) - (fact x th))) - (let ([negative? (lambda (n) (< n 0))]) - (letrec - ([fact (lambda (n) - (if (zero? n) 1 (* n (fact (- n 1)))))] - [call-fact (lambda (n) - (if (not (negative? n)) - (fact n) - (- 0 (fact (- 0 n)))))]) - (cons (call-fact 5) (call-fact -5)))) - (letrec ([iota-fill! (lambda (v i n) - (if (not (= i n)) - (begin - (vector-set! v i i) - (iota-fill! v (+ i 1) n))))]) - (let ([n 4]) - (let ([v (make-vector n)]) (iota-fill! v 0 n) v))) - ; make-vector with non-constant operand and improper alignment - (let ([x 6]) - (let ([v (make-vector x)]) - (vector-set! v 0 3) - (vector-set! v 1 (cons (vector-ref v 0) 2)) - (vector-set! v 2 (cons (vector-ref v 1) 2)) - (vector-set! v 3 (cons (vector-ref v 2) 2)) - (vector-set! v 4 (cons (vector-ref v 3) 2)) - (vector-set! v 5 (cons (vector-ref v 4) 2)) - (cons (pair? (vector-ref v 5)) (car (vector-ref v 4))))) - ; nest some lambdas - (((((lambda (a) - (lambda (b) - (lambda (c) - (lambda (d) - (cons (cons a b) (cons c d)))))) - 33) 55) 77) 99) - ; stress the register allocator - (let ((a 17)) - (let ((f (lambda (x) - (let ((x1 (+ x 1)) (x2 (+ x 2))) - (let ((y1 (* x1 7)) (y2 (* x2 7))) - (let ((z1 (- y1 x1)) (z2 (- y2 x2))) - (let ((w1 (* z1 a)) (w2 (* z2 a))) - (let ([g (lambda (b) - (if (= b a) - (cons x1 (cons y1 (cons z1 '()))) - (cons x2 (cons y2 (cons z2 '())))))] - [h (lambda (c) - (if (= c x) w1 w2))]) - (if (if (= (* x x) (+ x x)) - #t - (< x 0)) - (cons (g 17) (g 16)) - (cons (h x) (h (- x 0)))))))))))) - (cons (f 2) (cons (f -1) (cons (f 3) '()))))) - ; printer - (letrec - ([write - (lambda (x) - (let ([digits - (let ([v (make-vector 10)]) - (vector-set! v 0 #\0) - (vector-set! v 1 #\1) - (vector-set! v 2 #\2) - (vector-set! v 3 #\3) - (vector-set! v 4 #\4) - (vector-set! v 5 #\5) - (vector-set! v 6 #\6) - (vector-set! v 7 #\7) - (vector-set! v 8 #\8) - (vector-set! v 9 #\9) - v)]) - (letrec - ([list->vector - (lambda (ls) - (let ([v (make-vector (length ls))]) - (letrec - ([loop - (lambda (ls i) - (if (null? ls) - v - (begin - (vector-set! v i (car ls)) - (loop (cdr ls) (+ i 1)))))]) - (loop ls 0))))] - [length - (lambda (ls) - (if (null? ls) - 0 - (add1 (length (cdr ls)))))] - [map - (lambda (p ls) - (if (null? ls) - '() - (cons (p (car ls)) - (map p (cdr ls)))))] - [wr (lambda (x p) - (if (eq? x #f) - (cons #\# (cons #\f p)) - (if (eq? x #t) - (cons #\# (cons #\t p)) - (if (eq? x '()) - (cons #\( (cons #\) p)) - (if (eq? x (void)) - (cons #\# (cons #\< (cons #\v - (cons #\o (cons #\i (cons #\d - (cons #\> p))))))) - (if (char? x) - (cons #\# (cons #\\ - (if (eq? x #\newline) - (cons #\n (cons #\e (cons #\w - (cons #\l (cons #\i (cons #\n - (cons #\e p))))))) - (if (eq? x #\space) - (cons #\s (cons #\p - (cons #\a (cons #\c - (cons #\e p))))) - (if (eq? x #\tab) - (cons #\t (cons #\a - (cons #\b p))) - (cons x p)))))) - (if (integer? x) - (if (< x 0) - (cons #\- (wrint (- 0 x) p)) - (wrint x p)) - (if (pair? x) - (cons #\( ; ) - (letrec - ([loop - (lambda (x) - (wr (car x) - (if (pair? (cdr x)) - (cons #\space - (loop - (cdr x))) - (if - (null? - (cdr x)) - ;( - (cons #\) p) - (cons - #\space - (cons - #\. - (cons - #\space - (wr - (cdr - x) - ;( - (cons - #\) - p) - )))) - ))))]) - (loop x))) - (if (vector? x) - (cons #\# (cons #\( ; ) - (let - ([n (vector-length - x)]) - (if (= n 0) ;( - (cons #\) p) - (letrec - ([loop - (lambda (i) - (wr - (vector-ref - x i) - (if - (= - (+ - i - 1) - n) - ;( - (cons - #\) - p) - (cons - #\space - (loop - (+ - i - 1)) - ))) - )]) - (loop 0)))))) - (if (procedure? x) - (cons #\# (cons #\< - (cons #\p (cons #\r - (cons #\o - (cons #\c - (cons #\e - (cons #\d - (cons #\u - (cons - #\r - (cons - #\e - (cons - #\> - p) - ))) - )))))))) - (cons #\# (cons #\< - (cons #\g (cons #\a - (cons #\r - (cons #\b - (cons #\a - (cons #\g - (cons #\e - (cons - #\> - p)))) - ))))))))) - )))))))] - [wrint (lambda (n p) - (if (< n 10) - (cons (vector-ref digits n) p) - (wrint - (quotient n 10) - (cons (vector-ref digits - (remainder n 10)) p))))] - [remainder (lambda (x y) - (let ([q (quotient x y)]) (- x (* y q))))] - [quotient (lambda (x y) - (if (< x 0) - (- 0 (quotient (- 0 x) y)) - (if (< y 0) - (- 0 (quotient x (- 0 y))) - (letrec ([f (lambda (x a) - (if (< x y) - a - (f (- x y) (+ a 1))))]) - (f x 0)))))]) - (list->vector (map (lambda (x) - (char->integer x)) - (wr x '()))))))]) - (write - (let ([v1 (make-vector 4)] [v2 (make-vector 0)]) - (vector-set! v1 0 #\a) - (vector-set! v1 1 #\space) - (vector-set! v1 2 #\newline) - (vector-set! v1 3 #\tab) - (cons (cons 0 (cons 4 (cons 2334 -98765))) - (cons (cons #t (cons #f (cons (void) (cons '() '())))) - (cons v1 (cons v2 write)))))))))) diff --git a/ta6ob/nanopass/tests/compiler-test.ss b/ta6ob/nanopass/tests/compiler-test.ss deleted file mode 100644 index 6a89775..0000000 --- a/ta6ob/nanopass/tests/compiler-test.ss +++ /dev/null @@ -1,63 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (tests compiler-test) - (export test-one test-all run-main-tests run-final-tests run-all-tests) - (import (rnrs) - (tests compiler) - (tests test-driver) - (tests alltests)) - - (define run-final-tests - (case-lambda - [() (run-final-tests #t)] - [(emit?) (run-final-tests emit? #f)] - [(emit? noisy?) (tests final-tests) (test-all emit? noisy?)])) - - (define run-main-tests - (case-lambda - [() (run-main-tests #t)] - [(emit?) (run-main-tests emit? #f)] - [(emit? noisy?) (tests main-tests) (test-all emit? noisy?)])) - - (define run-all-tests - (case-lambda - [() (run-all-tests #t #f)] - [(emit?) (run-all-tests emit? #f)] - [(emit? noisy?) (run-main-tests emit? noisy?) - (run-final-tests emit? noisy?)])) - - (passes - (define-passes - rename-vars/verify-legal - remove-implicit-begin - remove-unquoted-constant - remove-one-armed-if - uncover-settable - remove-impure-letrec - remove-set! - sanitize-binding - remove-anonymous-lambda - uncover-free - convert-closure - lift-letrec - explicit-closure - normalize-context - remove-complex-opera* - remove-anonymous-call - introduce-dummy-rp - remove-nonunary-let - return-of-set! - explicit-labels - ;unparse-l18 - ;introduce-registers - ;uncover-live - ;uncover-conflict - ;uncover-move - ;assign-register - ;rename-register - ;assign-frame - ;rename-frame - ;flatten-program - ;generate-code - ))) diff --git a/ta6ob/nanopass/tests/compiler.ss b/ta6ob/nanopass/tests/compiler.ss deleted file mode 100644 index b2f35ac..0000000 --- a/ta6ob/nanopass/tests/compiler.ss +++ /dev/null @@ -1,1456 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (tests compiler) - (export - ;; languages - LP L0 L1 L2 L3 L4 L5 L6 L7 L8 L9 L10 L11 L12 L13 L14 L15 L16 L17 L18 - - ;; parsers - parse-LP parse-L0 parse-L1 parse-L2 parse-L3 parse-L4 parse-L5 parse-L6 - parse-L7 parse-L8 parse-L9 parse-L10 parse-L11 parse-L13 parse-L14 - parse-L15 parse-L16 parse-L17 parse-L18 - - ;; unparsers - unparse-LP unparse-L0 unparse-L1 unparse-L2 unparse-L3 unparse-L4 - unparse-L5 unparse-L6 unparse-L7 unparse-L8 unparse-L9 unparse-L10 - unparse-L11 unparse-L12 unparse-L13 unparse-L14 unparse-L15 unparse-L16 - unparse-L17 unparse-L18 - - ;; passes - verify-scheme remove-implicit-begin remove-unquoted-constant - remove-one-armed-if uncover-settable remove-impure-letrec remove-set! - sanitize-binding remove-anonymous-lambda uncover-free convert-closure - lift-letrec explicit-closure normalize-context remove-complex-opera* - remove-anonymous-call introduce-dummy-rp remove-nonunary-let - return-of-set! explicit-labels - - ;; preprocessor - rename-vars/verify-legal) - (import (rnrs) (nanopass) (tests helpers) (tests synforms) (nanopass nano-syntax-dispatch)) - - (define-language LP - (terminals - (variable (x)) - (datum (d)) - (user-primitive (pr))) - (Expr (e body) - d - x - pr - (set! x e) - (if e1 e2) - (if e1 e2 e3) - (begin e1 ... e2) - (lambda (x ...) body1 ... body2) - (let ((x e) ...) body1 ... body2) - (letrec ((x e) ...) body1 ... body2) - (e0 e1 ...))) - - (define-parser parse-LP LP) - - (define-language L0 (extends LP) - (Expr (e body) - (- d - x - pr - (e0 e1 ...)) - (+ (datum d) - (var x) - (primapp pr e ...) - (app e0 e1 ...)))) - - (define-parser parse-L0 L0) - - (define-who rename-vars/verify-legal - (lambda (expr) - (define keywords '(quote set! if begin let letrec lambda)) - (define extend-env* - (lambda (x* env) - (let f ([x* x*] [rx* '()] [env env]) - (if (null? x*) - (values (reverse rx*) env) - (let ([x (car x*)]) - (let ([rx (gen-symbol x)]) - (f (cdr x*) (cons rx rx*) (cons (cons x rx) env)))))))) - (let f ([expr expr] [env '()]) - (define f* (lambda (e* env) (map (lambda (e) (f e env)) e*))) - (with-output-language (L0 Expr) - (syncase expr - [,const (guard (constant? const)) `(datum ,const)] - [(quote ,lit) (guard (not (assq 'quote env))) `(datum ,lit)] - [,var - (guard (symbol? var)) - (cond - [(assq var env) => (lambda (a) `(var ,(cdr a)))] - [(memq var keywords) (error who "invalid reference to keyword" var)] - [else (error who "reference to unbound var" var)])] - [(set! ,var ,rhs) - (guard (not (assq 'set! env)) (symbol? var)) - (cond - [(assq var env) => (lambda (a) `(set! ,(cdr a) ,(f rhs env)))] - [(memq var keywords) (error who "set! of keyword" expr)] - [else (error who "set! of unbound var" expr)])] - [(if ,e0 ,e1) - (guard (not (assq 'if env))) - `(if ,(f e0 env) ,(f e1 env))] - [(if ,e0 ,e1 ,e2) - (guard (not (assq 'if env))) - `(if ,(f e0 env) ,(f e1 env) ,(f e2 env))] - [(begin ,e* ... ,e) - (guard (not (assq 'begin env))) - `(begin ,(f* e* env) ... ,(f e env))] - [(let ([,x* ,rhs*] ...) ,e* ... ,e) - (guard (for-all symbol? x*) (set? x*)) - (let-values ([(x* new-env) (extend-env* x* env)]) - `(let ([,x* ,(f* rhs* env)] ...) - ,(f* e* new-env) ... ,(f e new-env)))] - [(letrec ([,x* ,rhs*] ...) ,e* ... ,e) - (guard (for-all symbol? x*) (set? x*)) - (let-values ([(x* env) (extend-env* x* env)]) - `(letrec ([,x* ,(f* rhs* env)] ...) - ,(f* e* env) ... ,(f e env)))] - [(lambda (,x* ...) ,e* ... ,e) - (guard (not (assq 'lambda env)) (for-all symbol? x*) (set? x*)) - (let-values ([(x* env) (extend-env* x* env)]) - `(lambda (,x* ...) ,(f* e* env) ... ,(f e env)))] - [(,prim ,rand* ...) - (guard (not (assq prim env)) (user-primitive? prim) - (= (cadr (assq prim list-of-user-primitives)) (length rand*))) - `(primapp ,prim ,(f* rand* env) ...)] - [(,rator ,rand* ...) `(app ,(f rator env) ,(f* rand* env) ...)] - [else (error who "invalid expression" expr)]))))) - - (define-pass verify-scheme : LP (ir) -> L0 () - (definitions - (define invalid-var? - (lambda (x env) - (cond - [(memq x env) #f] - [(keyword? x) "keyword"] - [(user-primitive? x) "user-primitive"] - [else "unbound variable"]))) - - (define valid-bindings? - (lambda (ls) - (for-all variable? ls))) - - (define duplicate-names? - (lambda (var*) - (let f ([ls var*] [dups '()]) - (cond - [(null? ls) (if (null? dups) #f dups)] - [(and (memq (car ls) (cdr ls)) (not (memq (car ls) dups))) - (f (cdr ls) (cons (car ls) dups))] - [else (f (cdr ls) dups)])))) - (define format-list - (lambda (ls) - (case (length ls) - [(0) ""] - [(1) (format "~s" (car ls))] - [(2) (format "~s and ~s" (car ls) (cadr ls))] - [else (let f ([a (car ls)] [ls (cdr ls)]) - (if (null? ls) - (format "and ~s" a) - (format "~s, ~a" a (f (car ls) (cdr ls)))))])))) - (Expr : Expr (ir [env '()]) -> Expr () - [,d `(datum ,d)] - [,x (let ([invalid? (invalid-var? x env)]) - (if invalid? - (error 'verify-scheme (format "reference to ~a ~s" invalid? x)) - `(var ,x)))] - [(set! ,x ,e) - (let ([invalid? (invalid-var? x env)]) - (if invalid? - (error 'verify-scheme (format "assignment to ~a ~s" invalid? x)) - (let ([e (Expr e env)]) - `(set! ,x ,e))))] - [(lambda (,x ...) ,body1 ... ,body2) - (cond - [(not (valid-bindings? x)) - (error 'verify-scheme - (format "invalid binding list ~a in lambda form" x))] - [(duplicate-names? x) - => - (lambda (x) - (error 'verify-scheme - (format "duplicate bindings ~a in lambda form" - (format-list x))))] - [else - (let ([env (append env x)]) - (let ([body1 (map (lambda (x) (Expr x env)) body1)] - [body2 (Expr body2 env)]) - `(lambda (,x ...) ,body1 ... ,body2)))])] - [(let ((,x ,e) ...) ,body1 ... ,body2) ;; track variables - (cond - [(not (valid-bindings? x)) - (error 'verify-scheme - (format "invalid binding list ~a in let form" x))] - [(duplicate-names? x) - => - (lambda (x) - (error 'verify-scheme - (format "duplicate bindings ~a in let form" - (format-list x))))] - [else - (let ([e (map (lambda (x) (Expr x env)) e)]) - (let ([env (append env x)]) - (let ([body1 (map (lambda (x) (Expr x env)) body1)] - [body2 (Expr body2 env)]) - `(let ((,x ,e) ...) ,body1 ... ,body2))))])] - [(letrec ((,x ,e) ...) ,body1 ... ,body2) ;; track variables - (cond - [(not (valid-bindings? x)) - (error 'verify-scheme - (format "invalid binding list ~a in letrec form" x))] - [(duplicate-names? x) - => - (lambda (x) - (error 'verify-scheme - (format "duplicate bindings ~a in letrec form" - (format-list x))))] - [else - (let ([env (append env x)]) - (let ([e (map (lambda (x) (Expr x env)) e)]) - (let ([body1 (map (lambda (x) (Expr x env)) body1)] - [body2 (Expr body2 env)]) - `(letrec ((,x ,e) ...) ,body1 ... ,body2))))])] - [(,e0 ,e1 ...) - (let ([e1 (map (lambda (x) (Expr x env)) e1)]) - (if (and (symbol? e0) (user-primitive? e0)) - `(primapp ,e0 ,e1 ...) - `(app ,(Expr e0 env) ,e1 ...)))])) - - (define-language L1 (extends L0) - (Expr (e body) - (- (lambda (x ...) body1 ... body2) - (let ((x e) ...) body1 ... body2) - (letrec ((x e) ...) body1 ... body2)) - (+ (lambda (x ...) body) - (let ((x e) ...) body) - (letrec ((x e) ...) body)))) - - (define-parser parse-L1 L1) - - (define-pass remove-implicit-begin : L0 (ir) -> L1 () - (process-expr-expr : Expr (ir) -> Expr () - [(lambda (,x ...) ,[body1] ... ,[body2]) - `(lambda (,x ...) (begin ,body1 ... ,body2))] - [(let ((,x ,[e]) ...) ,[body1] ... ,[body2]) - `(let ((,x ,e) ...) (begin ,body1 ... ,body2))] - [(letrec ((,x ,[e]) ...) ,[body1] ... ,[body2]) - `(letrec ((,x ,e) ...) (begin ,body1 ... ,body2))])) - - (define-language L2 (extends L1) - (Expr (e body) - (- (datum d)) - (+ (quoted-const d)))) - - (define-parser parse-L2 L2) - - (define-pass remove-unquoted-constant : L1 (ir) -> L2 () - (process-expr-expr : Expr (ir) -> Expr () - [(datum ,d) `(quoted-const ,d)])) - - (define-language L3 (extends L2) (Expr (e body) (- (if e1 e2)))) - - (define-parser parse-L3 L3) - - (define-pass remove-one-armed-if : L2 (ir) -> L3 () - (process-expr-expr : Expr (ir) -> Expr () - [(if ,[e1] ,[e2]) `(if ,e1 ,e2 (primapp void))])) - - (define-language L4 (extends L3) - (Expr (e body) - (- (lambda (x ...) body) - (let ((x e) ...) body) - (letrec ((x e) ...) body)) - (+ (lambda (x ...) sbody) - (let ((x e) ...) sbody) - (letrec ((x e) ...) sbody))) - (SetBody (sbody) (+ (settable (x ...) body) => body))) - - (define-parser parse-L4 L4) - - (define-pass uncover-settable : L3 (ir) -> L4 () - (definitions - (define Expr* - (lambda (e* asgn-var*) - (if (null? e*) - (values '() asgn-var*) - (let-values ([(e asgn-var*) (Expr (car e*) asgn-var*)]) - (let-values ([(e* asgn-var*) (Expr* (cdr e*) asgn-var*)]) - (values (cons e e*) asgn-var*))))))) - (Expr : Expr (ir asgn-var*) -> Expr (asgn-var*) - [(set! ,x ,[e asgn-var*]) (values `(set! ,x ,e) (set-cons x asgn-var*))] - [(lambda (,x* ...) ,[body asgn-var*]) - (let ([set-x* (intersection asgn-var* x*)]) - (values `(lambda (,x* ...) (settable (,set-x* ...) ,body)) - (difference asgn-var* set-x*)))] - [(let ([,x* ,e*]...) ,[body asgn-var*]) - (let ([set-x* (intersection asgn-var* x*)]) - (let-values ([(e* asgn-var*) (Expr* e* (difference asgn-var* set-x*))]) - (values `(let ([,x* ,e*] ...) (settable (,set-x* ...) ,body)) asgn-var*)))] - [(letrec ([,x* ,e*]...) ,[body asgn-var*]) - (let-values ([(e* asgn-var*) (Expr* e* asgn-var*)]) - (let ([set-x* (intersection asgn-var* x*)]) - (values `(letrec ((,x* ,e*) ...) (settable (,set-x* ...) ,body)) - (difference asgn-var* set-x*))))] - ; TODO: this code used to be supported by the automatic combiners, we've - ; abandoned this in favor of threading, but we've not added threading yet - [(app ,[e asgn-var*] ,e* ...) - (let-values ([(e* asgn-var*) (Expr* e* asgn-var*)]) - (values `(app ,e ,e* ...) asgn-var*))] - [(primapp ,pr ,e* ...) - (let-values ([(e* asgn-var*) (Expr* e* asgn-var*)]) - (values `(primapp ,pr ,e* ...) asgn-var*))] - [(if ,[e0 asgn-var*] ,e1 ,e2) - (let-values ([(e1 asgn-var*) (Expr e1 asgn-var*)]) - (let-values ([(e2 asgn-var*) (Expr e2 asgn-var*)]) - (values `(if ,e0 ,e1 ,e2) asgn-var*)))] - [(begin ,e* ... ,[e asgn-var*]) - (let-values ([(e* asgn-var*) (Expr* e* asgn-var*)]) - (values `(begin ,e* ... ,e) asgn-var*))]) - (let-values ([(e asgn-var*) (Expr ir '())]) e)) - - (define-language L5 (extends L4) - (Expr (e body) - (+ lexpr - (letrec ((x lexpr) ...) body)) - (- (lambda (x ...) sbody) - (letrec ((x e) ...) sbody))) - (LambdaExpr (lexpr) (+ (lambda (x ...) sbody)))) - - (define-parser parse-L5 L5) - - (define-pass remove-impure-letrec : L4 (ir) -> L5 () - (process-expr-expr : Expr (ir) -> Expr () - [(lambda (,x ...) ,[sbody]) - (in-context LambdaExpr `(lambda (,x ...) ,sbody))] - [(letrec ((,x1 (lambda (,x2 ...) ,[sbody1])) ...) (settable () ,[body2])) - (let ([lambdabody (map - (lambda (x sbody) - (in-context LambdaExpr `(lambda (,x ...) ,sbody))) - x2 sbody1)]) - `(letrec ((,x1 ,lambdabody) ...) ,body2))] - [(letrec ((,x1 ,[e]) ...) (settable (,x2 ...) ,[body])) - (let () - (define void-maker - (lambda (ids) - (letrec ((helper (lambda (ls) - (if (null? (cdr ls)) - (list (in-context Expr `(primapp void))) - (cons (in-context Expr `(primapp void)) - (helper (cdr ls))))))) - (helper (iota (length ids)))))) - (let* ([new-ids (map gen-symbol x1)] - [voids (void-maker x1)] - [bodies (map (lambda (lhs id) - `(set! ,lhs (var ,id))) x1 new-ids)] - [rbodies (reverse bodies)] - [new-body (cdr rbodies)] - [rest-bodies (car rbodies)]) - `(let ([,x1 ,voids] ...) - (settable (,x1 ...) - (begin - (primapp void) - (let ([,new-ids ,e] ...) - ;;**** this need not be from the output nonterminal **** - (settable () - (begin ,new-body ... ,rest-bodies))) - ,body)))))]) - (process-setbody-setbody : SetBody (ir) -> SetBody () - [(settable (,x ...) ,[body]) `(settable (,x ...) ,body)]) - (process-expr-lexpr : Expr (ir) -> LambdaExpr () - [(lambda (,x ...) ,[sbody]) `(lambda (,x ...) ,sbody)]) - (process-setbody-expr : SetBody (ir) -> Expr () - [(settable (,x ...) ,[body]) `,body])) - - (define-language L6 (extends L5) - (Expr (e body) - (- (let ((x e) ...) sbody) - (set! x e)) - (+ (let ((x e) ...) body))) - (LambdaExpr (lexpr) - (- (lambda (x ...) sbody)) - (+ (lambda (x ...) body))) - (SetBody (sbody) (- (settable (x ...) body)))) - - (define-parser parse-L6 L6) - - (define-pass remove-set! : L5 (ir) -> L6 () - (Expr : Expr (ir [set* '()]) -> Expr () - [(var ,x) (if (memq x set*) `(primapp car (var ,x)) `(var ,x))] - [(set! ,x ,[e set* -> e]) `(primapp set-car! (var ,x) ,e)] - [(let ((,x ,[e set* -> e]) ...) ,sbody) - (let ([body (SetBody sbody x e set*)]) - `,body)]) - (LambdaExpr : LambdaExpr (ir set*) -> LambdaExpr () - [(lambda (,x ...) ,[sbody x '() set* -> body]) `,body]) - (SetBody : SetBody (ir x* e* set*) -> Expr () - [(settable () ,[body set* -> body]) - (if (null? e*) - `(lambda (,x* ...) ,body) - `(let ([,x* ,e*] ...) ,body))] - [(settable (,x ...) ,[body (append x set*) -> body]) - (let () - (define settable-bindings - (lambda (var* set*) - (if (null? var*) (values '() '() '()) - (let ([var (car var*)]) - (let-values ([(var* lhs* rhs*) - (settable-bindings (cdr var*) set*)]) - (if (memq var set*) - (let ([tmp (gen-symbol var)]) - (values (cons tmp var*) - (cons var lhs*) - (cons (in-context - Expr - `(primapp cons (var ,tmp) - (primapp void))) rhs*))) - ;; **** (primapp void) is still a problem here **** - (values (cons var var*) lhs* rhs*))))))) - (let-values ([(x* lhs* rhs*) (settable-bindings x* x)]) - ;; **** cannot have (let (,(apply append bindings*)) ---) or - ;; some such, due to nano-syntax-dispatch - ;; the problem is not that we don't allow ,(arbitrary - ;; function call) in the metaparser - (if (null? e*) - `(lambda (,x* ...) (let ([,lhs* ,rhs*] ...) ,body)) - `(let ([,x* ,e*] ...) (let ([,lhs* ,rhs*] ...) ,body)))))])) - - (define-pass sanitize-binding : L6 (ir) -> L6 () - (Expr : Expr (ir [rhs? #f]) -> Expr (#f) - [(var ,x) (values `(var ,x) #f)] - [(if ,[e1 #f -> e1 ig1] ,[e2 #f -> e2 ig2] ,[e3 #f -> e3 ig3]) - (values `(if ,e1 ,e2 ,e3) #f)] - [(begin ,[e1 #f -> e1 ig1] ... ,[e2 #f -> e2 ig2]) - (values `(begin ,e1 ... ,e2) #f)] - [(primapp ,pr ,[e #f -> e ig] ...) (values `(primapp ,pr ,e ...) #f)] - [(app ,[e0 #f -> e0 ig0] ,[e1 #f -> e1 ig1] ...) - (values `(app ,e0 ,e1 ...) #f)] - [(quoted-const ,d) (values `(quoted-const ,d) #f)] - [(let ([,x ,[e #t -> e lambda?]] ...) ,[body #f -> body ig]) - (let-values ([(let-x* let-e* letrec-x* letrec-e*) - (let f ([x x] [e e] [lambda? lambda?]) - (if (null? x) - (values '() '() '() '()) - (let-values ([(let-x let-e letrec-x letrec-e) - (f (cdr x) (cdr e) (cdr lambda?))]) - (let ([lhs (car x)] - [rhs (car e)] - [rhs-lambda? (car lambda?)]) - (if rhs-lambda? - (values let-x let-e (cons lhs letrec-x) - (cons rhs letrec-e)) - (values (cons lhs let-x) (cons rhs let-e) - letrec-x letrec-e))))))]) - (if (null? letrec-x*) - (values `(let ([,let-x* ,let-e*] ...) ,body) #f) - (if (null? let-x*) - (values `(letrec ([,letrec-x* ,letrec-e*] ...) ,body) #f) - (values `(letrec ([,letrec-x* ,letrec-e*] ...) - (let ([,let-x* ,let-e*] ...) ,body)) #f))))] - [(letrec ([,x1 (lambda (,x2 ...) ,[body1 #f -> body1 ig1])] ...) - ,[body2 #f -> body2 ig2]) - (values `(letrec ([,x1 (lambda (,x2 ...) ,body1)] ...) ,body2) #f)]) - (LambdaExpr : LambdaExpr (ir [rhs? #f]) -> LambdaExpr (dummy) - [(lambda (,x ...) ,[body #f -> body ig]) - (values `(lambda (,x ...) ,body) #t)])) - - (define-language L7 (extends L6) (Expr (e body) (- lexpr))) - - (define-parser parse-L7 L7) - - (define-pass remove-anonymous-lambda : L6 (ir) -> L7 () - (Expr : Expr (ir) -> Expr () - [(lambda (,x ...) ,[body]) - (let ([anon (gen-symbol 'anon)]) - `(letrec ([,anon (lambda (,x ...) ,body)]) (var ,anon)))])) - -#; - (define-pass remove-anonymous-lambda : L6 (ir) -> L7 () - (Expr : Expr (ir) -> Expr () - [(lambda (,x ...) ,[body]) - (let ([anon (gen-symbol 'anon)]) - `(letrec ([,anon (lambda (,x ...) ,body)]) (var ,anon)))] - [(var ,x) `(var ,x)] - [(quoted-const ,d) `(quoted-const ,d)] - [(if ,[e1] ,[e2] ,[e3]) `(if ,e1 ,e2 ,e3)] - [(begin ,[e1] ... ,[e2]) `(begin ,e1 ... ,e2)] - [(let ([,x ,[e]] ...) ,[body]) `(let ([,x ,e] ...) ,body)] - [(letrec ([,x ,[lexpr]] ...) ,[body]) - `(letrec ([,x ,lexpr] ...) ,body)] - [(primapp ,pr ,[e] ...) `(primapp ,pr ,e ...)] - [(app ,[e0] ,[e1] ...) `(app ,e0 ,e1 ...)]) - (LambdaExpr : LambdaExpr (ir) -> LambdaExpr () - [(lambda (,x ...) ,[body]) `(lambda (,x ...) ,body)])) - - (define-language L8 (extends L7) - (entry Expr) - (LambdaExpr (lexpr) (- (lambda (x ...) body))) - (FreeExp (free-body) (+ (free (x ...) body) => body)) - (LambdaExpr (lexpr) (+ (lambda (x ...) free-body)))) - - (define-parser parse-L8 L8) - - (define-pass uncover-free : L7 (ir) -> L8 () - (definitions - (define LambdaExpr* - (lambda (lexpr* free*) - (if (null? lexpr*) - (values '() free*) - (let-values ([(lexpr free*) (LambdaExpr (car lexpr*) free*)]) - (let-values ([(lexpr* free*) (LambdaExpr* (cdr lexpr*) free*)]) - (values (cons lexpr lexpr*) free*)))))) - (define Expr* - (lambda (e* free*) - (if (null? e*) - (values '() free*) - (let-values ([(e free*) (Expr (car e*) free*)]) - (let-values ([(e* free*) (Expr* (cdr e*) free*)]) - (values (cons e e*) free*))))))) - (Expr : Expr (ir free*) -> Expr (free*) - [(letrec ([,x* ,lexpr*] ...) ,[body free*]) - (let-values ([(e* free*) (LambdaExpr* lexpr* free*)]) - (values `(letrec ([,x* ,e*] ...) ,body) (difference free* x*)))] - [(let ([,x* ,e*] ...) ,[body free*]) - (let-values ([(e* free*) (Expr* e* (difference free* x*))]) - (values `(let ([,x* ,e*] ...) ,body) free*))] - [(var ,x) (values `(var ,x) (cons x free*))] - ; TODO: get threaded variables working so we don't need to do this by hand - [(app ,[e free*] ,e* ...) - (let-values ([(e* free*) (Expr* e* free*)]) - (values `(app ,e ,e* ...) free*))] - [(primapp ,pr ,e* ...) - (let-values ([(e* free*) (Expr* e* free*)]) - (values `(primapp ,pr ,e* ...) free*))] - [(if ,[e1 free*] ,e2 ,e3) - (let-values ([(e2 free*) (Expr e2 free*)]) - (let-values ([(e3 free*) (Expr e3 free*)]) - (values `(if ,e1 ,e2 ,e3) free*)))] - [(begin ,e* ... ,[e free*]) - (let-values ([(e* free*) (Expr* e* free*)]) - (values `(begin ,e* ... ,e) free*))]) - (LambdaExpr : LambdaExpr (ir free*) -> LambdaExpr (free*) - [(lambda (,x* ...) ,[body free*]) - (let ([free* (difference free* x*)]) - (values `(lambda (,x* ...) (free (,free* ...) ,body)) free*))]) - (let-values ([(e free*) (Expr ir '())]) e)) - - (define-language L9 - (terminals - (variable (x)) - (datum (d)) - (user-primitive (pr))) - (Expr (e body) - (var x) - (quoted-const d) - (if e1 e2 e3) - (begin e1 ... e2) - (let ((x e) ...) body) - (letrec ((x lexpr) ...) c-letrec) - (primapp pr e ...) - (app e0 e1 ...) - (anonymous-call e0 e1 ...)) - (LambdaExpr (lexpr) - (lambda (x ...) bf-body)) - (BindFree (bf-body) - (bind-free (x1 x2 ...) body)) - (Closure (c-exp) - (closure x1 x2 ...)) - (ClosureLetrec (c-letrec) - (closure-letrec ((x c-exp) ...) body))) - - (define-parser parse-L9 L9) - - (define-pass convert-closure : L8 (ir) -> L9 () - (Expr : Expr (ir [direct '()]) -> Expr () - [(app (var ,x) ,[e1 direct -> e1] ...) - (guard (assq x direct)) - `(app (var ,(cdr (assq x direct))) (var ,x) ,e1 ...)] - [(app ,[e0 direct -> e0] ,[e1 direct -> e1] ...) - `(anonymous-call ,e0 ,e1 ...)] - [(letrec ([,x1 (lambda (,x2 ...) (free (,x3 ...) ,body1))] ...) ,body2) - (let ([code-name* (map gen-label x1)] - [cp* (map (lambda (x) (gen-symbol 'cp)) x1)]) - (let* ([direct (append (map cons x1 code-name*) direct)] - [body1 (map (lambda (exp)(Expr exp direct)) body1)] - [bind-free* (map (lambda (cp formal* free* lbody) - (in-context LambdaExpr - `(lambda (,cp ,formal* ...) - (bind-free (,cp ,free* ...) - ,lbody)))) - cp* x2 x3 body1)] - [closure* (map (lambda (code-name free*) - (in-context Closure - `(closure ,code-name ,free* ...))) - code-name* x3)]) - `(letrec ([,code-name* ,bind-free*] ...) - (closure-letrec ([,x1 ,closure*] ...) - ,(Expr body2 direct)))))])) - - (define-language L10 (extends L9) - (entry LetrecExpr) - (LetrecExpr (lrexpr) (+ (letrec ((x lexpr) ...) e))) - (Expr (e body) - (- (letrec ((x lexpr) ...) c-letrec)) - (+ (closure-letrec ((x c-exp) ...) body))) - (ClosureLetrec (c-letrec) (- (closure-letrec ((x c-exp) ...) body)))) - - (define-parser parse-L10 L10) - - (define-pass lift-letrec : L9 (ir) -> L10 () - (definitions - (define Expr* - (lambda (e* binding*) - (if (null? e*) - (values '() binding*) - (let-values ([(e binding*) (Expr (car e*) binding*)]) - (let-values ([(e* binding*) (Expr* (cdr e*) binding*)]) - (values (cons e e*) binding*)))))) - (define LambdaExpr* - (lambda (lexpr* binding*) - (if (null? lexpr*) - (values '() binding*) - (let-values ([(lexpr binding*) (LambdaExpr (car lexpr*) binding*)]) - (let-values ([(lexpr* binding*) (LambdaExpr* (cdr lexpr*) binding*)]) - (values (cons lexpr lexpr*) binding*))))))) - (Expr : Expr (ir binding*) -> Expr (binding*) - ; TODO: we'd like to do this using variable threading! - [(var ,x) (values `(var ,x) binding*)] - [(quoted-const ,d) (values `(quoted-const ,d) binding*)] - [(if ,e1 ,e2 ,[e3 binding*]) - (let-values ([(e1 binding*) (Expr e1 binding*)]) - (let-values ([(e2 binding*) (Expr e2 binding*)]) - (values `(if ,e1 ,e2 ,e3) binding*)))] - [(begin ,e1 ... ,[e2 binding*]) - (let-values ([(e1 binding*) (Expr* e1 binding*)]) - (values `(begin ,e1 ... ,e2) binding*))] - [(let ([,x* ,e*] ...) ,[body binding*]) - (let-values ([(e* binding*) (Expr* e* binding*)]) - (values `(let ([,x* ,e*] ...) ,body) binding*))] - [(primapp ,pr ,e* ...) - (let-values ([(e* binding*) (Expr* e* binding*)]) - (values `(primapp ,pr ,e* ...) binding*))] - [(app ,[e binding*] ,e* ...) - (let-values ([(e* binding*) (Expr* e* binding*)]) - (values `(app ,e ,e* ...) binding*))] - [(anonymous-call ,[e binding*] ,e* ...) - (let-values ([(e* binding*) (Expr* e* binding*)]) - (values `(anonymous-call ,e ,e* ...) binding*))] - [(letrec ((,x* ,lexpr*) ...) ,[e binding*]) - (let-values ([(lexpr* binding*) (LambdaExpr* lexpr* binding*)]) - (values e (append (map cons x* lexpr*) binding*)))]) - (LambdaExpr : LambdaExpr (ir binding*) -> LambdaExpr (binding*) - [(lambda (,x* ...) ,[bf-body binding*]) - (values `(lambda (,x* ...) ,bf-body) binding*)]) - (BindFree : BindFree (ir binding*) -> BindFree (binding*) - [(bind-free (,x ,x* ...) ,[body binding*]) - (values `(bind-free (,x ,x* ...) ,body) binding*)]) - (ClosureLetrec : ClosureLetrec (ir binding*) -> Expr (binding*) - [(closure-letrec ([,x* ,[c-exp*]] ...) ,[body binding*]) - (values `(closure-letrec ([,x* ,c-exp*] ...) ,body) binding*)]) - (let-values ([(e binding*) (Expr ir '())]) - (let ([x* (map car binding*)] [e* (map cdr binding*)]) - `(letrec ([,x* ,e*] ...) ,e)))) - - (define-language L11 (extends L10) - (entry LetrecExpr) - (terminals - (+ (system-primitive (spr)))) - (Expr (e body) - (- (closure-letrec ((x c-exp) ...) body)) - (+ (sys-primapp spr e ...))) - (BindFree (bf-body) (- (bind-free (x1 x2 ...) body))) - (Closure (c-exp) (- (closure x1 x2 ...))) - (LambdaExpr (lexpr) - (- (lambda (x ...) bf-body)) - (+ (lambda (x ...) body)))) - - (define-parser parse-L11 L11) - - (define-pass explicit-closure : L10 (ir) -> L11 () - (LetrecExpr : LetrecExpr (ir) -> LetrecExpr () - [(letrec ((,x ,[lexpr]) ...) ,e) - (let ([e (Expr e '() '())]) `(letrec ((,x ,lexpr) ...) ,e))]) - - (Expr : Expr (ir [cp '()] [env '()]) -> Expr () - [(var ,x) - (let ([i (list-index x env)]) - (if (>= i 0) - `(sys-primapp closure-ref (var ,cp) (quoted-const ,i)) - `(var ,x)))] - [(closure-letrec ((,x ,[c-exp -> e free**]) ...) - ,[body cp env -> body]) - (let* ([e* (append (apply append - (map - (lambda (lhs free*) - (map - (lambda (i free) - `(sys-primapp - closure-set! - (var ,lhs) - (quoted-const ,i) - ,(let ([ind (list-index free env)]) - (if (>= ind 0) - `(sys-primapp - closure-ref - (var ,cp) - (quoted-const ,ind)) - `(var ,free))))) - (iota (length free*)) free*)) - x free**)) - (list body))]) - (let* ([re* (reverse e*)] [e1 (cdr re*)] [e2 (car re*)]) - `(let ([,x ,e] ...) (begin ,e1 ... ,e2))))]) - (BindFree : BindFree (ir) -> Expr () - [(bind-free (,x1 ,x2 ...) ,[body x1 x2 -> body]) `,body]) - (Closure : Closure (ir) -> Expr (dummy) - [(closure ,x1 ,x2 ...) - (values `(sys-primapp make-closure (var ,x1) - (quoted-const ,(length x2))) x2)]) - (LambdaExpr : LambdaExpr (ir) -> LambdaExpr () - [(lambda (,x ...) ,[bf-body -> body]) `(lambda (,x ...) ,body)])) - - (define-language L12 - (terminals - (variable (x)) - (datum (d)) - (value-primitive (vp)) - (predicate-primitive (pp)) - (effect-primitive (ep)) - (system-primitive (spr))) - (LetrecExpr (lrexpr) - (letrec ((x lexpr) ...) v)) - (LambdaExpr (lexpr) - (lambda (x ...) v)) - (Value (v) - (var x) - (quoted-const d) - (if p1 v2 v3) - (begin f0 ... v1) - (let ((x v1) ...) v2) - (primapp vp v ...) - (sys-primapp spr v ...) - (anonymous-call v0 v1 ...) - (app v0 v1 ...)) - (Predicate (p) - (true) - (false) - (if p1 p2 p3) - (begin f0 ... p1) - (let ((x v) ...) p) - (primapp pp v ...) - (sys-primapp spr v ...) - (anonymous-call v0 v1 ...) - (app v0 v1 ...)) - (Effect (f) - (nop) - (if p1 f2 f3) - (begin f0 ... f1) - (let ((x v) ...) f) - (primapp ep v ...) - (sys-primapp spr v ...) - (anonymous-call v0 v1 ...) - (app v0 v1 ...))) - - (define-parser parse-L12 L12) - - (define-pass normalize-context : L11 (ir) -> L12 () - (LetrecExpr : LetrecExpr (ir) -> LetrecExpr () - [(letrec ((,x ,[lexpr]) ...) ,[v]) `(letrec ((,x ,lexpr) ...) ,v)]) - (LambdaExpr : LambdaExpr (ir) -> LambdaExpr () - [(lambda (,x ...) ,[v]) `(lambda (,x ...) ,v)]) - (Value : Expr (ir) -> Value () - [(var ,x) `(var ,x)] - [(quoted-const ,d) `(quoted-const ,d)] - [(if ,[p0] ,[v1] ,[v2]) `(if ,p0 ,v1 ,v2)] - [(begin ,[f0] ... ,[v1]) `(begin ,f0 ... ,v1)] - [(let ((,x ,[v1]) ...) ,[v2]) `(let ((,x ,v1) ...) ,v2)] - [(primapp ,pr ,[p]) - (guard (equal? pr 'not)) - `(if ,p (quoted-const #f) (quoted-const #t))] - [(primapp ,pr ,[v0] ...) - (guard (predicate-primitive? pr)) - `(if (primapp ,pr ,v0 ...) (quoted-const #t) (quoted-const #f))] - [(primapp ,pr ,[v0] ...) - (guard (value-primitive? pr)) - `(primapp ,pr ,v0 ...)] - [(primapp ,pr ,[v0] ...) - (guard (effect-primitive? pr)) - `(begin (primapp ,pr ,v0 ...) (primapp void))] - [(sys-primapp ,spr ,[v0] ...) - (guard (predicate-primitive? spr)) - `(if (sys-primapp ,spr ,v0 ...) (quoted-const #t) (quoted-const #f))] - [(sys-primapp ,spr ,[v0] ...) - (guard (value-primitive? spr)) - `(sys-primapp ,spr ,v0 ...)] - [(sys-primapp ,spr ,[v0] ...) - (guard (effect-primitive? spr)) - `(begin (primapp ,spr ,v0 ...) (primapp void))] - [(anonymous-call ,[v0] ,[v1] ...) `(anonymous-call ,v0 ,v1 ...)] - [(app ,[v0] ,[v1] ...) `(app ,v0 ,v1 ...)]) - (Predicate : Expr (ir) -> Predicate () - [(var ,x) - `(if (primapp eq? (var ,x) (quoted-const #f)) (false) (true))] - [(quoted-const ,d) (if d `(true) `(false))] - [(if ,[p0] ,[p1] ,[p2]) `(if ,p0 ,p1 ,p2)] - [(begin ,[f0] ... ,[p1]) `(begin ,f0 ... ,p1)] - [(let ((,x ,[v]) ...) ,[p]) `(let ((,x ,v) ...) ,p)] - [(primapp ,pr ,[p]) (guard (equal? pr 'not)) `(if ,p (false) (true))] - [(primapp ,pr ,[v0] ...) - (guard (predicate-primitive? pr)) - `(primapp ,pr ,v0 ...)] - [(primapp ,pr ,[v0] ...) - (guard (value-primitive? pr)) - `(if (primapp eq? (primapp ,pr ,v0 ...) (quoted-const #f)) - (false) (true))] - [(primapp ,pr ,[v0] ...) - (guard (effect-primitive? pr)) - `(begin (primapp ,pr ,v0 ...)(true))] - [(sys-primapp ,spr ,[v0] ...) - (guard (predicate-primitive? spr)) - `(sys-primapp ,spr ,v0 ...)] - [(sys-primapp ,spr ,[v0] ...) - (guard (value-primitive? spr)) - `(if (primapp eq? (sys-primapp ,spr ,v0 ...) (quoted-const #f)) - (false) (true))] - [(sys-primapp ,spr ,[v0] ...) - (guard (effect-primitive? spr)) - `(begin (sys-primapp ,spr ,v0 ...)(true))] - [(anonymous-call ,[v0] ,[v1] ...) - `(if (primapp eq? (anonymous-call ,v0 ,v1 ...) (quoted-const #f)) - (false) (true))] - [(app ,[v0] ,[v1] ...) - `(if (primapp eq? (app ,v0 ,v1 ...) (quoted-const #f)) - (false) (true))]) - (Effect : Expr (ir) -> Effect () - [(var ,x) `(nop)] - [(quoted-const ,d) `(nop)] - [(if ,[p0] ,[f1] ,[f2]) `(if ,p0 ,f1 ,f2)] - [(begin ,[f0] ... ,[f1]) `(begin ,f0 ... ,f1)] - [(let ((,x ,[v]) ...) ,[f]) `(let ((,x ,v) ...) ,f)] - [(primapp ,pr ,[f]) (guard (equal? pr 'not)) f] - [(primapp ,pr ,[f0] ...) - (guard (or (predicate-primitive? pr) (value-primitive? pr))) - (if (null? f0) `(nop) `(begin ,f0 ... (nop)))] - [(primapp ,pr ,[v0] ...) - (guard (effect-primitive? pr)) - `(primapp ,pr ,v0 ...)] - [(sys-primapp ,spr ,[f0] ...) - (guard (or (predicate-primitive? spr) (value-primitive? spr))) - (if (null? f0) `(nop) `(begin ,f0 ... (nop)))] - [(sys-primapp ,spr ,[v0] ...) - (guard (effect-primitive? spr)) - `(sys-primapp ,spr ,v0 ...)] - [(anonymous-call ,[v0] ,[v1] ...) `(anonymous-call ,v0 ,v1 ...)] - [(app ,[v0] ,[v1] ...) `(app ,v0 ,v1 ...)])) - - (define-language L13 - (terminals - (variable (x)) - (datum (d)) - (value-primitive (vp)) - (predicate-primitive (pp)) - (effect-primitive (ep)) - (system-primitive (spr))) - (LetrecExpr (lrexpr) - (letrec ((x lexpr) ...) v)) - (LambdaExpr (lexpr) - (lambda (x ...) v)) - (Triv (t) - (var x) - (quoted-const d)) - (Value (v) - t - (if p1 v2 v3) - (begin f0 ... v1) - (let ((x v1) ...) v2) - (primapp vp t ...) - (sys-primapp spr t ...) - (anonymous-call t0 t1 ...) - (app t0 t1 ...)) - (Predicate (p) - (true) - (false) - (if p1 p2 p3) - (begin f0 ... p1) - (let ((x v) ...) p) - (primapp pp t ...) - (sys-primapp spr t ...) - (anonymous-call t0 t1 ...) - (app t0 t1 ...)) - (Effect (f) - (nop) - (if p1 f2 f3) - (begin f0 ... f1) - (let ((x v) ...) f) - (primapp ep t ...) - (sys-primapp spr t ...) - (anonymous-call t0 t1 ...) - (app t0 t1 ...))) - - (define-parser parse-L13 L13) - - (define-pass remove-complex-opera* : L12 (ir) -> L13 () - (definitions - (define remove-nulls - (lambda (ls) - (if (null? ls) - '() - (if (null? (car ls)) - (remove-nulls (cdr ls)) - (cons (car ls) (remove-nulls (cdr ls)))))))) - (LetrecExpr : LetrecExpr (ir) -> LetrecExpr () - [(letrec ((,x ,[lexpr]) ...) ,[v]) `(letrec ((,x ,lexpr) ...) ,v)]) - (LambdaExpr : LambdaExpr (ir) -> LambdaExpr () - [(lambda (,x ...) ,[v]) `(lambda (,x ...) ,v)]) - (Opera : Value (ir) -> Triv (dummy) - [(var ,x) (values `(var ,x) '())] - [(quoted-const ,d) (values `(quoted-const ,d) '())] - ; [,[v] (let ([tmp (gen-symbol 'tmp)]) - ; (values `(var ,tmp) - ; (list tmp (in-context Value `,v))))]) - [(if ,[p1] ,[v2] ,[v3]) - (let ([tmp (gen-symbol 'tmp)]) - (values `(var ,tmp) - (list tmp (in-context Value `(if ,p1 ,v2 ,v3)))))] - [(begin ,[f0] ... ,[v1]) - (let ([tmp (gen-symbol 'tmp)]) - (values `(var ,tmp) - (list tmp (in-context Value `(begin ,f0 ... ,v1)))))] - [(let ((,x ,[v1]) ...) ,[v2]) - (let ([tmp (gen-symbol 'tmp)]) - (values `(var ,tmp) - (list tmp (in-context Value `(let ((,x ,v1) ...) ,v2)))))] - [(primapp ,vp ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (let ([tmp (gen-symbol 'tmp)]) - (if (null? binding*) - (values `(var ,tmp) - (list tmp (in-context Value `(primapp ,vp ,t* ...)))) - (let ([x (map car binding*)] [v (map cadr binding*)]) - (values `(var ,tmp) - (list tmp - (in-context - Value `(let ((,x ,v) ...) - (primapp ,vp ,t* ...)))))))))] - [(sys-primapp ,spr ,[t* binding*]...) - (let ([binding* (remove-nulls binding*)]) - (let ([tmp (gen-symbol 'tmp)]) - (if (null? binding*) - (values `(var ,tmp) - (list tmp (in-context - Value `(sys-primapp ,spr ,t* ...)))) - (let ([x (map car binding*)][v (map cadr binding*)]) - (values - `(var ,tmp) - (list - tmp (in-context - Value `(let ((,x ,v) ...) - (sys-primapp ,spr ,t* ...)))))))))] - [(anonymous-call ,[v0 binding] ,[v1 binding*] ...) - (let ([binding* (remove-nulls (cons binding binding*))] - [tmp (gen-symbol 'tmp)]) - (if (null? binding*) - (values `(var ,tmp) - (list tmp (in-context Value - `(anonymous-call ,v0 ,v1 ...)))) - (let ([x (map car binding*)] [v (map cadr binding*)]) - (values `(var ,tmp) - (list tmp (in-context - Value - `(let ((,x ,v) ...) - (anonymous-call ,v0 ,v1 ...))))))))] - [(app ,[v0] ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (let ([tmp (gen-symbol 'tmp)]) - (if (null? binding*) - (values `(var ,tmp) - (list tmp (in-context Value `(app ,v0 ,t* ...)))) - (let ([x (map car binding*)] [v (map cadr binding*)]) - (values `(var ,tmp) - (list tmp - (in-context Value - `(let ((,x ,v) ...) - (app ,v0 ,t* ...)))))))))]) - (Value : Value (ir) -> Value () - [(var ,x) (in-context Triv `(var ,x))] - [(quoted-const ,d) (in-context Triv `(quoted-const ,d))] - [(if ,[p1] ,[v2] ,[v3]) `(if ,p1 ,v2 ,v3)] - [(begin ,[f0] ... ,[v1]) `(begin ,f0 ... ,v1)] - [(let ((,x ,[v1]) ...) ,[v2]) `(let ((,x ,v1) ...) ,v2)] - [(primapp ,vp ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (if (null? binding*) - `(primapp ,vp ,t* ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) - (primapp ,vp ,t* ...)))))] - [(sys-primapp ,spr ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (if (null? binding*) - `(sys-primapp ,spr ,t* ...) - (let ([x (map car binding*)][v (map cadr binding*)]) - `(let ((,x ,v) ...) - (sys-primapp ,spr ,t* ...)))))] - [(anonymous-call ,[t0 binding] ,[t1 binding*] ...) - (let ([binding* (remove-nulls (cons binding binding*))]) - (if (null? binding*) - `(anonymous-call ,t0 ,t1 ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) - (anonymous-call ,t0 ,t1 ...)))))] - [(app ,[v0] ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (if (null? binding*) - `(app ,v0 ,t* ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) (app ,v0 ,t* ...)))))]) - (Predicate : Predicate (ir) -> Predicate () - [(let ((,x ,[v]) ...) ,[p]) `(let ((,x ,v) ...) ,p)] - [(primapp ,pp ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (if (null? binding*) - `(primapp ,pp ,t* ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) - (primapp ,pp ,t* ...)))))] - [(sys-primapp ,spr ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (if (null? binding*) - `(sys-primapp ,spr ,t* ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) - (sys-primapp ,spr ,t* ...)))))] - [(anonymous-call ,[t0 binding] ,[t1 binding*]...) - (let ([binding* (remove-nulls (cons binding binding*))]) - (if (null? binding*) - `(anonymous-call ,t0 ,t1 ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) - (anonymous-call ,t0 ,t1 ...)))))] - [(app ,[v0] ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (if (null? binding*) - `(app ,v0 ,t* ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) (app ,v0 ,t* ...)))))]) - (Effect : Effect (ir) -> Effect () - [(let ((,x ,[v]) ...) ,[f]) `(let ((,x ,v) ...) ,f)] - [(primapp ,ep ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (if (null? binding*) - `(primapp ,ep ,t* ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) - (primapp ,ep ,t* ...)))))] - [(sys-primapp ,spr ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (if (null? binding*) - `(sys-primapp ,spr ,t* ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) - (sys-primapp ,spr ,t* ...)))))] - [(anonymous-call ,[t0 binding] ,[t1 binding*] ...) - (let ([binding* (remove-nulls (cons binding binding*))]) - (if (null? binding*) - `(anonymous-call ,t0 ,t1 ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) (anonymous-call ,t0 ,t1 ...)))))] - [(app ,[v0] ,[t* binding*] ...) - (let ([binding* (remove-nulls binding*)]) - (if (null? binding*) - `(app ,v0 ,t* ...) - (let ([x (map car binding*)] [v (map cadr binding*)]) - `(let ((,x ,v) ...) (app ,v0 ,t* ...)))))])) - - (define-language L14 (extends L13) - (entry LetrecExpr) - (Value (v) (- (anonymous-call t0 t1 ...))) - (Predicate (p) (- (anonymous-call t0 t1 ...))) - (Effect (f) (- (anonymous-call t0 t1 ...)))) - - (define-pass remove-anonymous-call : L13 (ir) -> L14 () - (Value : Value (ir) -> Value () - [(anonymous-call ,[t0] ,[t1] ...) - (let ([tmp (gen-symbol 'tmp)]) - `(let ([,tmp (sys-primapp procedure-code ,t0)]) - (app (var ,tmp) ,t0 ,t1 ...)))]) - (Predicate : Predicate (ir) -> Predicate () - [(anonymous-call ,[t0] ,[t1] ...) - (let ([tmp (gen-symbol 'tmp)]) - `(let ([,tmp (sys-primapp procedure-code ,t0)]) - (app (var ,tmp) ,t0 ,t1 ...)))]) - (Effect : Effect (ir) -> Effect () - [(anonymous-call ,[t0] ,[t1] ...) - (let ([tmp (gen-symbol 'tmp)]) - `(let ([,tmp (sys-primapp procedure-code ,t0)]) - (app (var ,tmp) ,t0 ,t1 ...)))])) - - (define-parser parse-L14 L14) - - (define-language L15 - (terminals - (variable (x)) - (datum (d)) - (value-primitive (vp)) - (predicate-primitive (pp)) - (effect-primitive (ep)) - (system-primitive (spr))) - (LetrecExpr (lrexpr) - (letrec ((x1 lexpr) ...) rnexpr)) - (RunExpr (rnexpr) - (run (x) tl)) - (LambdaExpr (lexpr) - (lambda (x ...) tl)) - (Triv (t) - (var x) - (quoted-const d)) - (Application (a) - (app t0 t1 ...)) - (Tail (tl) - (return t1 t2) - (if p1 tl2 tl3) - (begin f0 ... tl1) - (let ((x ntl1) ...) tl2) - (app t0 t1 ...)) - (Nontail (ntl) - t - (if p1 ntl2 ntl3) - (begin f0 ... ntl1) - (let ((x ntl1) ...) ntl2) - (primapp vp t ...) - (sys-primapp spr t ...) - (return-point x a)) - (Predicate (p) - (true) - (false) - (if p1 p2 p3) - (begin f0 ... p1) - (let ((x ntl) ...) p) - (primapp pp t ...) - (sys-primapp spr t ...)) - (Effect (f) - (nop) - (if p1 f2 f3) - (begin f0 ... f1) - (let ((x ntl) ...) f) - (primapp ep t ...) - (sys-primapp spr t ...) - (return-point x a))) - - (define-parser parse-L15 L15) - - ; (define process-tail - ; (lambda (expr rp) - ; (match expr - ; [(quote ,datum) `(return ,rp (quote ,datum))] - ; [,var (guard (symbol? var)) `(return ,rp ,var)] - ; [(if ,test ,[conseq] ,[altern]) - ; `(if ,(process-nontail test) ,conseq ,altern)] - ; [(begin ,expr* ...) - ; `(begin - ; ,@((foldl '()) - ; (lambda (expr) - ; (lambda (expr*) - ; (if (null? expr*) - ; (cons (process-tail expr rp) expr*) - ; (cons (process-nontail expr) expr*)))) - ; expr*))] - ; [(let ([,lhs* ,rhs*] ...) ,[body]) - ; (let ([rhs* (map process-nontail rhs*)]) - ; `(let ([,lhs* ,rhs*] ...) - ; ,body))] - ; [(,prim ,rand* ...) - ; (guard (primitive? prim)) - ; (let ([rand* (map process-nontail rand*)]) - ; (let ([tmp (gen-symbol 'tmp)]) - ; `(let ([,tmp (,prim ,rand* ...)]) - ; (return ,rp ,tmp))))] - ; [(,rator ,rand* ...) - ; (let ([rator (process-nontail rator)] - ; [rand* (map process-nontail rand*)]) - ; `(,rator ,rp ,rand* ...))] - ; [,expr (error 'insert-dummy-rp "Invalid expression: ~s" expr)]))) - ; (define process-nontail - ; (lambda (expr) - ; (match expr - ; [(quote ,datum) `(quote ,datum)] - ; [,var (guard (symbol? var)) `,var] - ; [(if ,[test] ,[conseq] ,[altern]) - ; `(if ,test ,conseq ,altern)] - ; [(begin ,[expr*] ...) `(begin ,expr* ...)] - ; [(let ([,lhs* ,[rhs*]] ...) ,[body]) - ; `(let ([,lhs* ,rhs*] ...) ,body)] - ; [(,prim ,[rand*] ...) - ; (guard (primitive? prim)) - ; `(,prim ,rand* ...)] - ; [(,[rator] ,[rand*] ...) - ; (let ([label (gen-label (gen-symbol 'lab))]) - ; `(return-point ,label - ; (,rator ,label ,rand* ...)))] - ; [,expr (error 'insert-dummy-rp "Invalid expression: ~s" expr)]))) - ; (define process-lambda - ; (lambda (expr) - ; (match expr - ; [(lambda (,formal* ...) ,body) - ; (let ([rp (gen-symbol 'rp)]) - ; `(lambda (,rp ,formal* ...) - ; ,(process-tail body rp)))]))) - ; (define process-letrec - ; (lambda (expr) - ; (match expr - ; [(letrec ([,lhs* ,rhs*] ...) ,body) - ; (let ([rhs* (map process-lambda rhs*)]) - ; (let ([rp (gen-symbol 'rp)]) - ; `(letrec ([,lhs* ,rhs*] ...) - ; (run (,rp) - ; ,(process-tail body rp)))))]))) - - (define-pass introduce-dummy-rp : L14 (ir) -> L15 () - (LetrecExpr : LetrecExpr (ir) -> LetrecExpr () - [(letrec ((,x ,[lexpr]) ...) ,[rnexpr]) - `(letrec ((,x ,lexpr) ...) ,rnexpr)]) - (LambdaExpr : LambdaExpr (ir) -> LambdaExpr () - [(lambda (,x ...) ,v) - (let ([rp (gen-symbol 'rp)]) - (let ([tl (ValueTail v rp)]) - `(lambda (,rp ,x ...) ,tl)))]) - (ValueRun : Value (ir) -> RunExpr () - [(var ,x) (let ([rp (gen-symbol 'rp)]) - `(run (,rp) (return (var ,rp) (var ,x))))] - [(quoted-const ,d) - (let ([rp (gen-symbol 'rp)]) - `(run (,rp) (return (var ,rp) (quoted-const ,d))))] - [(if ,[p1] ,v2 ,v3) - (let ([rp (gen-symbol 'rp)]) - (let ([tl2 (ValueTail v2 rp)] - [tl3 (ValueTail v3 rp)]) - `(run (,rp) (if ,p1 ,tl2 ,tl3))))] - [(begin ,[f0] ... ,v1) - (let ([rp (gen-symbol 'rp)]) - (let ([tl1 (ValueTail v1 rp)]) - `(run (,rp) (begin ,f0 ... ,tl1))))] - [(let ((,x ,[ntl1]) ...) ,v2) - (let ([rp (gen-symbol 'rp)]) - (let ([tl2 (ValueTail v2 rp)]) - `(run (,rp) (let ((,x ,ntl1) ...) ,tl2))))] - [(primapp ,vp ,[t] ...) - (let ([rp (gen-symbol 'rp)]) - (let ([tmp (gen-symbol 'tmp)]) - `(run (,rp) (let ([,tmp (primapp ,vp ,t ...)]) - (return (var ,rp) (var ,tmp))))))] - [(sys-primapp ,spr ,[t] ...) - (let ([rp (gen-symbol 'rp)]) - (let ([tmp (gen-symbol 'tmp)]) - `(run (,rp) (let ([,tmp (primapp ,spr ,t ...)]) - (return (var ,rp) (var ,tmp))))))] - [(app ,[t0] ,[t1] ...) - (let ([rp (gen-symbol 'rp)]) - `(run (,rp)(app ,t0 (var ,rp) ,t1 ...)))]) - (ValueTail : Value (ir rp) -> Tail () - [(var ,x) `(return (var ,rp) (var ,x))] - [(quoted-const ,d) `(return (var ,rp) (quoted-const ,d))] - [(if ,[p1] ,[ValueTail : v2 rp -> tl2] ,[ValueTail : v3 rp -> tl3]) - `(if ,p1 ,tl2 ,tl3)] - [(begin ,[f0] ... ,[ValueTail : v1 rp -> tl1]) `(begin ,f0 ... ,tl1)] - [(let ((,x ,[ntl1]) ...) ,[ValueTail : v2 rp -> tl2]) - `(let ((,x ,ntl1) ...) ,tl2)] - [(primapp ,vp ,[t] ...) - (let ([tmp (gen-symbol 'tmp)]) - `(let ([,tmp (primapp ,vp ,t ...)]) - (return (var ,rp) (var ,tmp))))] - [(sys-primapp ,spr ,[t] ...) - (let ([tmp (gen-symbol 'tmp)]) - `(let ([,tmp (primapp ,spr ,t ...)]) - (return (var ,rp) (var ,tmp))))] - [(app ,[t0] ,[t1] ...) `(app ,t0 (var ,rp) ,t1 ...)]) - (ValueNTail : Value (ir) -> Nontail () - [(if ,[p1] ,[ntl2] ,[ntl3]) `(if ,p1 ,ntl2 ,ntl3)] - [(begin ,[f0] ... ,[ntl1]) `(begin ,f0 ... ,ntl1)] - [(let ((,x ,[ntl1]) ...) ,[ntl2]) `(let ((,x ,ntl1) ...) ,ntl2)] - [(app ,[t0] ,[t1] ...) - (let ([label (gen-label (gen-symbol 'lab))]) - `(return-point ,label (app ,t0 (var ,label) ,t1 ...)))]) - (Predicate : Predicate (ir) -> Predicate () - [(let ((,x ,[ntl1]) ...) ,[p]) `(let ((,x ,ntl1) ...) ,p)]) - (Effect : Effect (ir) -> Effect () - [(let ((,x ,[ntl1]) ...) ,[f]) `(let ((,x ,ntl1) ...) ,f)] - [(app ,[t0] ,[t1] ...) - (let ([label (gen-label (gen-symbol 'lab))]) - `(return-point ,label (app ,t0 (var ,label) ,t1 ...)))])) - - (define-language L16 (extends L15) - (entry LetrecExpr) - (Tail (tl) - (- (let ((x ntl1) ...) tl2)) - (+ (let ((x ntl1)) tl2))) - (Nontail (ntl) - (- (let ((x ntl1) ...) ntl2)) - (+ (let ((x ntl1)) ntl2))) - (Predicate (p) - (- (let ((x ntl) ...) p)) - (+ (let ((x ntl)) p))) - (Effect (f) - (- (let ((x ntl) ...) f)) - (+ (let ((x ntl)) f)))) - - (define-parser parse-L16 L16) - - (define-pass remove-nonunary-let : L15 (ir) -> L16 () - (Tail : Tail (ir) -> Tail () - [(let ((,x ,[ntl]) ...) ,[tl]) - (let loop ([lhs* x] [rhs* ntl]) - (if (null? lhs*) - tl - (let ([x (car lhs*)] - [ntl (car rhs*)] - [tl (loop (cdr lhs*) (cdr rhs*))]) - `(let ((,x ,ntl)) ,tl))))]) - (Nontail : Nontail (ir) -> Nontail () - [(let ((,x ,[ntl1]) ...) ,[ntl2]) - (let loop ([lhs* x] [rhs* ntl1]) - (if (null? lhs*) - ntl2 - (let ([x (car lhs*)] - [ntl1 (car rhs*)] - [ntl2 (loop (cdr lhs*) (cdr rhs*))]) - `(let ((,x ,ntl1)) ,ntl2))))]) - (Predicate : Predicate (ir) -> Predicate () - [(let ((,x ,[ntl]) ...) ,[p]) - (let loop ([lhs* x] [rhs* ntl]) - (if (null? lhs*) - p - (let ([x (car lhs*)] - [ntl (car rhs*)] - [p (loop (cdr lhs*) (cdr rhs*))]) - `(let ((,x ,ntl)) ,p))))]) - (Effect : Effect (ir) -> Effect () - [(let ((,x ,[ntl]) ...) ,[f]) - (let loop ([lhs* x] [rhs* ntl]) - (if (null? lhs*) - f - (let ([x (car lhs*)] - [ntl (car rhs*)] - [f (loop (cdr lhs*) (cdr rhs*))]) - `(let ((,x ,ntl)) ,f))))])) - - (define-language L17 (extends L16) - (entry LetrecExpr) - (RunExpr (rnexpr) - (- (run (x) tl)) - (+ (run (x) dec))) - (LambdaExpr (lexpr) - (- (lambda (x ...) tl)) - (+ (lambda (x ...) dec))) - (DeclareExpr (dec) (+ (declare (x ...) tl))) - (Tail (tl) (- (let ((x ntl1)) tl2))) - (Nontail (ntl) - (- t - (if p1 ntl2 ntl3) - (begin f0 ... ntl1) - (let ((x ntl1)) ntl2) - (primapp vp t ...) - (sys-primapp spr t ...) - (return-point x a))) - (RhsExpr (rhs) - (+ t - (if p1 rhs2 rhs3) - (begin f0 ... rhs1) - (primapp vp t ...) - (sys-primapp spr t ...) - (return-point x a))) - (Predicate (p) (- (let ((x ntl)) p))) - (Effect (f) - (- (let ((x ntl)) f)) - (+ (set! x rhs)))) - - (define-parser parse-L17 L17) - - (define-pass return-of-set! : L16 (ir) -> L17 () - (definitions - (define Effect* - (lambda (f* var*) - (if (null? f*) - (values '() var*) - (let-values ([(f var*) (Effect (car f*) var*)]) - (let-values ([(f* var*) (Effect* (cdr f*) var*)]) - (values (cons f f*) var*))))))) - (RunExpr : RunExpr (ir) -> RunExpr () - [(run (,x) ,[tl '() -> tl var*]) `(run (,x) (declare (,var* ...) ,tl))]) - (LambdaExpr : LambdaExpr (ir) -> LambdaExpr () - [(lambda (,x* ...) ,[tl '() -> tl var*]) `(lambda (,x* ...) (declare (,var* ...) ,tl))]) - (Tail : Tail (ir var*) -> Tail (var*) - [(let ([,x ,ntl]) ,[tl var*]) - (let-values ([(rhs var*) (Nontail ntl var*)]) - (values `(begin (set! ,x ,rhs) ,tl) (cons x var*)))] - [(if ,[p1 var*] ,tl2 ,tl3) - (let-values ([(tl2 var*) (Tail tl2 var*)]) - (let-values ([(tl3 var*) (Tail tl3 var*)]) - (values `(if ,p1 ,tl2 ,tl3) var*)))] - [(begin ,f* ... ,[tl var*]) - (let-values ([(f* var*) (Effect* f* var*)]) - (values `(begin ,f* ... ,tl) var*))]) - (Nontail : Nontail (ir var*) -> RhsExpr (var*) - [(let ((,x ,ntl1)) ,[rhs2 var*]) - (let-values ([(rhs1 var*) (Nontail ntl1 var*)]) - (values `(begin (set! ,x ,rhs1) ,rhs2) (cons x var*)))] - [(if ,[p1 var*] ,ntl2 ,ntl3) - (let-values ([(rhs2 var*) (Nontail ntl2 var*)]) - (let-values ([(rhs3 var*) (Nontail ntl3 var*)]) - (values `(if ,p1 ,rhs2 ,rhs3) var*)))] - [(begin ,f* ... ,[rhs var*]) - (let-values ([(f* var*) (Effect* f* var*)]) - (values `(begin ,f* ... ,rhs) var*))] - ; TODO: something we could do better here? Triv->Rhs is effectively just this code - [(quoted-const ,d) (values `(quoted-const ,d) var*)] - [(var ,x) (values `(var ,x) var*)]) - (Effect : Effect (ir var*) -> Effect (var*) - [(let ([,x ,ntl]) ,[f var*]) - (let-values ([(rhs var*) (Nontail ntl var*)]) - (values `(begin (set! ,x ,rhs) ,f) var*))] - [(if ,[p1 var*] ,f2 ,f3) - (let-values ([(f2 var*) (Effect f2 var*)]) - (let-values ([(f3 var*) (Effect f3 var*)]) - (values `(if ,p1 ,f2 ,f3) var*)))] - [(begin ,f* ... ,[f var*]) - (let-values ([(f* var*) (Effect* f* var*)]) - (values `(begin ,f* ... ,f) var*))]) - (Predicate : Predicate (ir var*) -> Predicate (var*) - [(let ([,x ,ntl]) ,[p var*]) - (let-values ([(rhs var*) (Nontail ntl var*)]) - (values `(begin (set! ,x ,rhs) ,p) (cons x var*)))] - [(if ,[p1 var*] ,p2 ,p3) - (let-values ([(p2 var*) (Predicate p2 var*)]) - (let-values ([(p3 var*) (Predicate p3 var*)]) - (values `(if ,p1 ,p2 ,p3) var*)))] - [(begin ,f* ... ,[p var*]) - (let-values ([(f* var*) (Effect* f* var*)]) - (values `(begin ,f* ... ,p) var*))])) - - (define-language L18 (extends L17) - (entry LetrecExpr) - (Triv (t) (+ (label x)))) - - (define-parser parse-L18 L18) - - (define-pass explicit-labels : L17 (ir) -> L18 () - (LetrecExpr : LetrecExpr (ir [labs '()]) -> LetrecExpr () - [(letrec ((,x ,[lexpr x -> lexpr]) ...) ,[rnexpr x -> rnexpr]) - `(letrec ((,x ,lexpr) ...) ,rnexpr)]) - (LambdaExpr : LambdaExpr (ir labs) -> LambdaExpr ()) - (Triv : Triv (ir labs) -> Triv () - [(var ,x) (if (memq x labs) `(label ,x) `(var ,x))]) - (Application : Application (ir labs) -> Application ()) - (DeclareExpr : DeclareExpr (ir labs) -> DeclareExpr ()) - (RunExpr : RunExpr (ir labs) -> RunExpr ()) - (Tail : Tail (ir labs) -> Tail ()) - (RhsExpr : RhsExpr (ir labs) -> RhsExpr () - [(return-point ,x ,a) (let ([a (Application a (cons x labs))]) - `(return-point ,x ,a))]) - (Predicate : Predicate (ir labs) -> Predicate ()) - (Effect : Effect (ir labs) -> Effect () - [(return-point ,x ,a) (let ([a (Application a (cons x labs))]) - `(return-point ,x ,a))]))) diff --git a/ta6ob/nanopass/tests/helpers.ss b/ta6ob/nanopass/tests/helpers.ss deleted file mode 100644 index 6f22c14..0000000 --- a/ta6ob/nanopass/tests/helpers.ss +++ /dev/null @@ -1,325 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (tests helpers) - (export compose disjoin any every choose reverse-filter fold reduce - constant? keyword? list-of-user-primitives list-of-system-primitives - user-primitive? system-primitive? primitive? predicate-primitive? - value-primitive? effect-primitive? effect-free-primitive? gen-label - reset-seed gen-symbol set? iota with-values - empty-set singleton-set - add-element member? empty? union intersection difference - variable? datum? list-index primapp sys-primapp app const-datum const - var quoted-const time printf system interpret pretty-print format set-cons - define-who) - (import (rnrs) - (tests implementation-helpers) - (nanopass helpers)) - - (define-syntax primapp - (syntax-rules () - [(_ expr expr* ...) (expr expr* ...)])) - - (define-syntax sys-primapp - (syntax-rules () - [(_ expr expr* ...) (expr expr* ...)])) - - (define-syntax app - (syntax-rules () - [(_ expr expr* ...) (expr expr* ...)])) - - (define-syntax const-datum - (syntax-rules () - [(_ expr) (quote expr)])) - - (define-syntax const - (syntax-rules () - [(_ expr) expr])) - - (define-syntax var - (syntax-rules () - [(_ expr) expr])) - - (define-syntax quoted-const - (syntax-rules () - [(_ expr) (quote expr)])) - - (define compose - (case-lambda - [() (lambda (x) x)] - [(f) f] - [(f . g*) (lambda (x) (f ((apply compose g*) x)))])) - - (define disjoin - (case-lambda - [() (lambda (x) #f)] - [(p?) p?] - [(p? . q?*) (lambda (x) - (or (p? x) ((apply disjoin q?*) x)))])) - - (define any - (lambda (pred? ls) - (let loop ([ls ls]) - (cond - [(null? ls) #f] - [(pred? (car ls)) #t] - [else (loop (cdr ls))])))) - - (define every - (lambda (pred? ls) - (let loop ([ls ls]) - (cond - [(null? ls) #t] - [(pred? (car ls)) (loop (cdr ls))] - [else #f])))) - - (define choose - (lambda (pred? ls) - (fold (lambda (elt tail) - (if (pred? elt) - (cons elt tail) - tail)) - '() - ls))) - - (define reverse-filter - (lambda (pred? ls) - (fold (lambda (elt tail) - (if (pred? elt) - tail - (cons elt tail))) - '() - ls))) - - ;; fold op base (cons a (cons b (cons c '()))) = - ;; (op a (op b (op c base))) - (define fold - (lambda (op base ls) - (let recur ([ls ls]) - (if (null? ls) - base - (op (car ls) (recur (cdr ls))))))) - - ;; reduce op base (cons a (cons b (cons c '()))) - ;; (op c (op b (op a base))) - (define reduce - (lambda (op base ls) - (let loop ([ls ls] [ans base]) - (if (null? ls) - ans - (loop (cdr ls) (op (car ls) ans)))))) - - ;;; General Scheme helpers for the compiler - (define constant? - (disjoin null? number? char? boolean? string?)) - - (define keyword? - (lambda (x) - (and (memq x '(quote set! if begin let letrec lambda)) #t))) - - (define datum? - (lambda (x) - (or (constant? x) - (null? x) - (if (pair? x) - (and (datum? (car x)) (datum? (cdr x))) - (and (vector? x) (for-all datum? (vector->list x))))))) - - (define variable? symbol?) - - (define list-of-user-primitives - '(; not is a special case - (not 1 not) - - ; predicates - (< 2 test) - (<= 2 test) - (= 2 test) - (boolean? 1 test) - (char? 1 test) - (eq? 2 test) - (integer? 1 test) - (null? 1 test) - (pair? 1 test) - (procedure? 1 test) - - (vector? 1 test) - (zero? 1 test) - - ; value-producing - (* 2 value) - (+ 2 value) - (- 2 value) - (add1 1 value) - (car 1 value) - (cdr 1 value) - (char->integer 1 value) - (cons 2 value) - - (make-vector 1 value) - (quotient 2 value) - (remainder 2 value) - - (sub1 1 value) - - (vector -1 value) - (vector-length 1 value) - (vector-ref 2 value) - (void 0 value) - - ; side-effecting - (set-car! 2 effect) - (set-cdr! 2 effect) - - (vector-set! 3 effect))) - - (define list-of-system-primitives ; these are introduced later by the compiler - '(; value-producing - (closure-ref 2 value) - (make-closure 2 value) - (procedure-code 1 value) - - ; side-effecting - (closure-set! 3 effect) - - (fref 1 value) - (fset! 2 effect) - (fincr! 1 effect) - (fdecr! 1 effect) - (href 2 value) - (hset! 3 effect) - (logand 2 value) - (sll 2 value) - (sra 2 value))) - - (define user-primitive? - (lambda (x) - (and (assq x list-of-user-primitives) #t))) - - (define system-primitive? - (lambda (x) - (and (assq x list-of-system-primitives) #t))) - - (define primitive? - (lambda (x) - (or (user-primitive? x) (system-primitive? x)))) - - (define predicate-primitive? - (lambda (x) - (cond - [(or (assq x list-of-user-primitives) - (assq x list-of-system-primitives)) => - (lambda (a) (eq? (caddr a) 'test))] - [else #f]))) - - (define value-primitive? - (lambda (x) - (cond - [(or (assq x list-of-user-primitives) - (assq x list-of-system-primitives)) => - (lambda (a) (eq? (caddr a) 'value))] - [else #f]))) - - (define effect-primitive? - (lambda (x) - (cond - [(or (assq x list-of-user-primitives) - (assq x list-of-system-primitives)) => - (lambda (a) (eq? (caddr a) 'effect))] - [else #f]))) - - (define effect-free-primitive? - (lambda (x) - (not (effect-primitive? x)))) - - (define gen-label - ; at some point, gen-label should be redefined to emit - ; assembler-friendly labels - (lambda (sym) - (string->symbol (format "~a%" sym)))) - - (define gen-symbol-seed 0) - - (define reset-seed - (lambda () - (set! gen-symbol-seed 0))) - - (define gen-symbol - (lambda (sym) - (set! gen-symbol-seed (+ gen-symbol-seed 1)) - (string->symbol (format "~a_~s" sym gen-symbol-seed)))) - - (define set? - (lambda (ls) - (or (null? ls) - (and (not (memq (car ls) (cdr ls))) (set? (cdr ls)))))) - - ;;; ==================== - ;;; Extra syntax and helpers for multiple values - - ;;; Set abstraction - (define empty-set (lambda () '())) - - (define singleton-set (lambda (elt) (list elt))) - - (define add-element - (lambda (elt set) - (if (member? elt set) - set - (cons elt set)))) - - (define member? memq) - - (define empty? null?) - - (define set-cons - (lambda (a set) - (if (memq a set) set (cons a set)))) - - (define union - (case-lambda - [() (empty-set)] - [(set1 set2) - (cond - [(empty? set1) set2] - [(empty? set2) set1] - [(eq? set1 set2) set1] - [else (reduce (lambda (elt set) - (if (member? elt set2) set (cons elt set))) - set2 - set1)])] - [(set1 . sets) - (if (null? sets) - set1 - (union set1 (reduce union (empty-set) sets)))])) - - (define intersection - (lambda (set1 . sets) - (cond - [(null? sets) set1] - [(any empty? sets) (empty-set)] - [else (choose - (lambda (elt) - (every (lambda (set) (member? elt set)) sets)) set1)]))) - - (define list-index - (lambda (a ls) - (cond - [(null? ls) -1] - [(eq? (car ls) a) 0] - [else (maybe-add1 (list-index a (cdr ls)))]))) - - (define maybe-add1 - (lambda (n) - (if (= n -1) -1 (+ n 1)))) - - (define difference - (lambda (set1 . sets) - (let ((sets (reverse-filter empty? sets))) - (cond - [(null? sets) set1] - [else (reverse-filter (lambda (elt) - (any (lambda (set) - (member? elt set)) - sets)) - set1)]))))) diff --git a/ta6ob/nanopass/tests/implementation-helpers.chezscheme.sls b/ta6ob/nanopass/tests/implementation-helpers.chezscheme.sls deleted file mode 100644 index 95001c3..0000000 --- a/ta6ob/nanopass/tests/implementation-helpers.chezscheme.sls +++ /dev/null @@ -1,6 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (tests implementation-helpers) - (export time printf system interpret pretty-print format) - (import (only (chezscheme) time printf system interpret pretty-print format))) diff --git a/ta6ob/nanopass/tests/implementation-helpers.ikarus.ss b/ta6ob/nanopass/tests/implementation-helpers.ikarus.ss deleted file mode 100644 index 30bb03c..0000000 --- a/ta6ob/nanopass/tests/implementation-helpers.ikarus.ss +++ /dev/null @@ -1,19 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (tests implementation-helpers) - (export time printf system interpret pretty-print format) - (import (ikarus)) - - (library - (nanopass testing-environment) - (export not < <= = boolean? char? eq? integer? null? pair? procedure? - vector? zero? * + - add1 car cdr char->integer cons make-vector - quotient remainder sub1 vector vector-length vector-ref void - set-car! set-cdr! vector-set! quote set! if begin lambda let - letrec) - (import (rnrs) (rnrs mutable-pairs) (ikarus))) - - (define interpret - (lambda (src) - (eval src (environment '(nanopass testing-environment)))))) diff --git a/ta6ob/nanopass/tests/implementation-helpers.ironscheme.sls b/ta6ob/nanopass/tests/implementation-helpers.ironscheme.sls deleted file mode 100644 index 4ae0a01..0000000 --- a/ta6ob/nanopass/tests/implementation-helpers.ironscheme.sls +++ /dev/null @@ -1,23 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (tests implementation-helpers) - (export time printf system interpret pretty-print format) - (import (ironscheme)) - - ;; this seems to be only used for a pass not enabled. not sure how to use... - (define (system . args) #f) - - (library - (nanopass testing-environment) - (export not < <= = boolean? char? eq? integer? null? pair? procedure? - vector? zero? * + - add1 car cdr char->integer cons make-vector - quotient remainder sub1 vector vector-length vector-ref void - set-car! set-cdr! vector-set! quote set! if begin lambda let - letrec) - (import (rnrs) (rnrs mutable-pairs) (ironscheme))) - - - (define interpret - (lambda (src) - (eval src (environment '(nanopass testing-environment)))))) diff --git a/ta6ob/nanopass/tests/implementation-helpers.ss b/ta6ob/nanopass/tests/implementation-helpers.ss deleted file mode 100644 index 5642e5d..0000000 --- a/ta6ob/nanopass/tests/implementation-helpers.ss +++ /dev/null @@ -1,6 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (tests implementation-helpers) - (export time printf system interpret pretty-print format) - (import (only (scheme) time printf system interpret pretty-print format))) diff --git a/ta6ob/nanopass/tests/implementation-helpers.vicare.sls b/ta6ob/nanopass/tests/implementation-helpers.vicare.sls deleted file mode 100644 index 31bb85d..0000000 --- a/ta6ob/nanopass/tests/implementation-helpers.vicare.sls +++ /dev/null @@ -1,40 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (tests implementation-helpers) - (export time printf system interpret pretty-print format) - (import (vicare)) - - (library - (nanopass testing-environment) - (export not < <= = boolean? char? eq? integer? null? pair? procedure? - vector? zero? * + - add1 car cdr char->integer cons make-vector - quotient remainder sub1 vector vector-length vector-ref void - set-car! set-cdr! vector-set! quote set! if begin lambda let - letrec) - (import (rename (rnrs) (set! vicare:set!) (if vicare:if)) - (rnrs mutable-pairs) - (rename (only (vicare) void sub1 add1 remainder quotient) (void vicare:void))) - (define-syntax set! - (syntax-rules () - [(_ x v) (call-with-values (lambda () (vicare:set! x v)) (case-lambda [() #!void] [(x) x]))])) - (define-syntax if - (syntax-rules () - [(_ t c) (call-with-values (lambda () (vicare:if t c)) (case-lambda [() #!void] [(x) x]))] - [(_ t c a) (vicare:if t c a)])) - (define-syntax void - (syntax-rules () - [(_) (call-with-values (lambda () (vicare:void)) (case-lambda [() #!void] [(x) x]))]))) - - (define interpret - (lambda (src) - ;; work around for vicare's strange handling of the return value of primitives like set!, - ;; which apparently returns no values. - (call-with-values (lambda () (eval src (environment '(nanopass testing-environment)))) - (case-lambda - [() #!void] - [(x) x])))) - - (define system - (lambda (arg) - (foreign-call "system" arg)))) diff --git a/ta6ob/nanopass/tests/new-compiler.ss b/ta6ob/nanopass/tests/new-compiler.ss deleted file mode 100644 index 7ca4157..0000000 --- a/ta6ob/nanopass/tests/new-compiler.ss +++ /dev/null @@ -1,102 +0,0 @@ -;;; Copyright (c) 2000-2015 Andrew W. Keep, R. Kent Dybvig -;;; See the accompanying file Copyright for details - -(library (tests new-compiler) - (export L0 parse-L0 unparse-L0) - (import (rnrs) (nanopass) (tests helpers)) - -#| - (compiler-passes '( - parse-scheme ;; conversion? simplification? verification. - convert-complex-datum ;; conversion/simplification - uncover-assigned ;; analysis - purify-letrec ;; conversion/simplification - convert-assignments ;; conversion - optimize-direct-call ;; optimization - remove-anonymous-lambda ;; conversion - sanitize-binding-forms ;; conversion/simplification - uncover-free ;; analysis - convert-closures ;; conversion - optimize-known-call ;; optimization - analyze-closure-size ;; analysis - uncover-well-known ;; analysis (for optimization) - optimize-free ;; optimization - optimize-self-reference ;; optimization - analyze-closure-size ;; analysis - introduce-procedure-primitives ;; conversion - lift-letrec ;; conversion - normalize-context ;; conversion - specify-representation ;; conversion - uncover-locals ;; analysis - remove-let ;; conversion - verify-uil ;; verification - remove-complex-opera* ;; conversion - flatten-set! ;; conversion - impose-calling-conventions ;; conversion - expose-allocation-pointer ;; conversion - uncover-frame-conflict ;; conversion - pre-assign-frame ;; - assign-new-frame - (iterate - finalize-frame-locations - select-instructions - uncover-register-conflict - assign-registers - (break when everybody-home?) - assign-frame) - discard-call-live - finalize-locations - expose-frame-var - expose-memory-operands - expose-basic-blocks - #;optimize-jumps - flatten-program - generate-x86-64 - )) -|# - - (define vector-for-all - (lambda (p? x) - (let loop ([n (fx- (vector-length x) 1)]) - (cond - [(fx -;;; (time-stamp generated by emacs: Type M-x time-stamp anywhere to update) - -;;; syncase is a pattern matcher where patterns are quoted or -;;; quasiquoted expressions, or symbols. Unquoted symbols denote -;;; pattern variables. All quoted things must match precisely. -;;; Also, there is a symbol ".." that may be used to allow repetitions -;;; of the preceeding pattern. Any pattern variables within are bound -;;; to a list of matches. ".." may be nested. -;;; Below is the canonical example of "let" - -;;; [`(let ([,var ,rhs] ..) ,body0 ,body1 ..) -;;; (guard (for-all symbol? var) (no-duplicates? var)) -;;; `((lambda ,var ,body0 ,@body1) ,@rhs)] - -;;; For the pattern to match, the optional guard requires its -;;; arguments to be true. The guard also uses the pattern -;;; variables. - -;;; We have added three obvious new forms: synlambda, synlet, and -;;; synlet*. Finally, we have added a very useful operation, -;;; make-double-collector-over-list, whose description follows from the -;;; very simple code below. -;;; Here are some descriptive examples of each of the new special forms. - -;;;> (define foo -;;; (synlambda `((if ,exp0 ,exp1) ,env) -;;; (guard (number? exp1)) -;;; `(,env (if ,exp0 ,exp1 0)))) -;;;> (foo '(if 1 2) 'anenv) -;;;(anenv (if 1 2 0)) - -;;;> (synlet ([`(if ,exp0 ,exp1) -;;; (guard (number? exp0)) -;;; '(if 0 1)]) -;;; `(if ,exp1, exp0)) -;;;(if 1 0) - -;;;> (synlet ([`(if ,x ,y ,z) '(if 1 2 3)] -;;; [`(if ,a then ,b else ,c) '(if 1 then 2 else 3)] -;;; [`(when ,u ,w) (guard (number? u) (number? w) (= u w)) -;;; '(when 1 1)]) -;;; (list x y z a b c a b)) -;;; (1 2 3 1 2 3 1 2) - -;;;> (synlet* ([`(if ,exp0 ,exp1) (guard (number? exp0)) '(if 0 1)] -;;; [`(if ,x ,y ,exp2) `(if ,exp0 ,exp1 5)]) -;;; `(if ,exp0 ,y ,exp2)) -;;;(if 0 1 5) - -(library (tests synforms) - (export syncase) - (import (rnrs)) - - (define-syntax syncase - (syntax-rules () - [(_ Exp (Clause ...) ...) - (let ([x Exp]) - (call/cc - (lambda (succeed) - (pm:c start x succeed Clause ...) - ... - (error 'syncase "No match for ~s" x))))])) - - (define-syntax pm:c - (syntax-rules (guard start finish) - [(pm:c start V Succ Pattern (guard Exp ...) Body0 Body ...) - (pm:parse start Pattern - (pm:c finish V - (when (and Exp ...) - (Succ (begin Body0 Body ...)))))] - [(pm:c finish V Body Pattern UsedFormals) - (pm:find-dup UsedFormals - (cont (Dup) - (pm:error "Duplicate patvar ~s in pattern ~s" Dup Pattern)) - (cont () (pm V Pattern Body)))] - [(_ start V Succ Pattern Body0 Body ...) - (pm:c start V Succ Pattern (guard) Body0 Body ...)] - [(_ start V Succ Pattern) - (pm:error "Missing body for pattern ~s" Pattern)])) - - (define-syntax pm:parse ;; returns parsed thing + used formals - (syntax-rules (dots quasiquote quote unquote start) - [(pm:parse start () K) (pm:ak K (null) ())] - [(pm:parse start (unquote X) K) (pm:ak K (formal X) (X))] - [(pm:parse start (A . D) K) (pm:parseqq start (A . D) K)] - [(pm:parse start X K) (pm:ak K (keyword X) ())])) - - (define-syntax pm:parseqq;; returns parsed thing + used formals - (lambda (x) - (syntax-case x (unquote start dothead dottail dottemps pairhead pairtail) - [(pm:parseqq start (unquote ()) K) #'(pm:error "Bad variable: ~s" ())] - [(pm:parseqq start (unquote (quasiquote X)) K) #'(pm:parseqq start X K)] - [(pm:parseqq start (unquote (X . Y)) K) - #'(pm:error "Bad variable: ~s" (X . Y))] - [(pm:parseqq start (unquote #(X ...)) K) - #'(pm:error "Bad variable: ~s" #(X ...))] - [(pm:parseqq start (unquote X) K) #'(pm:ak K (formal X) (X))] - [(pm:parseqq start (X dots . Y) K) - (eq? (syntax->datum #'dots) '...) - #'(pm:parseqq start X (pm:parseqq dothead Y K))] - [(pm:parseqq dothead Y K Xpat Xformals) - #'(pm:parseqq^ start Y () () - (pm:parseqq dottail Xpat Xformals K))] - [(pm:parseqq dottail Xpat Xformals K Yrevpat Yformals) - #'(pm:gen-temps Xformals () - (pm:parseqq dottemps Xpat Yrevpat Xformals Yformals K))] - [(pm:parseqq dottemps Xpat Yrevpat (Xformal ...) (Yformal ...) K Xtemps) - #'(pm:ak K (dots (Xformal ...) Xtemps Xpat Yrevpat) - (Xformal ... Yformal ...))] - [(pm:parseqq start (X . Y) K) - #'(pm:parseqq start X (pm:parseqq pairhead Y K))] - [(pm:parseqq pairhead Y K Xpat Xformals) - #'(pm:parseqq start Y (pm:parseqq pairtail Xpat Xformals K))] - [(pm:parseqq pairtail Xpat (Xformal ...) K Ypat (Yformal ...)) - #'(pm:ak K (pair Xpat Ypat) (Xformal ... Yformal ...))] - [(pm:parseqq start X K) #'(pm:ak K (keyword X) ())]))) - - (define-syntax pm:parseqq^;; returns list-of parsed thing + used formals - (syntax-rules (dots start pairhead) - [(pm:parseqq^ start () Acc Used K) (pm:ak K Acc ())] - [(pm:parseqq^ start (dots . Y) Acc Used K) - (pm:error "Illegal continuation of list pattern beyond dots: ~s" Y)] - [(pm:parseqq^ start (X . Y) Acc Used K) - (pm:parseqq start X (pm:parseqq^ pairhead Y Acc Used K))] - [(pm:parseqq^ pairhead Y Acc (Used ...) K Xpat (Xformal ...)) - (pm:parseqq^ start Y (Xpat . Acc) (Used ... Xformal ...) K)] - [(pm:parseqq^ start X Acc Used K) (pm:error "Bad pattern ~s" X)])) - - (define-syntax pm - (syntax-rules (keyword formal dots null pair) - [(pm V (keyword K) Body) (when (eqv? V 'K) Body)] - [(pm V (formal F) Body) (let ((F V)) Body)] - [(pm V (dots Dformals DTemps DPat (PostPat ...)) Body) - (when (list? V) - (let ((rev (reverse V))) - (pm:help rev (PostPat ...) Dformals DTemps DPat Body)))] - [(pm V (null) Body) (when (null? V) Body)] - [(pm V (pair P0 P1) Body) - (when (pair? V) - (let ((X (car V)) (Y (cdr V))) - (pm X P0 (pm Y P1 Body))))])) - - (define-syntax pm:help - (syntax-rules () - [(pm:help V () (DFormal ...) (DTemp ...) DPat Body) - (let f ((ls V) (DTemp '()) ...) - (if (null? ls) - (let ((DFormal DTemp) ...) Body) - (let ((X (car ls)) (Y (cdr ls))) - (pm X DPat - (f Y (cons DFormal DTemp) ...)))))] - [(pm:help V (Post0 PostPat ...) DFormals DTemps DPat Body) - (when (pair? V) - (let ((X (car V)) (Y (cdr V))) - (pm X Post0 - (pm:help Y (PostPat ...) DFormals DTemps DPat Body))))])) - - (define-syntax pm:error - (syntax-rules () - [(pm:error X ...) (error 'syncase 'X ...)])) - - (define-syntax pm:eq? - (syntax-rules () - [(_ A B SK FK) ; b should be an identifier - (let-syntax ([f (syntax-rules (B) - [(f B _SK _FK) (pm:ak _SK)] - [(f nonB _SK _FK) (pm:ak _FK)])]) - (f A SK FK))])) - - (define-syntax pm:member? - (syntax-rules () - [(pm:member? A () SK FK) (pm:ak FK)] - [(pm:member? A (Id0 . Ids) SK FK) - (pm:eq? A Id0 SK (cont () (pm:member? A Ids SK FK)))])) - - (define-syntax pm:find-dup - (syntax-rules () - [(pm:find-dup () SK FK) (pm:ak FK)] - [(pm:find-dup (X . Y) SK FK) - (pm:member? X Y - (cont () (pm:ak SK X)) (cont () (pm:find-dup Y SK FK)))])) - - (define-syntax pm:gen-temps - (syntax-rules () - [(_ () Acc K) (pm:ak K Acc)] - [(_ (X . Y) Acc K) (pm:gen-temps Y (temp . Acc) K)])) - - ;;; ------------------------------ - ;;; Continuation representation and stuff - (define-syntax cont ; broken for non-nullary case - (syntax-rules () - [(_ () Body) Body] - [(_ (Var ...) Body Exp ...) - (let-syntax ([f (syntax-rules () - [(_ Var ...) Body])]) - (f Exp ...))])) - - (define-syntax pm:ak - (syntax-rules () - [(_ (X Y ...) Z ...) (X Y ... Z ...)])) - - ;;; ------------------------------ - ;;; tests - - ;(define exp0 - ; '(syncase '((a) (b) (c d)) - ; ((,zz ,ww) ((,zz .. ,ww) ..) - ; zz))) - - ;(define test - ; (lambda (x) - ; (pretty-print x) - ; (pretty-print (eval x)) - ; (newline))) - ; - ;(define test0 (lambda () (test exp0))) - - ;;; There are three additional special forms, which should be obvious. - (define-syntax synlambda - (syntax-rules (guard) - [(_ pat (guard g ...) body0 body1 ...) - (lambda (x) - (syncase x - [pat (guard g ...) (begin body0 body1 ...)]))] - [(_ pat body0 body1 ...) - (lambda (x) - (syncase x - [pat (begin body0 body1 ...)]))])) - - (define-syntax synlet - (syntax-rules (guard) - [(_ ([pat (guard g) rhs] ...) body0 body1 ...) - ((synlambda `(,pat ...) - (guard (and g ...)) body0 body1 ...) `(,rhs ...))] - [(_ ([pat rhs] ...) body0 body1 ...) - ((synlambda `(,pat ...) body0 body1 ...) `(,rhs ...))] - [(_ stuff ...) (synlet-all-guarded () stuff ...)])) - - (define-syntax synlet-all-guarded - (syntax-rules (guard) - [(_ (x ...) () body0 body1 ...) (synlet (x ...) body0 body1 ...)] - [(_ (x ...) ([pat (guard g0 g1 g2 ...) rhs] decl ...) body0 body1 ...) - (synlet-all-guarded (x ... [pat (guard (and g0 g1 g2 ...)) rhs]) - (decl ...) body0 body1 ...)] - [(_ (x ...) ([pat rhs] decl ...) body0 body1 ...) - (synlet-all-guarded (x ... [pat (guard #t) rhs]) - (decl ...) body0 body1 ...)] - [(_ (x ...) ([pat] decl ...) body0 body1 ...) - (pm:error "synlet missing right-hand-side for pattern: ~s" pat)] - [(_ () (decl ...)) (pm:error "synlet missing body")])) - - (define-syntax synlet* - (syntax-rules () - [(_ (dec) body0 body1 ...) (synlet (dec) body0 body1 ...)] - [(_ (dec0 decl ...) body0 body1 ...) - (synlet (dec0) (synlet* (decl ...) body0 body1 ...))])) - - (define make-double-collector-over-list - (lambda (constructor1 base1 constructor2 base2) - (letrec ((loop42 (lambda args - (if (not (= (length args) 2)) - (error 'syncase "Invalid rhs expression")) - (let ([f (car args)] [arg (cadr args)]) - (cond - [(null? arg) `(,base1 ,base2)] - [else - (synlet ([`(,x ,y) (f (car arg))] - [`(,x* ,y*) (loop42 f (cdr arg))]) - `(,(constructor1 x x*) - ,(constructor2 y y*)))]))))) - loop42)))) diff --git a/ta6ob/nanopass/tests/test-driver.ss b/ta6ob/nanopass/tests/test-driver.ss deleted file mode 100644 index 7dc8682..0000000 --- a/ta6ob/nanopass/tests/test-driver.ss +++ /dev/null @@ -1,200 +0,0 @@ -;;; Copyright (c) 2000-2015 Dipanwita Sarkar, Andrew W. Keep, R. Kent Dybvig, Oscar Waddell -;;; See the accompanying file Copyright for details - -(library (tests test-driver) - (export define-passes pass-names passes tracer test-one test-all tests - print-file) - (import (rnrs) (tests helpers)) - - (define subst - (lambda (new old tree) - (cond - [(null? tree) '()] - [(equal? tree old) new] - [(pair? tree) `(,(subst new old (car tree)) . - ,(subst new old (cdr tree)))] - [else tree]))) - - (define void (lambda () (if #f #f))) - - (define-syntax define-passes - (syntax-rules () - [(_ p1 p2 ...) (list '(p1 p2 ...) (list p1 p2 ...))])) - - (define passes - (let ([pass-list '()]) - (case-lambda - [() pass-list] - [(x) (set! pass-list x)]))) - - (define-syntax pass-names - (identifier-syntax (let ([passes (passes)]) - (if (null? passes) '() (car passes))))) - - (define tests - (let ([test-list '()]) - (case-lambda - [() test-list] - [(x) (set! test-list x)]))) - - (define tracer - (let ([trace-list '()]) - (case-lambda - [() trace-list] - [(x) - (set! trace-list - (cond - [(eq? x #t) pass-names] - [(eq? x #f) '()] - [(and (symbol? x) (memq x pass-names)) (list x)] - [(and (list? x) (for-all (lambda (x) (memq x pass-names)) x)) x] - [else (error 'tracer (format "invalid argument ~s" x))]))]))) - - (define test-all - (case-lambda - [() (test-all #t #f #f)] - [(emit?) (test-all emit? #f #f)] - [(emit? print-expr?) (test-all emit? print-expr? #f)] - [(emit? print-expr? check-eval?) - (for-each - (lambda (x) - (when print-expr? (pretty-print x)) - (unless (test-one x emit?) - (error 'test-all "test failed"))) - (tests))])) - - (define print-file - (lambda (path) - (with-input-from-file path - (letrec ([f (lambda () - (unless (eof-object? (peek-char)) - (write-char (read-char)) - (f)))]) - f)))) - - (define test-one - (case-lambda - [(original-input-expr) (test-one original-input-expr #t)] - [(original-input-expr emit?) - (let ([answer (interpret original-input-expr)]) - (define-syntax on-error - (syntax-rules () - [(_ e0 e1 e2 ...) - (guard (e [else e0 (raise e)]) - e1 e2 ...)])) - #; - (define check-eval - (lambda (pass-name input-expr output-expr) - (on-error - (begin - (printf "~s input:~%" pass-name) - (pretty-print input-expr) - (printf "========~%~s output:~%" pass-name) - (pretty-print output-expr)) - (let ([t (interpret output-exr)]) - (unless (equal? t answer) - (error pass-name - (format "answer is ~s, should have been ~s" t answer))) - (let ([t (parameterize ([run-cp0 (lambda (cp0 x) x)]) - (interpret output-expr))]) - (unless (equal? t answer) - (error pass-name "answer is ~s, should have been ~s" - t answer))))))) - (define check-eval - (lambda (pass-name input-expr output-expr) - (void))) - (define run - (lambda (input-expr pass-names pass-procs) - (if (null? pass-names) - input-expr - (let ([pass-name (car pass-names)]) - (when (memq pass-name (tracer)) (printf "~%~s:~%" pass-name)) - (let ([pass (car pass-procs)]) - (let ([output-expr - (on-error - (begin - (printf "~s input:~%" pass-name) - (pretty-print input-expr)) - (pass input-expr))]) - (check-eval pass-name input-expr output-expr) - (when (memq pass-name (tracer)) - (pretty-print output-expr)) - (run output-expr (cdr pass-names) (cdr pass-procs)))))))) - ;; AWK - TODO - need to come up with more elegant handling of this - ;; since looking up generate-code for each test is - ;; pretty hackish. Maybe passes could handle this as - ;; well? - (define generate-code - (lambda (expr) - (let ([passes (passes)]) - (if (null? passes) - (error 'generate-code "No passes defined") - (let ([proc (let l ([names (car passes)] - [procs (cadr passes)]) - (cond - [(null? names) - (error 'generate-code - "No generate-code pass defined")] - [(eq? 'generate-code (car names)) (car procs)] - [else (l (cdr names) (cdr procs))]))]) - (proc expr)))))) - (define run-code - (lambda (input-expr) - (define asm-file "t1.s") - (define err-file "t1.err") - (define out-file "t1.out") - (when (memq 'generate-code (tracer)) (printf "~%generate-code:~%")) - (on-error - (begin - (printf "generate-code input:~%") - (pretty-print input-expr)) - (when (file-exists? asm-file) (delete-file asm-file)) - (with-output-to-file asm-file - (lambda () - (printf "/* ~%") - (pretty-print original-input-expr) - (printf "*/~%~%") - (print-file "canned.s") - (newline) - (generate-code input-expr)))) - (on-error - (begin - (printf "generate-code input:~%") - (pretty-print input-expr) - (printf "========~%generate-code output:~%") - (print-file asm-file) - (printf "========~%") - (print-file err-file)) - (let ([t (assemble-and-run asm-file err-file out-file)]) - (unless (equal? t answer) - (error 'generate-code - (format "answer is ~s, should have been ~s" - t answer))))) - (when (memq 'generate-code (tracer)) (print-file asm-file)))) - (reset-seed) - (let ([expr (run original-input-expr (car (passes)) (cadr (passes)))]) - (when (and emit? (memq 'generate-code pass-names)) - (run-code expr)) - #t))])) - - (define assemble-and-run - (lambda (asm-file err-file out-file) - (define shell - (lambda (s . args) - (system (apply format s args)))) - (unless - (= 0 (shell "cc -o run startup.c ~a > ~a 2>&1" asm-file err-file)) - (error 'generate-program "build error(s)")) - (let ([status (shell "exec ./run > ~a 2>&1" out-file)]) - (shell "cat ~a >> ~a" out-file err-file) - (unless (= status 0) - (error 'generate-program "run error(s)"))) - ; replace # with "#" to make it something the reader can - ; handle, then substitute void for "#" - (shell "sed -e 's/#/\"#\"/g' < ~a > ~a.tmp" - out-file out-file) - (let ([ip (open-input-file (format "~a.tmp" out-file))]) - (let ([x (subst (void) "#" (read ip))]) - (close-input-port ip) - x))))) - diff --git a/ta6ob/nanopass/tests/unit-test-helpers-implementation.chezscheme.sls b/ta6ob/nanopass/tests/unit-test-helpers-implementation.chezscheme.sls deleted file mode 100644 index 6b5ddc9..0000000 --- a/ta6ob/nanopass/tests/unit-test-helpers-implementation.chezscheme.sls +++ /dev/null @@ -1,9 +0,0 @@ -;;; Copyright (c) 2000-2015 Andrew W. Keep, R. Kent Dybvig -;;; See the accompanying file Copyright for details - -(library (tests unit-test-helpers-implementation) - (export with-output-to-string display-condition format-error-message) - (import (chezscheme)) - (define-syntax format-error-message - (syntax-rules () - [(_ args ...) (parameterize ([print-level 3] [print-length 6]) (format args ...))]))) diff --git a/ta6ob/nanopass/tests/unit-test-helpers-implementation.ikarus.sls b/ta6ob/nanopass/tests/unit-test-helpers-implementation.ikarus.sls deleted file mode 100644 index bcc17be..0000000 --- a/ta6ob/nanopass/tests/unit-test-helpers-implementation.ikarus.sls +++ /dev/null @@ -1,29 +0,0 @@ -;;; Copyright (c) 2000-2015 Andrew W. Keep, R. Kent Dybvig -;;; See the accompanying file Copyright for details - -(library (tests unit-test-helpers-implementation) - (export with-output-to-string display-condition format-error-message) - (import (ikarus)) - - (define display-condition - (case-lambda - [(c) (display-condition c (current-output-port))] - [(c op) - (display - (format "~a~a~a~a~a" - (if (warning? c) "Warning" "Exception") - (if (who-condition? c) (format " in ~s" (condition-who c)) "") - (if (message-condition? c) (format ": ~a" (condition-message c)) "") - (if (and (irritants-condition? c) (not (null? (condition-irritants c)))) - (format " with irritants ~s" (condition-irritants c)) - "") - (if (syntax-violation? c) - (if (syntax-violation-subform c) - (format "~s in ~s" (syntax-violation-subform c) (syntax-violation-form c)) - (format "~s" (syntax-violation-form c))) - "")) - op)])) - - (define-syntax format-error-message - (syntax-rules () - [(_ args ...) (format args ...)]))) diff --git a/ta6ob/nanopass/tests/unit-test-helpers-implementation.ironscheme.sls b/ta6ob/nanopass/tests/unit-test-helpers-implementation.ironscheme.sls deleted file mode 100644 index 3147aeb..0000000 --- a/ta6ob/nanopass/tests/unit-test-helpers-implementation.ironscheme.sls +++ /dev/null @@ -1,36 +0,0 @@ -;;; Copyright (c) 2000-2015 Andrew W. Keep, R. Kent Dybvig -;;; See the accompanying file Copyright for details - -(library (tests unit-test-helpers-implementation) - (export with-output-to-string display-condition format-error-message) - (import (ironscheme)) - - ;; easy enough to define ;p - (define (with-output-to-string thunk) - (let-values (((p g) (open-string-output-port))) - (parameterize ([current-output-port p]) - (thunk) - (g)))) - - (define display-condition - (case-lambda - [(c) (display-condition c (current-output-port))] - [(c op) - (display - (format "~a~a~a~a~a" - (if (warning? c) "Warning" "Exception") - (if (who-condition? c) (format " in ~s" (condition-who c)) "") - (if (message-condition? c) (format ": ~a" (condition-message c)) "") - (if (and (irritants-condition? c) (not (null? (condition-irritants c)))) - (format " with irritants ~s" (condition-irritants c)) - "") - (if (syntax-violation? c) - (if (syntax-violation-subform c) - (format "~s in ~s" (syntax-violation-subform c) (syntax-violation-form c)) - (format "~s" (syntax-violation-form c))) - "")) - op)])) - - (define-syntax format-error-message - (syntax-rules () - [(_ args ...) (format args ...)]))) diff --git a/ta6ob/nanopass/tests/unit-test-helpers-implementation.vicare.sls b/ta6ob/nanopass/tests/unit-test-helpers-implementation.vicare.sls deleted file mode 100644 index eec558c..0000000 --- a/ta6ob/nanopass/tests/unit-test-helpers-implementation.vicare.sls +++ /dev/null @@ -1,32 +0,0 @@ -;;; Copyright (c) 2000-2015 Andrew W. Keep, R. Kent Dybvig -;;; See the accompanying file Copyright for details - -(library (tests unit-test-helpers-implementation) - (export with-output-to-string display-condition format-error-message) - (import (vicare)) - - (define display-condition - (case-lambda - [(c) (display-condition c (current-output-port))] - [(c op) - (display - (format "~a~a~a~a~a" - (if (warning? c) "Warning" "Exception") - (if (who-condition? c) (format " in ~s" (condition-who c)) "") - (if (message-condition? c) (format ": ~a" (condition-message c)) "") - (if (and (irritants-condition? c) (not (null? (condition-irritants c)))) - (format " with irritants ~s" (condition-irritants c)) - "") - (if (syntax-violation? c) - (if (syntax-violation-subform c) - (format "~s in ~s" (syntax-violation-subform c) (syntax-violation-form c)) - (format "~s" (syntax-violation-form c))) - "")) - op)])) - - (define-syntax format-error-message - (syntax-rules () - [(_ args ...) (format args ...)])) - - ;; needed to get an r6rs script to print with vicare - (current-output-port (current-error-port))) diff --git a/ta6ob/nanopass/tests/unit-test-helpers.ss b/ta6ob/nanopass/tests/unit-test-helpers.ss deleted file mode 100644 index ed6dea7..0000000 --- a/ta6ob/nanopass/tests/unit-test-helpers.ss +++ /dev/null @@ -1,124 +0,0 @@ -;;; Copyright (c) 2000-2018 Andrew W. Keep, R. Kent Dybvig -;;; See the accompanying file Copyright for details - -(library (tests unit-test-helpers) - (export test-suite test assert-equal? assert-error with-output-to-string format-error-message) - (import (rnrs) (tests unit-test-helpers-implementation) (only (nanopass helpers) errorf)) - - (define-syntax test-suite - (lambda (x) - (define name->run-name - (lambda (name) - (datum->syntax name - (string->symbol - (string-append "run-" (symbol->string (syntax->datum name))))))) - (syntax-case x () - [(_ name test test* ...) - (with-syntax ([run (name->run-name #'name)]) - #'(define run - (lambda () - (display "Running ") - (write (quote name)) - (display " test suite...\n") - (let f ([tests (list (lambda () test) (lambda () test*) ...)] - [successes 0] [failures 0] [exceptions 0]) - (if (null? tests) - (begin - (display "Ran ") - (write (+ successes failures exceptions)) - (display " tests with ") - (write successes) - (display " successes, ") - (write failures) - (display " failures, and ") - (write exceptions) - (display " exceptions\n") - (and (= failures 0) (= exceptions 0))) - (guard (e [else - (display " caught expection... ") - (display-condition e) - (newline) - (f (cdr tests) successes failures - (+ exceptions 1))]) - (let ([result ((car tests))]) - (write result) - (newline) - (if result - (f (cdr tests) (+ successes 1) failures - exceptions) - (f (cdr tests) successes (+ failures 1) - exceptions)))))))))]))) - - (define-syntax test - (syntax-rules () - [(_ name assertion assertion* ...) - (begin - (display " Testing ") - (write (quote name)) - (display " ...") - (and assertion assertion* ...))])) - - ;; extended to cover record equality, but not doing the union-find - ;; equality we should be doing. - (define stupid-extended-equal? - (lambda (x y) - (or (equal? x y) - (and (record? x) - (record? y) - (record=? x y))))) - - (define record-type-accessors - (lambda (rtd) - (let loop ([i (vector-length (record-type-field-names rtd))] [ls '()]) - (if (fx=? i 0) - ls - (let ([i (fx- i 1)]) - (loop i (cons (record-accessor rtd i) ls))))))) - - (define record=? - (lambda (x y) - (let ([rtd (record-rtd x)]) - (and (eq? rtd (record-rtd y)) - (let loop ([rtd rtd]) - (or (eq? rtd #f) - (and (for-all (lambda (ac) (stupid-extended-equal? (ac x) (ac y))) (record-type-accessors rtd)) - (loop (record-type-parent rtd))))))))) - - (define-syntax assert-equal? - (syntax-rules () - [(_ expected actual) - (or (stupid-extended-equal? expected actual) - (begin - (newline) - (display "!!! ") - (write actual) - (display " does not match expected: ") - (write expected) - (newline) - #f))])) - - (define-syntax assert-error - (syntax-rules () - [(_ ?msg ?expr) - (let ([msg ?msg]) - (guard (e [else - (let ([e-msg (with-output-to-string - (lambda () - (display-condition e)))]) - (or (string=? msg e-msg) - (begin - (newline) - (display "!!! expected error message ") - (write msg) - (display " does not match ") - (write e-msg) - (newline) - #f)))]) - (let ([t ?expr]) - (newline) - (display "!!! expected error with message ") - (write msg) - (display " but got result ") - (write t) - (newline) - #f)))]))) diff --git a/ta6ob/nanopass/tests/unit-tests.ss b/ta6ob/nanopass/tests/unit-tests.ss deleted file mode 100644 index e6bea4d..0000000 --- a/ta6ob/nanopass/tests/unit-tests.ss +++ /dev/null @@ -1,1105 +0,0 @@ -;;; Copyright (c) 2000-2018 Andrew W. Keep, R. Kent Dybvig -;;; See the accompanying file Copyright for details - -(library (tests unit-tests) - (export run-unit-tests run-ensure-correct-identifiers run-maybe-tests - run-maybe-dots-tests run-language-dot-support run-maybe-unparse-tests - run-argument-name-matching run-error-messages run-pass-parser-unparser) - (import (rnrs) - (nanopass helpers) - (nanopass language) - (nanopass pass) - (nanopass parser) - (tests unit-test-helpers)) - - (define primitives '(car cdr cons + - =)) - (define primitive? (lambda (x) (memq x primitives))) - (define variable? (lambda (x) (and (symbol? x) (not (primitive? x))))) - (define constant? - (lambda (x) - (or (number? x) (boolean? x) (string? x) - (and (pair? x) (constant? (car x)) (constant? (cdr x)))))) - - (define-language L0 - (terminals - (variable (x)) - (constant (c)) - (primitive (pr))) - (Expr (e) - (var x) - (quote c) - (begin e0 ... e1) - (if e0 e1 e2) - (lambda (x ...) e0 ... e1) - (let ([x e] ...) e0 ... e1) - (letrec ([x e] ...) e0 ... e1) - (primapp pr e1 ...) - (app e0 e1 ...))) - - (define-record-type var - (fields sym ref set mset) - (protocol - (lambda (new) - (lambda (sym) - (new sym #f #f #f))))) - - (define-language LUNPARSE - (terminals - (var (x)) => var-sym - (constant (c)) - (primitive (pr))) - (Expr (e body) - (var x) => x - (quoted c) => (quote c) - (seq e0 e1) => (begin e0 e1) - (if e0 e1 e2) - (lambda (x ...) e0 ... e1) - (binding (x ...) (e ...) body0 ... body1) => (let ([x e] ...) body0 ... body1) - (recbinding (x ...) (e ...) body0 ... body1) => (letrec ([x e] ...) body0 ... body1) - (primapp pr e1 ...) => (pr e1 ...) - (app e0 e1 ...) => (e0 e1 ...))) - - (define-language LBool - (terminals - (boolean (b))) - (Expr (e) - b)) - - (define-language LBoolLambda - (terminals - (boolean (b)) - (symbol (x))) - (Expr (e) - v - x - (lambda (x) e) - (and e0 e1) - (or e0 e1) - (not e) - (e0 e1)) - (Value (v) - b)) - - (test-suite unit-tests - (test with-output-language - (assert-equal? - '(var a) - (unparse-L0 (with-output-language L0 (in-context Expr `(var a))))) - (assert-equal? - '(let ([x '1] [y '2]) (primapp + (var x) (var y))) - (unparse-L0 - (with-output-language L0 - (in-context Expr - `(let ([x (quote 1)] [y (quote 2)]) - (primapp + (var x) (var y))))))) - (assert-equal? - '(var a) - (unparse-L0 (with-output-language (L0 Expr) `(var a)))) - (assert-equal? - '(let ([x '1] [y '2]) (primapp + (var x) (var y))) - (unparse-L0 - (with-output-language (L0 Expr) - `(let ([x (quote 1)] [y (quote 2)]) - (primapp + (var x) (var y))))))) - - (test unparse-language - (assert-equal? - `(quoted 5) - (unparse-LUNPARSE - (with-output-language (LUNPARSE Expr) `(quoted 5)) - #t)) - - (assert-equal? - `(seq (quoted 7) (quoted 8)) - (unparse-LUNPARSE - (with-output-language (LUNPARSE Expr) - `(seq (quoted 7) (quoted 8))) - #t)) - - (let ([x.0 (make-var 'x.0)]) - (assert-equal? - `(var ,x.0) - (unparse-LUNPARSE - (with-output-language (LUNPARSE Expr) `(var ,x.0)) - #t))) - - (let ([x.1 (make-var 'x.1)] - [x.2 (make-var 'x.2)] - [y.3 (make-var 'y.2)] - [x.4 (make-var 'x.4)] - [zero?.5 (make-var 'zero?.5)] - [*.6 (make-var '*.6)] - [f.7 (make-var 'f.7)]) - (assert-equal? - `(recbinding (,zero?.5 ,*.6 ,f.7) - ((lambda (,x.1) (primapp = (var ,x.1) (quoted 0))) - (lambda (,x.2 ,y.3) - (if (app (var ,zero?.5) (var ,x.2)) - (quoted 0) - (if (primapp = (var ,x.2) (quoted 1)) - (var ,y.3) - (primapp + (var ,y.3) - (app (var ,*.6) - (primapp - (var ,x.2) (quoted 1)) - (var ,y.3)))))) - (lambda (,x.4) - (if (app (var ,zero?.5) (var ,x.4)) - (quoted 1) - (app (var ,*.6) (var ,x.4) - (app (var ,f.7) - (primapp - (var ,x.4) (quoted 1))))))) - (app (var ,f.7) (quoted 10))) - (unparse-LUNPARSE - (with-output-language (LUNPARSE Expr) - `(recbinding - (,zero?.5 ,*.6 ,f.7) - ((lambda (,x.1) (primapp = (var ,x.1) (quoted 0))) - (lambda (,x.2 ,y.3) - (if (app (var ,zero?.5) (var ,x.2)) - (quoted 0) - (if (primapp = (var ,x.2) (quoted 1)) - (var ,y.3) - (primapp + (var ,y.3) - (app (var ,*.6) - (primapp - (var ,x.2) (quoted 1)) - (var ,y.3)))))) - (lambda (,x.4) - (if (app (var ,zero?.5) (var ,x.4)) - (quoted 1) - (app (var ,*.6) (var ,x.4) - (app (var ,f.7) - (primapp - (var ,x.4) (quoted 1))))))) - (app (var ,f.7) (quoted 10)))) #t))) - - (assert-equal? - '(quote 5) - (unparse-LUNPARSE - (with-output-language (LUNPARSE Expr) `(quoted 5)) - #f)) - - (assert-equal? - '(begin (quote 7) (quote 8)) - (unparse-LUNPARSE - (with-output-language (LUNPARSE Expr) - `(seq (quoted 7) (quoted 8))) - #f)) - - (let ([x.0 (make-var 'x.0)]) - (assert-equal? - 'x.0 - (unparse-LUNPARSE - (with-output-language (LUNPARSE Expr) `(var ,x.0)) - #f))) - - (let ([x.1 (make-var 'x.1)] - [x.2 (make-var 'x.2)] - [y.3 (make-var 'y.3)] - [x.4 (make-var 'x.4)] - [zero?.5 (make-var 'zero?.5)] - [*.6 (make-var '*.6)] - [f.7 (make-var 'f.7)]) - (assert-equal? - '(letrec ([zero?.5 (lambda (x.1) (= x.1 '0))] - [*.6 (lambda (x.2 y.3) - (if (zero?.5 x.2) - '0 - (if (= x.2 '1) - y.3 - (+ y.3 (*.6 (- x.2 '1) y.3)))))] - [f.7 (lambda (x.4) - (if (zero?.5 x.4) - '1 - (*.6 x.4 (f.7 (- x.4 '1)))))]) - (f.7 '10)) - (unparse-LUNPARSE - (with-output-language (LUNPARSE Expr) - `(recbinding - (,zero?.5 ,*.6 ,f.7) - ((lambda (,x.1) (primapp = (var ,x.1) (quoted 0))) - (lambda (,x.2 ,y.3) - (if (app (var ,zero?.5) (var ,x.2)) - (quoted 0) - (if (primapp = (var ,x.2) (quoted 1)) - (var ,y.3) - (primapp + (var ,y.3) - (app (var ,*.6) - (primapp - (var ,x.2) (quoted 1)) - (var ,y.3)))))) - (lambda (,x.4) - (if (app (var ,zero?.5) (var ,x.4)) - (quoted 1) - (app (var ,*.6) (var ,x.4) - (app (var ,f.7) - (primapp - (var ,x.4) (quoted 1))))))) - (app (var ,f.7) (quoted 10)))) #f))) - ) - - (test boolean-terminals - (let () - (define-parser parse-LBool LBool) - (assert-equal? #t (parse-LBool #t))) - (let () - (define-parser parse-LBool LBool) - (assert-equal? #f (parse-LBool #f))) - (let () - (define-parser parse-LBool LBool) - (guard (c [else #t]) - (assert-equal? 'a (parse-LBool 'a)))) - (let () - (define-parser parse-LBoolLambda LBoolLambda) - (assert-equal? #t (parse-LBoolLambda #t))) - (let () - (define-parser parse-LBoolLambda LBoolLambda) - (assert-equal? #f (parse-LBoolLambda #f))) - (let () - (define-parser parse-LBoolLambda LBoolLambda) - (assert-equal? - '(lambda (x) #f) - (unparse-LBoolLambda - (parse-LBoolLambda '(lambda (x) #f))))) - (let () - (define-parser parse-LBoolLambda LBoolLambda) - (assert-equal? - '(lambda (f) (f #f)) - (unparse-LBoolLambda - (parse-LBoolLambda '(lambda (f) (f #f)))))) - (let () - (define-parser parse-LBoolLambda LBoolLambda) - (assert-equal? - '(lambda (f) (not (f #f))) - (unparse-LBoolLambda - (parse-LBoolLambda '(lambda (f) (not (f #f))))))))) - - (define datum? - (lambda (x) - (or (number? x) (string? x) (symbol? x) - (and (pair? x) (datum? (car x)) (datum? (cdr x))) - (and (vector? x) (for-all datum? (vector->list x)))))) - - (define-language LVAR - (terminals - (var (x)) - (primitive (pr)) - (datum (d))) - (Expr (e) - (var x) - (quote d) - (if e0 e1 e2) - (begin e0 ... e1) - (let ([x e] ...) e1) - (letrec ([x e] ...) e1) - (app e0 e1 ...) - (primapp pr e ...))) - - (define-pass break-variable : LVAR (ir) -> LVAR () - (definitions - (define var? symbol?)) - (Expr : Expr (ir) -> Expr () - [(var ,x) (printf "found var: ~a\n" (var-sym x)) `(var ,x)])) - - (test-suite ensure-correct-identifiers - (test accidental-variable?-capture - (assert-equal? - (with-output-to-string - (lambda () - (break-variable - (with-output-language (LVAR Expr) - `(var ,(make-var 'x)))))) - "found var: x\n"))) - - (define-language Lmaybe - (terminals - (boolean (b)) - (integer (i))) - (Exp (e) - (Int i) - (Bool b) - (Bar (maybe i) e) - (Foo i (maybe e)))) - - (define-parser parse-Lmaybe Lmaybe) - - (test-suite maybe-tests - (test maybe-parse/unparse - (assert-equal? - '(Int 72) - (unparse-Lmaybe (parse-Lmaybe '(Int 72)))) - (assert-equal? - '(Bool #t) - (unparse-Lmaybe (parse-Lmaybe '(Bool #t)))) - (assert-equal? - '(Bar 5 (Bool #t)) - (unparse-Lmaybe (parse-Lmaybe '(Bar 5 (Bool #t))))) - (assert-equal? - '(Bar #f (Bool #t)) - (unparse-Lmaybe (parse-Lmaybe '(Bar #f (Bool #t))))) - (assert-equal? - '(Foo 5 #f) - (unparse-Lmaybe (parse-Lmaybe '(Foo 5 #f)))) - (assert-equal? - '(Foo 5 (Foo 4 (Foo 3 #f))) - (unparse-Lmaybe (parse-Lmaybe '(Foo 5 (Foo 4 (Foo 3 #f)))))) - (assert-equal? - '(Foo 5 (Bar 3 (Foo 1 #f))) - (unparse-Lmaybe (parse-Lmaybe '(Foo 5 (Bar 3 (Foo 1 #f)))))) - (assert-equal? - '(Foo 5 (Int 3)) - (unparse-Lmaybe (parse-Lmaybe '(Foo 5 (Int 3)))))) - (test maybe-with-output-language/unparse - (assert-equal? - '(Int 72) - (unparse-Lmaybe (with-output-language (Lmaybe Exp) `(Int 72)))) - (assert-equal? - '(Bool #t) - (unparse-Lmaybe (with-output-language (Lmaybe Exp) `(Bool #t)))) - (assert-equal? - '(Bar 5 (Bool #t)) - (unparse-Lmaybe (with-output-language (Lmaybe Exp) `(Bar 5 (Bool #t))))) - (assert-equal? - '(Bar #f (Bool #t)) - (unparse-Lmaybe (with-output-language (Lmaybe Exp) `(Bar #f (Bool #t))))) - (assert-equal? - '(Foo 5 #f) - (unparse-Lmaybe (with-output-language (Lmaybe Exp) `(Foo 5 #f)))) - (assert-equal? - '(Foo 5 (Foo 4 (Foo 3 #f))) - (unparse-Lmaybe (with-output-language (Lmaybe Exp) `(Foo 5 (Foo 4 (Foo 3 #f)))))) - (assert-equal? - '(Foo 5 (Bar 3 (Foo 1 #f))) - (unparse-Lmaybe (with-output-language (Lmaybe Exp) `(Foo 5 (Bar 3 (Foo 1 #f)))))) - (assert-equal? - '(Foo 5 (Int 3)) - (unparse-Lmaybe (with-output-language (Lmaybe Exp) `(Foo 5 (Int 3)))))) - (test maybe-pass - (let () - (define-pass add-one-int : Lmaybe (ir) -> Lmaybe () - (Exp : Exp (ir) -> Exp () - [(Int ,i) `(Int ,(fx+ i 1))])) - (and - (assert-equal? - '(Int 4) - (unparse-Lmaybe (add-one-int (with-output-language (Lmaybe Exp) `(Int 3))))) - (assert-equal? - '(Foo 4 (Int 4)) - (unparse-Lmaybe (add-one-int (with-output-language (Lmaybe Exp) `(Foo 4 (Int 3)))))) - (assert-equal? - '(Foo 4 (Foo 5 (Int 3))) - (unparse-Lmaybe (add-one-int (with-output-language (Lmaybe Exp) `(Foo 4 (Foo 5 (Int 2))))))) - (assert-equal? - '(Foo 3 #f) - (unparse-Lmaybe (add-one-int (with-output-language (Lmaybe Exp) `(Foo 3 #f))))) - (assert-equal? - '(Bar #f (Int 5)) - (unparse-Lmaybe (add-one-int (with-output-language (Lmaybe Exp) `(Bar #f (Int 4)))))))) - (let () - (define-pass add-one : Lmaybe (ir) -> Lmaybe () - (Exp : Exp (ir) -> Exp () - [(Foo ,i ,[e?]) `(Foo ,(fx+ i 1) ,e?)] - [(Bar ,i? ,[e]) `(Bar ,(and i? (fx+ i? 1)) ,e)] - [(Int ,i) `(Int ,(fx+ i 1))])) - (and - (assert-equal? - '(Int 4) - (unparse-Lmaybe (add-one (with-output-language (Lmaybe Exp) `(Int 3))))) - (assert-equal? - '(Foo 5 (Int 4)) - (unparse-Lmaybe (add-one (with-output-language (Lmaybe Exp) `(Foo 4 (Int 3)))))) - (assert-equal? - '(Foo 5 (Foo 6 (Int 3))) - (unparse-Lmaybe (add-one (with-output-language (Lmaybe Exp) `(Foo 4 (Foo 5 (Int 2))))))) - (assert-equal? - '(Foo 4 (Bar 6 (Foo 7 #f))) - (unparse-Lmaybe (add-one (with-output-language (Lmaybe Exp) `(Foo 3 (Bar 5 (Foo 6 #f))))))) - (assert-equal? - '(Foo 4 (Bar #f (Foo 7 #f))) - (unparse-Lmaybe (add-one (with-output-language (Lmaybe Exp) `(Foo 3 (Bar #f (Foo 6 #f))))))))))) - - (define-language Lmaybe2 - (terminals - (boolean (b)) - (integer (i))) - (Exp (e) - (Int i) - (Bool b) - (Bar (maybe i) ... e) - (Foo i (maybe e) ...))) - - (define-parser parse-Lmaybe2 Lmaybe2) - - (test-suite maybe-dots-tests - (test maybe-parse/unparse - (assert-equal? - '(Foo 3) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Foo 3)))) - (assert-equal? - '(Bar (Int 72)) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Bar (Int 72))))) - (assert-equal? - '(Int 72) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Int 72)))) - (assert-equal? - '(Bool #t) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Bool #t)))) - (assert-equal? - '(Bar 5 (Bool #t)) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Bar 5 (Bool #t))))) - (assert-equal? - '(Bar #f (Bool #t)) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Bar #f (Bool #t))))) - (assert-equal? - '(Bar #f 1 #f 2 #f 3 (Bool #t)) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Bar #f 1 #f 2 #f 3 (Bool #t))))) - (assert-equal? - '(Bar 1 #f 2 #f 3 #f (Bool #t)) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Bar 1 #f 2 #f 3 #f (Bool #t))))) - (assert-equal? - '(Foo 5 #f) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Foo 5 #f)))) - (assert-equal? - '(Foo 5 #f #f (Bar 3 (Foo 2 #f)) (Bool #t) #f #f (Int 2) #f) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Foo 5 #f #f (Bar 3 (Foo 2 #f)) (Bool #t) #f #f (Int 2) #f)))) - (assert-equal? - '(Foo 5 (Foo 4 (Foo 3 #f (Bool #t) (Int 3)))) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Foo 5 (Foo 4 (Foo 3 #f (Bool #t) (Int 3))))))) - (assert-equal? - '(Foo 5 (Bar 3 (Foo 1 (Bar 2 (Bool #t)) #f #f))) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Foo 5 (Bar 3 (Foo 1 (Bar 2 (Bool #t)) #f #f)))))) - (assert-equal? - '(Foo 5 (Int 3) (Bool #f)) - (unparse-Lmaybe2 (parse-Lmaybe2 '(Foo 5 (Int 3) (Bool #f)))))) - (test maybe-with-output-language/unparse - (assert-equal? - '(Foo 3) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Foo 3)))) - (assert-equal? - '(Bar (Int 72)) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Bar (Int 72))))) - (assert-equal? - '(Int 72) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Int 72)))) - (assert-equal? - '(Bool #t) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Bool #t)))) - (assert-equal? - '(Bar 5 (Bool #t)) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Bar 5 (Bool #t))))) - (assert-equal? - '(Bar #f (Bool #t)) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Bar #f (Bool #t))))) - (assert-equal? - '(Bar #f 1 #f 2 #f 3 (Bool #t)) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Bar #f 1 #f 2 #f 3 (Bool #t))))) - (assert-equal? - '(Bar 1 #f 2 #f 3 #f (Bool #t)) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Bar 1 #f 2 #f 3 #f (Bool #t))))) - (assert-equal? - '(Foo 5 #f) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Foo 5 #f)))) - (assert-equal? - '(Foo 5 #f #f (Bar 3 (Foo 2 #f)) (Bool #t) #f #f (Int 2) #f) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Foo 5 #f #f (Bar 3 (Foo 2 #f)) (Bool #t) #f #f (Int 2) #f)))) - (assert-equal? - '(Foo 5 (Foo 4 (Foo 3 #f (Bool #t) (Int 3)))) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Foo 5 (Foo 4 (Foo 3 #f (Bool #t) (Int 3))))))) - (assert-equal? - '(Foo 5 (Bar 3 (Foo 1 (Bar 2 (Bool #t)) #f #f))) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Foo 5 (Bar 3 (Foo 1 (Bar 2 (Bool #t)) #f #f)))))) - (assert-equal? - '(Foo 5 (Int 3) (Bool #f)) - (unparse-Lmaybe2 (with-output-language (Lmaybe2 Exp) `(Foo 5 (Int 3) (Bool #f)))))) - (test maybe-pass - (let () - (define-pass add-one-int : Lmaybe2 (ir) -> Lmaybe2 () - (Exp : Exp (ir) -> Exp () - [(Int ,i) `(Int ,(fx+ i 1))])) - (and - (assert-equal? - '(Int 4) - (unparse-Lmaybe2 (add-one-int (with-output-language (Lmaybe2 Exp) `(Int 3))))) - (assert-equal? - '(Foo 4 (Int 4) (Int 5) (Int 7) #f #f (Int 8)) - (unparse-Lmaybe2 (add-one-int (with-output-language (Lmaybe2 Exp) `(Foo 4 (Int 3) (Int 4) (Int 6) #f #f (Int 7)))))) - (assert-equal? - '(Foo 4 (Foo 5 (Int 3) #f (Int 4) (Int 5))) - (unparse-Lmaybe2 (add-one-int (with-output-language (Lmaybe2 Exp) `(Foo 4 (Foo 5 (Int 2) #f (Int 3) (Int 4))))))) - (assert-equal? - '(Foo 3 #f (Int 4)) - (unparse-Lmaybe2 (add-one-int (with-output-language (Lmaybe2 Exp) `(Foo 3 #f (Int 3)))))) - (assert-equal? - '(Bar 3 #f 4 #f (Int 4)) - (unparse-Lmaybe2 (add-one-int (with-output-language (Lmaybe2 Exp) `(Bar 3 #f 4 #f (Int 3)))))))) - (let () - (define-pass add-one : Lmaybe2 (ir) -> Lmaybe2 () - (Exp : Exp (ir) -> Exp () - [(Foo ,i ,[e?*] ...) `(Foo ,(fx+ i 1) ,e?* ...)] - [(Bar ,i?* ... ,[e]) `(Bar ,(map (lambda (i?) (and i? (fx+ i? 1))) i?*) ... ,e)] - [(Int ,i) `(Int ,(fx+ i 1))])) - (and - (assert-equal? - '(Int 4) - (unparse-Lmaybe2 (add-one (with-output-language (Lmaybe2 Exp) `(Int 3))))) - (assert-equal? - '(Foo 5 (Int 4) (Int 5) (Int 6) #f (Int 8)) - (unparse-Lmaybe2 (add-one (with-output-language (Lmaybe2 Exp) `(Foo 4 (Int 3) (Int 4) (Int 5) #f (Int 7)))))) - (assert-equal? - '(Foo 5 (Foo 6 (Int 3) (Bar 4 3 2 #f 1 (Foo 3 (Int 8) (Int 9))))) - (unparse-Lmaybe2 (add-one (with-output-language (Lmaybe2 Exp) `(Foo 4 (Foo 5 (Int 2) (Bar 3 2 1 #f 0 (Foo 2 (Int 7) (Int 8))))))))) - (assert-equal? - '(Foo 4 (Bar 6 #f 8 #f 9 (Foo 7 #f)) (Bool #t) #f) - (unparse-Lmaybe2 (add-one (with-output-language (Lmaybe2 Exp) `(Foo 3 (Bar 5 #f 7 #f 8 (Foo 6 #f)) (Bool #t) #f))))) - (assert-equal? - '(Foo 4 (Bar #f (Foo 7 #f)) (Bool #t) #f) - (unparse-Lmaybe2 (add-one (with-output-language (Lmaybe2 Exp) `(Foo 3 (Bar #f (Foo 6 #f)) (Bool #t) #f))))))))) - - (define-language LMaybeNoBool - (terminals - (symbol (x)) - (number (n))) - (Expr (e) - (foo x (maybe n)) - (bar (maybe e) x) - (num n) - (ref x))) - - (define-language LMaybeListNoBool - (terminals - (symbol (x)) - (number (n))) - (Expr (e) - (foo ([x (maybe n)] ...) e) - (bar (maybe e) ... x) - (num n) - (ref x))) - - (test-suite maybe-unparse-tests - (test maybe-unparse - (assert-equal? '(foo x 10) - (unparse-LMaybeNoBool - (with-output-language (LMaybeNoBool Expr) - `(foo x 10)))) - (assert-equal? '(bar (foo x #f) x) - (unparse-LMaybeNoBool - (with-output-language (LMaybeNoBool Expr) - `(bar (foo x #f) x)))) - (assert-equal? '(bar (bar (foo y #f) y) z) - (unparse-LMaybeNoBool - (with-output-language (LMaybeNoBool Expr) - `(bar (bar (foo y #f) y) z)))) - (assert-equal? '(bar (bar (bar #f x) y) z) - (unparse-LMaybeNoBool - (with-output-language (LMaybeNoBool Expr) - `(bar (bar (bar #f x) y) z))))) - - (test maybe-unparse-dots - (assert-equal? '(foo ([x 10] [y 12]) (ref x)) - (unparse-LMaybeListNoBool - (with-output-language (LMaybeListNoBool Expr) - `(foo ([x 10] [y 12]) (ref x))))) - (assert-equal? '(foo ([x #f] [y 12] [z #f]) (ref y)) - (unparse-LMaybeListNoBool - (with-output-language (LMaybeListNoBool Expr) - `(foo ([x #f] [y 12] [z #f]) (ref y))))) - (assert-equal? '(bar #f #f (num 10) (ref x) #f (foo ([x #f] [y 10] [z 5] [w #f]) (bar #f z)) #f w) - (unparse-LMaybeListNoBool - (with-output-language (LMaybeListNoBool Expr) - `(bar #f #f (num 10) (ref x) #f (foo ([x #f] [y 10] [z 5] [w #f]) (bar #f z)) #f w)))))) - - ;; tests related to issue #7 on github.com - (define-language LPairs - (terminals - (symbol (x)) - (null (n))) - (Expr (e) - x - n - (e0 . e1))) - - (define-parser parse-LPairs LPairs) - - (define-pass reverse-pairs : LPairs (p) -> LPairs () - (Expr : Expr (p) -> Expr () - [(,[e0] . ,[e1]) `(,e1 . ,e0)])) - - (define-language LList - (terminals - (symbol (x)) - (null (n))) - (Expr (e) - x - n - (e0 ... . e1))) - - (define-parser parse-LList LList) - - (define-language LList2 - (terminals - (symbol (x)) - (null (n))) - (Expr (e) - x - n - (e0 ... e1))) - - (define-pass swap-parts : LList (e) -> LList () - (Expr : Expr (e) -> Expr () - [(,[e*] ... . ,[e]) - `(,e ,e* ... . ())])) - - ;; example provided by Simon Stapleton via bug #7 - (define-language Lx - (terminals - (symbol (x))) - (Expr (e) - x - (lambda (x* ... . x) e) - (define (x x* ... . x1) e) - (define x e))) - - (define-parser parse-Lx Lx) - - (define-pass Px1 : Lx (ir) -> Lx () - (Expr : Expr (ir) -> Expr() - [(define (,x ,x* ... . ,x1) ,[e]) - `(define ,x (lambda (,x* ... . ,x1) ,e))])) - - (test-suite language-dot-support - (test simple-dots - (assert-equal? - '() - (unparse-LPairs (parse-LPairs '()))) - (assert-equal? - 'a - (unparse-LPairs (parse-LPairs 'a))) - (assert-equal? - '(a) - (unparse-LPairs (parse-LPairs '(a)))) - (assert-equal? - '(a . b) - (unparse-LPairs (parse-LPairs '(a . b)))) - (assert-equal? - '(a b c . d) - (unparse-LPairs (parse-LPairs '(a b c . d)))) - (assert-equal? - '(((a b . c) d e) f . g) - (unparse-LPairs (parse-LPairs '(((a b . c) d e) f . g)))) - (assert-equal? - '() - (unparse-LPairs (with-output-language (LPairs Expr) `()))) - (assert-equal? - 'a - (unparse-LPairs (with-output-language (LPairs Expr) `a))) - (assert-equal? - '(a) - (unparse-LPairs (with-output-language (LPairs Expr) `(a)))) - (assert-equal? - '(a . b) - (unparse-LPairs (with-output-language (LPairs Expr) `(a . b)))) - (assert-equal? - '(a b c . d) - (unparse-LPairs (with-output-language (LPairs Expr) `(a b c . d)))) - (assert-equal? - '(((a b . c) d e) f . g) - (unparse-LPairs (with-output-language (LPairs Expr) `(((a b . c) d e) f . g)))) - (assert-equal? - '(() . a) - (unparse-LPairs (reverse-pairs (parse-LPairs '(a))))) - (assert-equal? - '(b . a) - (unparse-LPairs (reverse-pairs (parse-LPairs '(a . b))))) - (assert-equal? - '(((d . c) . b) . a) - (unparse-LPairs (reverse-pairs (parse-LPairs '(a b c . d))))) - (assert-equal? - '((g . f) ((() . e) . d) (c . b) . a) - (unparse-LPairs (reverse-pairs (parse-LPairs '(((a b . c) d e) f . g)))))) - (test dot-after-ellipsis - (assert-equal? - '() - (unparse-LList (parse-LList '()))) - (assert-equal? - 'x - (unparse-LList (parse-LList 'x))) - (assert-equal? - '(a b c) - (unparse-LList (parse-LList '(a b c)))) - (assert-equal? - '(a b c . d) - (unparse-LList (parse-LList '(a b c . d)))) - (assert-equal? - '(((a b) (c d)) e . f) - (unparse-LList (parse-LList '(((a b) (c d)) e . f)))) - (assert-equal? - '() - (unparse-LList (with-output-language (LList Expr) `()))) - (assert-equal? - 'x - (unparse-LList (with-output-language (LList Expr) `x))) - (assert-equal? - '(a b c) - (unparse-LList (with-output-language (LList Expr) `(a b c)))) - (assert-equal? - '(a b c . d) - (unparse-LList (with-output-language (LList Expr) `(a b c . d)))) - (assert-equal? - '(((a b) (c d)) e . f) - (unparse-LList (with-output-language (LList Expr) `(((a b) (c d)) e . f)))) - (assert-equal? - '(() a b c) - (unparse-LList (swap-parts (with-output-language (LList Expr) `(a b c))))) - (assert-equal? - '(d a b c) - (unparse-LList (swap-parts (with-output-language (LList Expr) `(a b c . d))))) - (assert-equal? - '(f (() (() a b) (() c d)) e) - (unparse-LList (swap-parts (with-output-language (LList Expr) `(((a b) (c d)) e . f)))))) - - (test github-issue-7 - (assert-equal? - 'x - (unparse-Lx (parse-Lx 'x))) - (assert-equal? - '(lambda (x . z) x) - (unparse-Lx (parse-Lx '(lambda (x . z) x)))) - (assert-equal? - '(lambda (x y . z) x) - (unparse-Lx (parse-Lx '(lambda (x y . z) x)))) - (assert-equal? - '(lambda x x) - (unparse-Lx (parse-Lx '(lambda x x)))) - (assert-equal? - '(define (x y . z) z) - (unparse-Lx (parse-Lx '(define (x y . z) z)))) - (assert-equal? - '(define x x) - (unparse-Lx (parse-Lx '(define x x)))) - (assert-equal? - '(define (l m . n) - (define g - (lambda (x . z) - (lambda (a . b) - (lambda (c . d) - l))))) - (unparse-Lx (parse-Lx '(define (l m . n) - (define g - (lambda (x . z) - (lambda (a . b) - (lambda (c . d) - l)))))))) - (assert-equal? - 'x - (unparse-Lx (with-output-language (Lx Expr) `x))) - (assert-equal? - '(lambda (x . z) x) - (unparse-Lx (with-output-language (Lx Expr) `(lambda (x . z) x)))) - (assert-equal? - '(lambda (x y . z) x) - (unparse-Lx (with-output-language (Lx Expr) `(lambda (x y . z) x)))) - (assert-equal? - '(define (x y . z) z) - (unparse-Lx (with-output-language (Lx Expr) `(define (x y . z) z)))) - (assert-equal? - '(lambda x x) - (unparse-Lx (with-output-language (Lx Expr) `(lambda x x)))) - (assert-equal? - '(define x x) - (unparse-Lx (with-output-language (Lx Expr) `(define x x)))) - (assert-equal? - '(define (l m . n) - (define g - (lambda (x . z) - (lambda (a . b) - (lambda (c . d) - l))))) - (unparse-Lx (with-output-language (Lx Expr) `(define (l m . n) - (define g - (lambda (x . z) - (lambda (a . b) - (lambda (c . d) - l)))))))) - (assert-equal? - '(define f (lambda (x . y) x)) - (unparse-Lx (Px1 (parse-Lx '(define (f x . y) x))))) - (assert-equal? - '(define g (lambda (x y z . w) w)) - (unparse-Lx (Px1 (parse-Lx '(define (g x y z . w) w))))) - (assert-equal? - '(define h (lambda (x y . z) (define i (lambda (a b c . d) d)))) - (unparse-Lx (Px1 (parse-Lx '(define (h x y . z) (define (i a b c . d) d)))))) - (assert-equal? - '(define f (lambda x (define g (lambda y x)))) - (unparse-Lx (Px1 (parse-Lx '(define (f . x) (define (g . y) x)))))))) - - (define-language LMULTI - (terminals - (var (x)) - (primitive (pr)) - (datum (d))) - (Expr (e) - (var x) - (primref pr) - (quote d) - (if e0 e1 e2) - (begin e0 ... e1) - (let ([x e] ...) e1) - (letrec ([x le] ...) e) - (app e0 e1 ...)) - (LambdaExpr (le) - (lambda (x ...) e) - (case-lambda cl ...)) - (CaseLambdaClause (cl) - (clause (x ...) e))) - - (define-language L-error - (terminals - (symbol (x))) - (Expr (e body) - x - (lambda (x* ...) body* ... body) - (let ([x* e*] ...) body* ... body) - (let-values ([(x** ...) e*] ...) body* ... body) - (e e* ...))) - - (define test-file - (let () - (define-syntax foo (lambda (x) (syntax-violation 'foo "unexpected call to foo" x))) - (source-information-source-file (syntax->source-information #'foo)))) - - (test-suite error-messages - (test run-time-error-messages - (assert-error - (format-error-message "Exception in with-output-language: expected list of symbol but received x in field x* of (lambda (x* ...) body* ... body) from expression ~s at line 872, char 23 of ~a" ''x test-file) - (with-output-language (L-error Expr) - `(lambda (,'x ...) z))) - (assert-error - (format-error-message "Exception in with-output-language: expected list of list of symbol but received x** in field x** of ~s from expression ~s at line 876, char 29 of ~a" '(let-values (((x** ...) e*) ...) body* ... body) ''x** test-file) - (with-output-language (L-error Expr) - `(let-values ([(,'x** ...) ,'(y)] ...) z))) - )) - - ;; regression test for error reported by R. Kent Dybvig: - - (define-language L - (terminals - (symbol (x))) - (A (a) b) - (B (b) x)) - - (define-pass P1 : L (ir) -> L () - (A : A (ir foo bar ignore) -> A ()) - (B : B (ir foo bar) -> B () - [else (printf "bar = ~s\n" bar) ir]) - (A ir "I am not bar" "I am bar" "extra stuff")) - - (define-pass P2 : L (ir) -> L () - (A : A (ir foo bar ignore) -> A ()) - (B : B (ir bar) -> B () - [else (printf "bar = ~s\n" bar) ir]) - (A ir "I am not bar" "I am bar" "extra stuff")) - - (define-pass P3 : L (ir) -> L () - (A : A (ir xxfoo xxbar ignore) -> A ()) - (B : B (ir foo bar) -> B () - [else (printf "bar = ~s\n" bar) ir]) - (B2 : B (ir) -> B () - [else (printf "calling B2\n") ir]) - (A ir "I am not bar" "I am bar" "extra stuff")) - - (define-pass P4 : L (ir) -> L () - (A : A (ir) -> A ()) - (B : B (ir [foo "I am not bar"] [bar "I am bar"]) -> B () - [else (printf "bar = ~s\n" bar) ir]) - (A ir)) - - (define-pass P5 : L (ir) -> L () - (B : B (ir foo bar ignore) -> B ()) - (symbol : symbol (ir foo bar) -> symbol () - (printf "bar = ~s\n" bar) - ir) - (B ir "I am not bar" "I am bar" "extra stuff")) - - (define-pass P6 : L (ir) -> L () - (B : B (ir foo bar ignore) -> B ()) - (symbol : symbol (ir bar) -> symbol () - (printf "bar = ~s\n" bar) - ir) - (B ir "I am not bar" "I am bar" "extra stuff")) - - (define-pass P7 : L (ir) -> L () - (B : B (ir foo bar ignore) -> B ()) - (symbol : symbol (ir xxfoo xxbar) -> symbol () - (printf "bar = ~s\n" xxbar) - ir) - (symbol2 : symbol (ir) -> symbol () - (printf "calling symbol2\n") - ir) - (B ir "I am not bar" "I am bar" "extra stuff")) - - (define-pass P8 : L (ir) -> L () - (B : B (ir) -> B ()) - (symbol : symbol (ir [foo "I am not bar"] [bar "I am bar"]) -> symbol () - (printf "bar = ~s\n" bar) - ir) - (B ir)) - - (define-pass P9 : L (ir foo bar ignore) -> L () - (A : A (ir foo bar) -> A () - [else (printf "bar = ~s\n" bar) ir])) - - (define-pass P10 : L (ir foo bar ignore) -> L () - (A : A (ir bar) -> A () - [else (printf "bar = ~s\n" bar) ir])) - - (define-pass P11 : L (ir foo bar ignore) -> L () - (A : A (ir xxfoo xxbar) -> A ()) - (A2 : A (ir) -> A () - [else (printf "calling A2\n") ir])) - - (define-pass P12 : L (ir) -> L () - (A : A (ir [foo "I am not bar"] [bar "I am bar"]) -> A () - [else (printf "bar = ~s\n" bar) ir])) - - (test-suite argument-name-matching - (test sub-nonterminal-regression - (assert-equal? - "bar = \"I am bar\"\n" - (with-output-to-string (lambda () (P1 'q)))) - (assert-equal? - "bar = \"I am bar\"\n" - (with-output-to-string (lambda () (P2 'q)))) - (assert-equal? - "calling B2\n" - (with-output-to-string (lambda () (P3 'q)))) - (assert-equal? - "bar = \"I am bar\"\n" - (with-output-to-string (lambda () (P4 'q))))) - (test sub-terminal-regression - (assert-equal? - "bar = \"I am bar\"\n" - (with-output-to-string (lambda () (P5 'q)))) - (assert-equal? - "bar = \"I am bar\"\n" - (with-output-to-string (lambda () (P6 'q)))) - (assert-equal? - "calling symbol2\n" - (with-output-to-string (lambda () (P7 'q)))) - (assert-equal? - "bar = \"I am bar\"\n" - (with-output-to-string (lambda () (P8 'q))))) - (test sub-terminal-regression - (assert-equal? - "bar = \"I am bar\"\n" - (with-output-to-string - (lambda () (P9 'q "I am not bar" "I am bar" "extra stuff")))) - (assert-equal? - "bar = \"I am bar\"\n" - (with-output-to-string - (lambda () (P10 'q "I am not bar" "I am bar" "extra stuff")))) - (assert-equal? - "calling A2\n" - (with-output-to-string - (lambda () (P11 'q "I am not bar" "I am bar" "extra stuff")))) - (assert-equal? - "bar = \"I am bar\"\n" - (with-output-to-string - (lambda () (P12 'q)))))) - - (define (ski-combinator? x) (memq x '(S K I))) - - (define-language Lski - (terminals - (ski-combinator (C))) - (Expr (e) - C - (e0 e1))) - - (define-language Llc - (terminals - (symbol (x))) - (Expr (e) - x - (lambda (x) e) - (e0 e1))) - - (define-pass ski->lc : Lski (ir) -> Llc () - (definitions - (define-syntax with-variables - (syntax-rules () - [(_ (x* ...) body0 body1 ...) - (let* ([x* (make-variable 'x*)] ...) body0 body1 ...)])) - (define counter 0) - (define inc-counter - (lambda () - (let ([count counter]) - (set! counter (fx+ count 1)) - count))) - (define make-variable - (lambda (x) - (string->symbol - (format "~s.~s" x (inc-counter)))))) - (Expr : Expr (e) -> Expr () - [,C (case C - [(S) (with-variables (x y z) - `(lambda (,x) - (lambda (,y) - (lambda (,z) - ((,x ,z) (,y ,z))))))] - [(K) (with-variables (x y) - `(lambda (,x) - (lambda (,y) - ,x)))] - [(I) (with-variables (x) - `(lambda (,x) ,x))])] - [(,e0 ,e1) - (let* ([e0 (Expr e0)] [e1 (Expr e1)]) - `(,e0 ,e1))])) - - (define-pass ski-in : * (ir) -> Lski () - (Expr : * (ir) -> Expr () - (cond - [(memq ir '(S K I)) ir] - [(and (list? ir) (= (length ir) 2)) - (let ([e0 (car ir)] [e1 (cdr ir)]) - `(,(Expr e0) ,(Expr e1)))] - [else (errorf who "unrecognized ski input ~s" ir)])) - (Expr ir)) - - (define-pass lc-out : Llc (ir) -> * (sexpr) - (Expr : Expr (ir) -> * (sexpr) - [(lambda (,x) ,[sexpr]) `(lambda (,x) ,sexpr)] - [(,[sexpr0] ,[sexpr1]) `(,sexpr0 ,sexpr1)] - [,x x]) - (Expr ir)) - - (test-suite pass-parser-unparser - (test pass-parsers - (assert-equal? - '((S K) I) - ((pass-input-parser ski-in) '((S K) I))) - (assert-equal? - (with-output-language (Lski Expr) - `((S K) I)) - ((pass-input-parser ski->lc) '((S K) I))) - (assert-equal? - (with-output-language (Llc Expr) - `(lambda (x) (x x))) - ((pass-input-parser lc-out) '(lambda (x) (x x))))) - (test pass-unparsers - (assert-equal? - '((S I) K) - ((pass-output-unparser ski-in) - (with-output-language (Lski Expr) - `((S I) K)))) - (assert-equal? - '((lambda (x) (x x)) (lambda (y) (y y))) - ((pass-output-unparser ski->lc) - (with-output-language (Llc Expr) - `((lambda (x) (x x)) (lambda (y) (y y)))))) - (assert-equal? - 'bob - ((pass-output-unparser lc-out) 'bob))) - (test pass-parser-unparser - (assert-equal? - '(((lambda (x.0) (lambda (y.1) x.0)) (lambda (x.2) x.2)) (lambda (x.3) x.3)) - ((pass-output-unparser ski->lc) (ski->lc ((pass-input-parser ski->lc) '((K I) I))))))) - - ) diff --git a/ta6ob/petite.1 b/ta6ob/petite.1 deleted file mode 100644 index 971941e..0000000 --- a/ta6ob/petite.1 +++ /dev/null @@ -1,799 +0,0 @@ -.ds s \fIChez Scheme\fP -.ds p \fIPetite Chez Scheme\fP -.if t .ds c caf\o'\'e' -.if n .ds c cafe -.ds ]W -.TH SCHEME 1 "Chez Scheme Version 9.5.9 April 2022" -.SH NAME -\fIChez Scheme\fP -.br -\fIPetite Chez Scheme\fP -.SH SYNOPSIS -\fBscheme\fP [ \fIoptions\fP ] \fIfile\fP ... -.br -\fBpetite\fP [ \fIoptions\fP ] \fIfile\fP ... -.SH DESCRIPTION -\*s is a programming language, based on R6RS Scheme, and a -high-performance implementation of that language. -\*s compiles source expressions \fIincrementally\fP to machine code, -providing the speed of compiled code in an interactive system. -.LP -\*p is an interpreted version of \*s that may be -used as a run-time environment for \*s applications or as a -stand-alone Scheme system. -With the exception that the compiler is not present, \*p is 100% -compatible with \*s. -Interpreted code is fast in \*p, but generally not nearly as fast as -compiled code. -Debugging and profiling support is also limited for interpreted -code. -.LP -Scheme is normally used interactively. The system prompts -the user with a right angle bracket (\*(lq>\*(rq) at the beginning of each -input line. Any Scheme expression may be entered. The system evaluates -the expression and prints the result. After printing -the result, the system prompts again for more input. -The user can exit the system by typing -Control-D or by using the procedure \fIexit\fP. -.SH COMMAND-LINE OPTIONS -.LP -\*s recognizes the following command line options: -.TP 1i -.B -q, --quiet -Suppress greeting and prompts. -.TP -.B --script \fIfile\fP -Run \fIfile\fP as a shell script. -.TP -.B --program \fIfile\fP -Run rnrs program in \fIfile\fP as a shell script. -.TP -.B --libdirs \fIdir\fP:... -Set library directories to \fIdir\fP:.... -.TP -.B --libexts \fIext\fP:... -Set library extensions to \fIext\fP:.... -.TP -.B --compile-imported-libraries -Compile libraries before loading them. -.TP -.B --import-notify -Enable import search messages. -.TP -.B --optimize-level 0 | 1 | 2 | 3 -Set optimize level to 0, 1, 2, or 3. -.TP -.B --debug-on-exception -On uncaught exception, call debug. -.TP -.B --eedisable -Disables the expression editor. -.TP -.B --eehistory off | \fIfile\fP -Set expression-editor history file or disable restore and save of history. -.TP -.B --enable-object-counts -Have collector maintain object counts. -.TP -.B --retain-static-relocation -Keep reloc information for compute-size, etc. -.TP -.B -b \fIfile\fP, --boot \fIfile\fP -Load boot code from \fIfile\fP. -.TP -.B --verbose -Trace boot search process. -.TP -.B --version -Print version and exit. -.TP -.B --help -Print brief command-line help and exit. -.TP -.B -- -Pass all remaining command-line arguments through to Scheme. -.LP -The following options are recognized but cause the system to print an -error message and exit because saved heaps are not presently supported. -.TP 1in -.B -h \fIfile\fP, --heap \fIfile\fP -.TP -.B -s[\fIlevel\fP] \fIfile\fP, --saveheap[\fIlevel\fP] \fIfile\fP -.TP -.B -c, --compact -.LP -Any remaining command-line arguments are treated as the names of -files to be loaded before Chez Scheme begins interacting with the -user (see COMMAND-LINE FILE ARGUMENTS), unless \*(lq--script\*(rq or -\*(lq--program\*(rq is present, in which case the remaining arguments -are made available to the script via the \fIcommand-line\fP parameter -(see SCHEME SCRIPTS). -.SH WAITERS and CAFES -.LP -Interaction of the system with the user is performed -by a Scheme program called a \fIwaiter\fP, running in a -program state called a \fI\*c\fP. The waiter -merely prompts, reads, evaluates, prints and loops -back for more. It is possible to open up a chain of \*s -\*cs by invoking the \fInew-cafe\fP procedure with no arguments. -New-cafe is also one of the options when an interrupt -occurs. Each \*c has its own reset and exit procedures. -Exiting from one \*c in the chain returns you to the next one -back, and so on, until the entire chain closes and you leave the -system altogether. Sometimes it is useful to -interrupt a long computation by typing the interrupt character, -enter a new \*c to execute something (perhaps to check a status -variable set by computation), and exit the \*c back to the old -computation. -.LP -You can tell what level you are at by the number of angle brackets -in the prompt, one for level one, two for level two, and so on. -Three angle brackets in the prompt means you would have to exit from -three \*cs to get out of \*s. If you wish to abort -from \*s and you are several \*cs deep, the procedure -\fIabort\fP leaves the system directly. -.LP -You can exit the system by typing the end-of-file character -(normally Control-D) or by using the procedure \fIexit\fP. -Typing Control-D is equivalent to (exit), (exit (void)), or -(exit 0), each of which is considered a \*(lqnormal exit\*(rq. -.SH DEBUGGER -Ordinarily, if an exception occurs during interactive use of the system, -the default exception handler displays -the condition with which the exception was raised, saves it for -possibly later use by the debugger, and prints the message -"type (debug) to enter the debugger." -Once in the debugger, the user has the option of inspecting the -raise continuation, i.e., the stack frames of the pending calls. -When an exception occurs in a script or top level program, or when the -standard input and/or output ports are redirected, the default exception -handler does not save the continuation of the exception and does not print -the "type (debug)" message. -.LP -If the parameter debug-on-exception is set to #t, however, the default -exception handler directly invokes debug, whether running interactively or -not, and even when running a script or top-level program. -The \*(lq--debug-on-exception\*(rq option may be used to set -debug-on-exception to #t from the command line, which is particularly -useful when debugging scripts or top-level programs run via the -\*(lq--script\*(rq or \*(lq--program\*(rq options. -.LP -None of this applies to exceptions raised with a non-serious (warning) -condition, for which the default exception handler simply displays the -condition and returns. -.SH KEYBOARD INTERRUPTS -Running programs may be interrupted by typing the interrupt -character (normally Control-C). In response, the -system enters a break handler, which prompts for input with a -\*(lqbreak>\*(rq prompt. -Several commands may be issued to the break handler, including -\*(lqe\*(rq to exit from the handler and continue, -\*(lqr\*(rq to reset to the current \*c, -\*(lqa\*(rq to abort \*s, -\*(lqn\*(rq to enter a new \*c, -\*(lqi\*(rq to inspect the current continuation, and -\*(lqs\*(rq to display statistics about the interrupted program. -While typing an expression to the waiter, the interrupt character -simply resets to the current \*c. -.SH EXPRESSION EDITOR -.LP -When \*s is used interactively in a -shell window, the waiter's \*(lqprompt and read\*(rq -procedure employs an expression editor that permits entry and editing of -single- and multiple-line expressions, automatically indents expressions -as they are entered, and supports name-completion based on the identifiers -defined in the interactive environment. -The expression editor also maintains a history of expressions typed during -and across sessions and supports tcsh(1)-like history movement and search -commands. -Other editing commands include simple cursor movement via -arrow keys, deletion of characters via backspace and delete, and -movement, deletion, and other commands using mostly -emacs key bindings. -.LP -The expression editor does not run if the TERM environment variable is -not set, if the standard input or output files have been redirected, or -if the --eedisable command-line option has been used. -The history is saved across sessions, by default, in the file -\*(lq$HOME/.chezscheme_history\*(rq. -The --eehistory command-line option -can be used to specify a different -location for the history file or to disable the saving and restoring of -the history file. -.LP -Keys for nearly all printing characters (letters, digits, and special -characters) are \*(lqself inserting\*(rq by default. -The open parenthesis, close parenthesis, open bracket, and close bracket -keys are self inserting as well, but also cause the editor to \*(lqflash\*(rq -to the matching delimiter, if any. -Furthermore, when a close parenthesis or close bracket is typed, it is -automatically corrected to match the corresponding open delimiter, if any. -.LP -Key bindings for other keys and key sequences initially recognized by -the expression editor are given below, organized into groups by function. -Some keys or key sequences serve more than one purpose depending upon -context. -For example, tab is used both for identifier completion and for -indentation. -Such bindings are shown in each applicable functional group. -.LP -Multiple-key sequences are displayed with hyphens between the keys of -the sequences, but these hyphens should not be entered. -When two or more key sequences perform the same operation, the sequences -are shown separated by commas. -.LP -Newlines, acceptance, exiting, and redisplay: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -enter, ^M accept balanced entry if used at end of entry; -.br - else add a newline before the cursor and indent -.br -^J accept entry unconditionally -.br -^O insert newline after the cursor and indent -.br -^D exit from the waiter if entry is empty; -.br - else delete character under cursor -.br -^Z suspend to shell if shell supports job control -.br -^L redisplay entry -.br -^L-^L clear screen and redisplay entry -.br -.LP -Basic movement and deletion: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -left, ^B move cursor left -.br -right, ^F move cursor right -.br -up, ^P move cursor up; from top of unmodified entry, -.br - move to preceding history entry. -.br -down, ^N move cursor down; from bottom of unmodified entry, -.br - move to next history entry. -.br -^D delete character under cursor if entry not empty; -.br - else exit from the waiter. -.br -backspace, ^H delete character before cursor -.br -.br -delete delete character under cursor -.br -.LP -Line movement and deletion: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -home, ^A move cursor to beginning of line -.br -end, ^E move cursor to end of line -.br -^K, esc-k delete to end of line or, if cursor is at the end -.br - of a line, join with next line -.br -^U delete contents of current line -.LP -When used on the first line of a multiline entry of which only the first line -is displayed, i.e., immediately after history movement, ^U deletes the -contents of the entire entry, like ^G (described below). -.br -.LP -Expression movement and deletion: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -esc-^F move cursor to next expression -.br -esc-^B move cursor to preceding expression -.br -esc-] move cursor to matching delimiter -.br -^] flash cursor to matching delimiter -.br -esc-^K, esc-delete delete next expression -.br -esc-backspace, esc-^H delete preceding expression -.br -.LP -Entry movement and deletion: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -esc-< move cursor to beginning of entry -.br -esc-> move cursor to end of entry -.br -^G delete current entry contents -.br -^C delete current entry contents; reset to end of history -.br -.LP -Indentation: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -tab re-indent current line if identifier prefix not -.br - just entered; else insert identifier completion -.br -esc-tab re-indent current line unconditionally -.br -esc-q, esc-Q, esc-^Q re-indent each line of entry -.br -.LP -Identifier completion: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -tab insert identifier completion if just entered -.br - identifier prefix; else re-indent current line -.br -tab-tab show possible identifier completions at end of -.br - identifier just typed, else re-indent -.br -^R insert next identifier completion -.LP -If at end of existing identifier, i.e., not one just typed, the first tab -re-indents, the second tab inserts identifier completion, and the third -shows possible completions. -.br -.LP -History movement: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -up, ^P move to preceding entry if at top of unmodified -.br - entry; else move up within entry -.br -down, ^N move to next entry if at bottom of unmodified -.br - entry; else move down within entry -.br -esc-up, esc-^P move to preceding entry from unmodified entry -.br -esc-down, esc-^N move to next entry from unmodified entry -.br -esc-p search backward through history for given prefix -.br -esc-n search forward through history for given prefix -.br -esc-P search backward through history for given string -.br -esc-N search forward through history for given string -.br -.LP -To search, enter a prefix or string followed by one of the search key -sequences. -Follow with additional search key sequences to search further backward or -forward in the history. -For example, enter \*(lq(define\*(rq followed by one or more esc-p key sequences -to search backward for entries that are definitions, or \*(lq(define\*(rq -followed by one or more esc-P key sequences for entries that contain -definitions. -.br -.LP -Word and page movement: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -esc-f, esc-F move cursor to end of next word -.br -esc-b, esc-B move cursor to start of preceding word -.br -^X-[ move cursor up one screen page -.br -^X-] move cursor down one screen page -.br -.LP -Inserting saved text: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -^Y insert most recently deleted text -.br -^V insert contents of window selection/paste buffer -.br -.LP -Mark operations: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -^@, ^space, ^^ set mark to current cursor position -.br -^X-^X move cursor to mark, leave mark at old cursor -.br -^W delete between current cursor position and mark -.br -.LP -Command repetition: -.LP -.ta \w'{xxxxxxxxxxxxx}'u+.25i -esc-^U repeat next command four times -.br -esc-^U-\fIn\fP repeat next command \fIn\fP times -.br -.SH TOP-LEVEL ENVIRONMENT SEMANTICS -.LP -Upon startup, the \*(lqinteraction environment\*(rq used to -hold the top-level bindings for user-defined variables and other -identifiers contains an initial set of bindings, some standard -and some specific to \*s. -Any initial identifier binding may be replaced by redefining -the identifier with a normal top-level definition. -For example, the initial binding for \fIcons\fP can be replaced -with one that performs a "reverse cons" as follows. -.br -.sp -(define cons (lambda (x y) (import scheme) (cons y x))) -.br -.sp -Code entered into the REPL or loaded from a file prior to this -point will still use the original binding for \fIcons\fP. -If you want it to use the new binding, you must reenter or reload -the code. -Furthermore, the initial bindings for variables like \fIcons\fP are immutable, -so you cannot assign one (e.g., via set! or trace) without first defining -it. -This allows the system to check to make sure it receives the expected -two arguments at compile time and generate inline code to allocate -the pair. -This is not the case if \fIcons\fP is redefined, even if redefined to have -the same value, since its value can be changed via set! at any time -during a program run. -.SH COMMAND-LINE FILE ARGUMENTS -.LP -In the normal mode of operation, -the file names on the command line (except for the arguments -to the various command-line options) are -loaded before \*s begins interacting with the user. Each of the -expressions in the loaded files is executed just as if it were -typed by the user in response to a prompt. If you wish to load a -set of definitions each time, consider setting up a shell script to -load the file \*(lq.schemerc\*(rq from your home directory: -.br -.sp - scheme ${HOME}/.schemerc $* -.sp -.br -If you have a -substantial number of definitions to load each time, it might -be worthwhile to compile the .schemerc file (that is, compile -the definitions and name the resulting object file .schemerc). -.LP -Typically, a Scheme programmer creates a source file of -definitions and other Scheme forms using an editor such as -\fIvi\fP(1) or \fIemacs\fP(1) -and loads the file into Scheme to test them. The -conventional filename extension for \*s source files -is \fI.ss\fP. Such a file may be loaded during a session by typing -(load \*(lq\fIfilename\fP\*(rq), or by specifying the filename on -the command line as mentioned above. Any expression that may be -typed interactively may be placed in a file to be loaded. -.SH SCHEME SCRIPTS -.LP -When the \*(lq--script\*(rq option is used, the named file is -treated as a Scheme shell script, and the script name and remaining -command-line arguments are made available via the parameter -\*(lqcommand-line\*(rq. -To support executable shell scripts, the system ignores the first -line of a loaded script if it begins with #! followed by -a space or forward slash. -For example, the following script prints its command-line arguments. -.br -.sp -#! /usr/local/bin/scheme --script -.br -(for-each -.br - (lambda (x) (display x) (newline)) -.br - (cdr (command-line))) -.SH RNRS TOP-LEVEL PROGRAMS -.LP -The \*(lq--program\*(rq option is like the \*(lq--script\*(rq option -except that the script file is treated as an RNRS top-level program. -The following RNRS top-level program prints its command-line arguments, as -with the script above. -.br -.sp -#! /usr/local/bin/scheme --program -.br -(import (rnrs)) -.br -(for-each -.br - (lambda (x) (display x) (newline)) -.br - (cdr (command-line))) -.LP -\*(lqscheme-script\*(rq may be used in place of \*(lqscheme --program\*(rq, -possibly prefixed by \*(lq/usr/bin/env\*(rq as suggested in the nonnormative -R6RS appendix on running top-level programs as scripts, i.e., the first line -of the top-level program may be replaced with the following. -.br -.sp -#! /usr/bin/env scheme-script -.br -.LP -If a top-level program depends on libraries other than those built into -\*s, the \*(lq--libdirs\*(rq option can be used to specify -which source and object directories to search. -Similarly, if a library upon which a top-level program depends has an -extension other than one of the standard extensions, the -\*(lq--libexts\*(rq option can be used to specify additional extensions -to search. -.LP -These options set the corresponding \*s parameters -library-directories and library-extensions. -The values of both parameters are lists of pairs of strings. -The first string in each library-directories pair identifies a -source-file root directory, and the second identifies the corresponding -object-file root directory. -Similarly, the first string in each library-extensions pair -identifies a source-file extension, and the second identifies the -corresponding object-file extension. -The full path of a library source or object file consists of the source or -object root followed by the components of the library name prefixed by -slashes, with the library extension added on the end. -For example, for root /usr/lib/scheme, library name -(app lib1), and extension .sls, the full path is -/usr/lib/scheme/app/lib1.sls. -.LP -The format of the arguments to \*(lq--libdirs\*(rq and -\*(lq--libexts\*(rq is the same: -a sequence of substrings separated by a single separator -character. -The separator character is a colon (:), except under Windows where it is a -semi-colon (;). -Between single separators, the source and object strings, if both are -specified, are separated by two separator characters. -If a single separator character appears at the end of the string, -the specified pairs are added to the existing list; otherwise, the -specified pairs replace the existing list. -The parameters are set after all boot files have been loaded. -.LP -If multiple \*(lq--libdirs\*(rq options appear, all but the final -one are ignored, and if -If multiple \*(lq--libexts\*(rq options appear, all but the final -are ignored. -If no \*(lq--libdirs\*(rq option appears and the CHEZSCHEMELIBDIRS -environment variable is set, the string value of CHEZSCHEMELIBDIRS is -treated as if it were specified by a \*(lq--libdirs\*(rq option. -Similarly, if no \*(lq--libexts\*(rq option appears and the CHEZSCHEMELIBEXTS -environment variable is set, the string value of CHEZSCHEMELIBEXTS is -treated as if it were specified by a \*(lq--libexts\*(rq option. -.LP -The library-directories and library-extensions -parameters set by these options are consulted by the expander when it -encounters an import for a library that has not previously been defined or -loaded. -The expander first constructs a partial name from the list of components in the -library name, e.g., \*(lqa/b\*(rq for library (a b). -It then searches for the partial name in each pair -of root directories, in order, trying each of the source extensions then -each of the object extensions in turn before moving onto the next pair of -root directories. -If the partial name is an absolute pathname, e.g., \*(lq~/.myappinit\*(rq -for a library named (~/.myappinit), only the specified absolute -path is searched, first with each source extension, then with each object -extension. -If the expander finds both a source file and its corresponding object -file, and the object file is not older than the source file, the -expander loads the object file. -If the object file does not exist, if the object file is older, or -if after loading the object file, the expander determines it was -built using a library or include file that has changed, the source -file is loaded or compiled, depending on the value of the parameter -compile-imported-libraries. -If compile-imported-libraries -is set to #t, the expander -compiles the library via compile-library (which is described below). -Otherwise, the expander loads the source file. -(Loading the source file actually causes the code to be compiled, -assuming the default value of current-eval, but the compiled -code is not saved to an object file.) -An exception is raised during this process if a -source or object file exists but is not readable or if an object -file cannot be created. -.LP -The search process used by the expander when processing an import -for a library that has not yet been loaded can be monitored by -setting the parameter import-notify to #t. -This parameter can be set from the command line via the -\*(lq--import-notify\*(rq command-line option. -.SH OPTIMIZE LEVELS -The \*(lq--optimize-level\*(rq option sets the initial value of the -\*s optimize-level parameter to 0, 1, 2, or 3. -The value is 0 by default. -.LP -At optimize-levels 0, 1, and 2, code generated by the compiler is -\fIsafe\fP, i.e., generates full type and bounds checks. -At optimize-level 3, code generated by the compiler is \fIunsafe\fP, -i.e., may omit these checks. -Unsafe code is usually faster, but optimize-level 3 should be used only -for well-tested code since the absence of type and bounds checks may -result in invalid memory references, corruption of the Scheme heap (which -may cause seemingly unrelated problems later), system crashes, or other -undesirable behaviors. -.LP -At present, there is no direct difference other than safety among -optimize levels. -.SH COMPILING FILES -.LP -\*s compiles source expressions as it sees them. In -order to speed loading of a large file, the file may be compiled -with the output placed in an object file. -(compile-file \*(lqfoo\*(rq) compiles the expressions in the file -\*(lqfoo.ss\*(rq and places the resulting object code on the file -\*(lqfoo.so\*(rq. Loading a pre-compiled file is no different from -loading the source file, except that loading is faster since -compilation is already done. -.LP -To compile a program to be run with --program, use -compile-program instead of compile-file. -compile-program preserves the first line unchanged, if it begins -with #! followed by a forward slash or space. -Also, while compile-file compresses the resulting object file, -compile-program does not do so if the #! line is present, so -it can be recognized by the shell's script executor. -Any libraries upon which the top-level program depends, other than -built-in libraries, must be compiled first via compile-file -or compile-library. -This can be done manually or by setting the parameter -compile-imported-libraries to #t before compiling the program. -.LP -To compile a script to be run with --script, use -compile-script instead of compile-file. -compile-script is like compile-program, but, like compile-file, implements -the interactive top-level semantics rather than the RNRS top-level -program semantics. -.SH BOOT and HEAP FILES -.LP -When \*s is run, it looks for one or more boot files to load. -Boot files contain the compiled Scheme code that implements most of -the Scheme system, including the interpreter, compiler, and most -libraries. -Boot files may be specified explicitly on the command -line via \*(lq-b\*(rq options or implicitly. -In the simplest case, no \*(lq-b\*(rq options -are given and the necessary boot files are loaded -automatically based on the name of the executable. -For example, if the executable name is \*(lqmyapp\*(rq, the -system looks for \*(lqmyapp.boot\*(rq in a set of standard -directories. -It also looks for and loads any subordinate boot files required -by \*(lqmyapp.boot\*(rq. -Subordinate boot files are also loaded automatically for the -first boot file explicitly specified via the command line. -When multiple boot files are specified via the command line and boot each -file must be listed before those that depend upon it. -.LP -The \*(lq--verbose\*(rq option may be used to trace the boot file -searching process and must appear before any boot arguments -for which search tracing is desired. -.LP -Ordinarily, the search for boot files is limited to a set of -default installation directories, but this may be overridden by setting -the environment variable SCHEMEHEAPDIRS. -SCHEMEHEAPDIRS should be a colon-separated list of directories, listed in -the order in which they should be searched. -Within each directory, the two-character escape sequence \*(lq%v\*(rq -is replaced by the current version, and the two-character escape sequence -\*(lq%m\*(rq is replaced by the machine type. -A percent followed by any other character is replaced by the second -character; in particular, \*(lq%%\*(rq is replaced by \*(lq%\*(rq, and -\*(lq%:\*(rq is replaced by \*(lq:\*(rq. -If SCHEMEHEAPDIRS ends in a non-escaped colon, the default directories are -searched after those in SCHEMEHEAPDIRS; otherwise, only those listed in -SCHEMEHEAPDIRS are searched. -Under Windows, semi-colons are used in place of colons. -.LP -Boot files consist of a header followed by ordinary compiled code and -may be created with make-boot-file. -For example, -.br -.sp - (make-boot-file "myapp.boot" '("petite") - "myapp1.so" "myapp2.so") -.sp -.br -creates a boot file containing the code from myapp1.so and myapp2.so -with a header identifying petite.boot as a boot file upon which the new -boot file depends. -Source files can be provided as well and are compiled on-the-fly -by make-boot-header. -.LP -Multiple alternatives for the boot file upon which the new boot -file depends can be listed, e.g.: -.br -.sp - (make-boot-file "myapp.boot" '("petite" "scheme") - "myapp1.so" "myapp2.so") -.sp -.br -When possible, both \*(lqscheme\*(lq and \*(lqpetite\*(lq should be -specified when creating a boot file for an application, as shown above, so -that the application can run in either \*p or \*s. -If the application requires the use of the compiler, just -\*(lqscheme\*(lq should be specified. -.LP -If the new boot file is to be a base boot file, i.e., one that does not -depend on another boot file, petite.boot (or some other boot file created -from petite.boot) should be listed first among the input files. -.br -.sp - (make-boot-file "myapp.boot" '() "petite.boot" - "myapp1.so" "myapp2.so") -.sp -.br -.SH DOCUMENTATION -.LP -Complete documentation for \*s is available in two parts: -\fIThe Scheme Programming Language, 4th Edition\fP, and -\fIThe Chez Scheme Version 9 User's Guide\fP. -The first document is available in printed form from MIT Press, -and links to online versions of both documents are available -at https://cisco.github.io/ChezScheme/. -.LP -Several example Scheme programs, ranging from a simple factorial procedure -to a somewhat complex unification algorithm, are in the examples directory -(see FILES below). Looking at and trying out example programs is a good way -to start learning Scheme. -.SH ENVIRONMENT -.LP -The environment variable -.B SCHEMEHEAPDIRS \fR -(see above) may be set -to a colon-separated (semi-colon under Windows) list of directories -in which to search for boot files. -.SH FILES -.if 0 COMMENT: put the longest path from below in the tab computation: -.ta \w'/usr/local/lib/csv9.5.9/examples'u+.25i -/usr/local/bin/scheme executable file -.br -/usr/local/bin/petite executable file -.br -/usr/local/bin/scheme-script executable file -.br -/usr/local/lib/csv9.5.9/examples example program library -.br -/usr/local/lib/csv9.5.9/ta6ob boot and include files -.sp -.br -.SH SEE ALSO -.in +5 -.br -.ti -5 -R. Kent Dybvig, -\fIThe Scheme Programming Language, 4th Edition\fP, -MIT Press (2009), http://www.scheme.com/tspl4/. -.br -.ti -5 -\fIChez Scheme Version 9 User's Guide\fP, -Cisco Systems, Inc. -.br -.ti -5 -Michael Sperber, R. Kent Dybvig, Matthew Flatt, and Anton van Straaten, eds., -.if t \*(lqRevised\u6\d Report on the Algorithmic Language Scheme,\*(rq -.if n \*(lqRevised^6 Report on the Algorithmic Language Scheme,\*(rq -(2007), http://www.r6rs.org/. -.br -.ti -5 -Daniel P. Friedman and Matthias Felleisen, -\fIThe Little Schemer\fP, fourth edition, -MIT Press (1996). -.br -.ti -5 -Harold Abelson and Gerald J. Sussman with Julie Sussman, -\fIStructure and Interpretation of Computer Programs, -Second Edition\fP, -MIT press (1996). -.in -5 -.SH AUTHOR -Copyright 2022 Cisco Systems, Inc. -Licensed under the Apache License, Version 2.0 -(http://www.apache.org/licenses/LICENSE-2.0) diff --git a/ta6ob/pkg/Makefile b/ta6ob/pkg/Makefile deleted file mode 100644 index 7f833ae..0000000 --- a/ta6ob/pkg/Makefile +++ /dev/null @@ -1,108 +0,0 @@ -# Makefile -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -m := $(shell find ../bin/* -type d | xargs basename) -version = 9.5.9 -release = 1 - -DOTUSER = $(shell ls -ld . | sed -e 's/[^ ]* *[^ ]* *\([^ ]*\).*/\1/') -DOTGROUP = $(shell ls -ldg . | sed -e 's/[^ ]* *[^ ]* *\([^ ]*\).*/\1/') -BUILDROOT = $(m)$(version) -RELEASE = csv$(version) -TARBALL = $(RELEASE)-$(m).tar.gz -PKG = $(RELEASE)-$(m)-$(release).pkg - -PKGCONTENT =\ - $(BUILDROOT)/Resources/en.lproj/Welcome.html\ - $(BUILDROOT)/Resources/en.lproj/License.txt\ - $(BUILDROOT)/Distribution\ - $(BUIDROOT)/Root/bin\ - $(BUILDROOT)/Root/lib\ - $(BUILDROOT)/Root/man - -$(PKG): $(BUILDROOT)/$(PKG) - sudo /usr/bin/productbuild\ - --resources $(BUILDROOT)/Resources\ - --distribution $(BUILDROOT)/Distribution\ - --package-path $(BUILDROOT)\ - $(PKG) - sudo chown $(DOTUSER):$(DOTGROUP) $(PKG) - sudo rm -rf $(RELEASE) $(BUILDROOT) - -$(BUILDROOT)/$(PKG): $(PKGCONTENT) - sudo /usr/bin/pkgbuild\ - --root $(BUILDROOT)/Root\ - --identifier chezscheme\ - --version $(version)\ - --install-location /\ - --ownership recommended\ - $(BUILDROOT)/$(PKG) - -$(BUILDROOT)/Distribution: $(BUILDROOT) - echo '' > $(BUILDROOT)/Distribution - echo '' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' Chez Scheme' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' ' >> $(BUILDROOT)/Distribution - echo ' #$(PKG)' >> $(BUILDROOT)/Distribution - echo '' >> $(BUILDROOT)/Distribution - chmod 644 $(BUILDROOT)/Distribution - -$(BUILDROOT)/Resources/en.lproj/Welcome.html: $(BUILDROOT)/Resources/en.lproj - echo '' > $(BUILDROOT)/Resources/en.lproj/Welcome.html - echo '

Chez Scheme Version $(version)

' >> $(BUILDROOT)/Resources/en.lproj/Welcome.html - echo '

Copyright © 2022 Cisco Systems, Inc.

' >> $(BUILDROOT)/Resources/en.lproj/Welcome.html - echo '

Chez Scheme is a programming language and an implementation of that language, with supporting tools and documentation.

' >> $(BUILDROOT)/Resources/en.lproj/Welcome.html - echo '' >> $(BUILDROOT)/Resources/en.lproj/Welcome.html - chmod 644 $(BUILDROOT)/Resources/en.lproj/Welcome.html - -$(BUILDROOT)/Resources/en.lproj/License.txt: $(BUILDROOT)/Resources/en.lproj - cat ../../NOTICE ../../LICENSE > $(BUILDROOT)/Resources/en.lproj/License.txt - chmod 644 $(BUILDROOT)/Resources/en.lproj/License.txt - -$(BUILDROOT)/Resources/en.lproj: $(BUILDROOT)/Resources - install -d $(BUILDROOT)/Resources/en.lproj - -$(BUILDROOT)/Resources: $(BUILDROOT) - install -d $(BUILDROOT)/Resources - -$(BUIDROOT)/Root/bin $(BUILDROOT)/Root/lib $(BUILDROOT)/Root/man: $(BUILDROOT)/Root $(RELEASE) - ( cd $(RELEASE); sudo make install InstallGroup=wheel TempRoot=../$(BUILDROOT)/Root ) - -$(BUILDROOT)/Root: $(BUILDROOT) - install -d $(BUILDROOT)/Root - -$(RELEASE): $(BUILDROOT) ../bintar/$(TARBALL) - tar -xzf ../bintar/$(TARBALL) - -$(BUILDROOT): - install -d $(BUILDROOT) - -clean: - rm -rf $(PKG) $(BUILDROOT) $(RELEASE) diff --git a/ta6ob/pkg/rmpkg b/ta6ob/pkg/rmpkg deleted file mode 100755 index c3a19ea..0000000 --- a/ta6ob/pkg/rmpkg +++ /dev/null @@ -1,37 +0,0 @@ -#! /bin/csh -f - -# rmpkg -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -if ( $#argv != 1) then - echo "Usage: sudo $0 release" - echo " e.g.,: sudo $0 8.4" - exit 1 -endif - -if ( `id -u` != 0 ) then - echo "$0 must be run as root (e.g., via sudo)" - exit 1 -endif - -set R = $1 - -if (!(-e /usr/local/lib/csv$R)) then - echo "(Petite) Chez Scheme Version $R doesn't appear to be installed" - exit -endif - -/bin/rm -rf /usr/local/bin/petite /usr/local/bin/scheme /usr/local/bin/scheme-script /usr/local/lib/csv$R /usr/local/share/man/man1/petite.1.gz /usr/local/share/man/man1/scheme.1.gz -pkgutil --forget chezscheme diff --git a/ta6ob/rpm/Makefile b/ta6ob/rpm/Makefile deleted file mode 100644 index 28fb388..0000000 --- a/ta6ob/rpm/Makefile +++ /dev/null @@ -1,84 +0,0 @@ -# Makefile -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -version = 9.5.9 -release = 1 -m := $(shell find ../bin/* -type d | xargs basename) -arch := $(shell if test "$(m)" == "i3le" ; then echo i686 ; elif test "$(m)" == "a6le" ; then echo x86_64 ; else echo UNKNOWN ; fi) -DOTUSER := $(shell ls -ld . | sed -e 's/[^ ]* *[^ ]* *\([^ ]*\).*/\1/') -DOTGROUP := $(shell ls -ldg . | sed -e 's/[^ ]* *[^ ]* *\([^ ]*\).*/\1/') -TMP := $(shell pwd)/tmp -SPEC = $(TMP)/ChezScheme-$(version)-$(arch)-$(release).spec -RELEASE = csv$(version) -TARBALL = $(RELEASE)-$(m).tar.gz -RPM = ChezScheme-$(version)-$(release).$(arch).rpm - - -$(RPM): $(TMP)/$(RPM) - sudo install -m 644 -o $(DOTUSER) -g $(DOTGROUP) $(TMP)/${RPM} . - -$(TMP)/$(RPM): $(SPEC) $(TMP)/$(TARBALL) - sudo setarch $(arch) rpmbuild\ - --target $(arch)\ - --define "_topdir $(TMP)" \ - --define "_srcrpmdir $(TMP)" \ - --define "_rpmdir $(TMP)" \ - --define "_sourcedir $(TMP)" \ - --define "_builddir $(TMP)" \ - --define "_rpmfilename %{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm" \ - --quiet -ba $(SPEC) - -$(SPEC): $(TMP) - echo 'Summary: Chez Scheme: A high-performance version of Scheme' > $(SPEC) - echo 'Name: ChezScheme' >> $(SPEC) - echo 'Version: $(version)' >> $(SPEC) - echo 'Release: $(release)' >> $(SPEC) - echo 'Provides: ChezScheme-runtime-{VERSION}' >> $(SPEC) - echo 'License: Apache 2.0' >> $(SPEC) - echo 'URL: http://github.com/cisco/chezscheme' >> $(SPEC) - echo 'Group: Development/Languages' >> $(SPEC) - echo 'Source0: $(TARBALL)' >> $(SPEC) - echo 'BuildRoot: %{_tmppath}/%{name}' >> $(SPEC) - echo '%description' >> $(SPEC) - echo 'Chez Scheme is a programming language and an implementation of that language,' >> $(SPEC) - echo 'with supporting tools and documentation.' >> $(SPEC) - echo '' >> $(SPEC) - echo '%prep' >> $(SPEC) - echo '' >> $(SPEC) - echo '%setup -T -b 0 -n $(RELEASE)' >> $(SPEC) - echo '' >> $(SPEC) - echo '#%build' >> $(SPEC) - echo '' >> $(SPEC) - echo '%install' >> $(SPEC) - echo 'make install TempRoot=%{buildroot}' >> $(SPEC) - echo '' >> $(SPEC) - echo '%files' >> $(SPEC) - echo '#%doc NOTICE' >> $(SPEC) - echo '#%doc LICENSE' >> $(SPEC) - echo '/usr/lib/$(RELEASE)' >> $(SPEC) - echo '/usr/bin/petite' >> $(SPEC) - echo '/usr/bin/scheme' >> $(SPEC) - echo '/usr/bin/scheme-script' >> $(SPEC) - echo '/usr/share/man/man1/petite.1.gz' >> $(SPEC) - echo '/usr/share/man/man1/scheme.1.gz' >> $(SPEC) - -$(TMP)/$(TARBALL): $(TMP) ../bintar/$(TARBALL) - cp ../bintar/$(TARBALL) $(TMP) - -$(TMP): - mkdir $(TMP) - -clean: - rm -rf $(TMP) $(RPM) diff --git a/ta6ob/s/4.ss b/ta6ob/s/4.ss deleted file mode 100644 index 4bd58a1..0000000 --- a/ta6ob/s/4.ss +++ /dev/null @@ -1,421 +0,0 @@ -;;; 4.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(begin -(define-who apply - (let () - (define-syntax build-apply - (lambda (x) - (syntax-case x () - [(_ () cl ...) - #'(case-lambda - [(p r) - (unless (procedure? p) - ($oops #f "attempt to apply non-procedure ~s" p)) - (let ([n ($list-length r who)]) - (case n - [(0) (p)] - [(1) (p (car r))] - [(2) (p (car r) (cadr r))] - [(3) (let ([y1 (cdr r)]) (p (car r) (car y1) (cadr y1)))] - [else ($apply p n r)]))] - cl ... - [(p x . r) - (unless (procedure? p) - ($oops #f "attempt to apply non-procedure ~s" p)) - (let ([r (cons x ($apply list* ($list-length r who) r))]) - ($apply p ($list-length r who) r))])] - [(_ (s1 s2 ...) cl ...) - (with-syntax ((m (length #'(s1 s2 ...)))) - #'(build-apply - (s2 ...) - [(p s1 s2 ... r) - (unless (procedure? p) - ($oops #f "attempt to apply non-procedure ~s" p)) - (let ([n ($list-length r who)]) - (case n - [(0) (p s1 s2 ...)] - [(1) (p s1 s2 ... (car r))] - [(2) (p s1 s2 ... (car r) (cadr r))] - [(3) (let ([y1 (cdr r)]) - (p s1 s2 ... (car r) (car y1) (cadr y1)))] - [else ($apply p (fx+ n m) (list* s1 s2 ... r))]))] - cl ...))]))) - (build-apply (x1 x2 x3 x4)))) - -(let () - (define length-error - (lambda (who l1 l2) - ($oops who "lists ~s and ~s differ in length" l1 l2))) - - (define nonprocedure-error - (lambda (who what) - ($oops who "~s is not a procedure" what))) - - (define length-check - (lambda (who first rest) - (let ([n ($list-length first who)]) - (let loop ([rest rest]) - (cond - [(null? rest) n] - [(fx= ($list-length (car rest) who) n) (loop (cdr rest))] - [else (length-error who first (car rest))]))))) - - (define mutation-error - (lambda (who) - ($oops who "input list was altered during operation"))) - - ; getcxrs returns the cdrs of ls and their cars - (define getcxrs - (lambda (ls who) - (if (null? ls) - (values '() '()) - (let-values ([(cdrs cars) (getcxrs (cdr ls) who)]) - (let ([d (cdar ls)]) - (unless (pair? d) (mutation-error who)) - (values (cons d cdrs) (cons (car d) cars))))))) - - (let () - (define-syntax do-ormap - (syntax-rules () - [(_ who) - (case-lambda - [(f ls) - (unless (procedure? f) (nonprocedure-error who f)) - (and (not (null? ls)) - (let ormap ([n ($list-length ls who)] [ls ls]) - (if (fx= n 1) - (f (car ls)) - (or (f (car ls)) - (let ([ls (cdr ls)]) - (unless (pair? ls) (mutation-error who)) - (ormap (fx- n 1) ls))))))] - [(f ls . more) - (unless (procedure? f) (nonprocedure-error who f)) - (let ([n (length-check who ls more)]) - (and (not (fx= n 0)) - (let ormap ([n n] [ls ls] [more more] [cars (map car more)]) - (if (fx= n 1) - (apply f (car ls) cars) - (or (apply f (car ls) cars) - (let ([ls (cdr ls)]) - (unless (pair? ls) (mutation-error who)) - (let-values ([(cdrs cars) (getcxrs more who)]) - (ormap (fx- n 1) ls cdrs cars))))))))])])) - (set-who! ormap (do-ormap who)) - (set-who! exists (do-ormap who))) - - (let () - (define-syntax do-andmap - (syntax-rules () - [(_ who) - (case-lambda - [(f ls) - (unless (procedure? f) (nonprocedure-error who f)) - (or (null? ls) - (let andmap ([n ($list-length ls who)] [ls ls]) - (if (fx= n 1) - (f (car ls)) - (and (f (car ls)) - (let ([ls (cdr ls)]) - (unless (pair? ls) (mutation-error who)) - (andmap (fx- n 1) ls))))))] - [(f ls . more) - (unless (procedure? f) (nonprocedure-error who f)) - (let ([n (length-check who ls more)]) - (or (fx= n 0) - (let andmap ([n n] [ls ls] [more more] [cars (map car more)]) - (if (fx= n 1) - (apply f (car ls) cars) - (and (apply f (car ls) cars) - (let ([ls (cdr ls)]) - (unless (pair? ls) (mutation-error who)) - (let-values ([(cdrs cars) (getcxrs more who)]) - (andmap (fx- n 1) ls cdrs cars))))))))])])) - (set-who! andmap (do-andmap who)) - (set-who! for-all (do-andmap who))) - - (set-who! map - (case-lambda - [(f ls) - (unless (procedure? f) (nonprocedure-error who f)) - ($list-length ls who) - ; library map cdrs first to avoid getting sick if f mutates input - (#3%map f ls)] - [(f ls1 ls2) - (unless (procedure? f) (nonprocedure-error who f)) - (unless (fx= ($list-length ls1 who) ($list-length ls2 who)) - (length-error who ls1 ls2)) - ; library map cdrs first to avoid getting sick if f mutates input - (#3%map f ls1 ls2)] - [(f ls . more) - (unless (procedure? f) (nonprocedure-error who f)) - (length-check who ls more) - (let map ([f f] [ls ls] [more more]) - (if (null? ls) - '() - ; cdr first to avoid getting sick if f mutates input - (let ([tail (map f (cdr ls) (#3%map cdr more))]) - (cons (apply f (car ls) (#3%map car more)) tail))))])) - - (set! $map - ; same as map but errors are reported as coming from who - (case-lambda - [(who f ls) - (unless (procedure? f) (nonprocedure-error who f)) - ($list-length ls who) - ; library map cdrs first to avoid getting sick if f mutates input - (#3%map f ls)] - [(who f ls1 ls2) - (unless (procedure? f) (nonprocedure-error who f)) - (unless (fx= ($list-length ls1 who) ($list-length ls2 who)) - (length-error who ls1 ls2)) - ; library map cdrs first to avoid getting sick if f mutates input - (#3%map f ls1 ls2)] - [(who f ls . more) - (unless (procedure? f) (nonprocedure-error who f)) - (length-check who ls more) - (let map ([f f] [ls ls] [more more]) - (if (null? ls) - '() - ; cdr first to avoid getting sick if f mutates input - (let ([tail (map f (cdr ls) (#3%map cdr more))]) - (cons (apply f (car ls) (#3%map car more)) tail))))])) - - (set-who! for-each - (case-lambda - [(f ls) - (unless (procedure? f) (nonprocedure-error who f)) - (unless (null? ls) - (let for-each ([n ($list-length ls who)] [ls ls]) - (if (fx= n 1) - (f (car ls)) - (begin - (f (car ls)) - (let ([ls (cdr ls)]) - (unless (pair? ls) (mutation-error who)) - (for-each (fx- n 1) ls))))))] - [(f ls . more) - (unless (procedure? f) (nonprocedure-error who f)) - (let ([n (length-check who ls more)]) - (unless (fx= n 0) - (let for-each ([n n] [ls ls] [more more] [cars (map car more)]) - (if (fx= n 1) - (apply f (car ls) cars) - (begin - (apply f (car ls) cars) - (let ([ls (cdr ls)]) - (unless (pair? ls) (mutation-error who)) - (let-values ([(cdrs cars) (getcxrs more who)]) - (for-each (fx- n 1) ls cdrs cars))))))))])) - - (set-who! fold-left - (case-lambda - [(combine nil ls) - (unless (procedure? combine) (nonprocedure-error who combine)) - (cond - [(null? ls) nil] - [else - ($list-length ls who) - (let fold-left ([ls ls] [acc nil]) - (let ([cdrls (cdr ls)]) - (if (pair? cdrls) - (fold-left cdrls (combine acc (car ls))) - (if (null? cdrls) - (combine acc (car ls)) - (mutation-error who)))))])] - [(combine nil ls . more) - (unless (procedure? combine) (nonprocedure-error who combine)) - (length-check who ls more) - (if (null? ls) - nil - (let fold-left ([ls ls] [more more] [cars (map car more)] [acc nil]) - (let ([cdrls (cdr ls)]) - (if (null? cdrls) - (apply combine acc (car ls) cars) - (let ([acc (apply combine acc (car ls) cars)]) - (unless (pair? cdrls) (mutation-error who)) - (let-values ([(cdrs cars) (getcxrs more who)]) - (fold-left cdrls cdrs cars acc)))))))])) - - (set-who! fold-right - (case-lambda - [(combine nil ls) - (unless (procedure? combine) (nonprocedure-error who combine)) - ($list-length ls who) - ; #3%fold-right naturally does cdrs first to avoid mutation sickness - (#3%fold-right combine nil ls)] - [(combine nil ls1 ls2) - (unless (procedure? combine) (nonprocedure-error who combine)) - (unless (fx= ($list-length ls1 who) ($list-length ls2 who)) - (length-error who ls1 ls2)) - ; #3%fold-right naturally does cdrs first to avoid mutation sickness - (#3%fold-right combine nil ls1 ls2)] - [(combine nil ls . more) - (unless (procedure? combine) (nonprocedure-error who combine)) - (length-check who ls more) - (let fold-right ([combine combine] [nil nil] [ls ls] [more more]) - (if (null? ls) - nil - (apply combine (car ls) - (#3%fold-right cons - (list (fold-right combine nil (cdr ls) (map cdr more))) - (map car more)))))])) -) - -(let () - (define disable/enable (make-winder #f disable-interrupts enable-interrupts)) - - (define (dwind in body out) - (let ((old-winders ($current-winders))) - (in) - ($current-winders (cons (make-winder #f in out) old-winders)) - (call-with-values - body - (case-lambda - [(x) - ($current-winders old-winders) - (out) - x] - [args - ($current-winders old-winders) - (out) - (apply values args)])))) - - (define (cwind in body out) - (let* ((old-winders ($current-winders)) - [d/e+old-winders (cons disable/enable old-winders)]) - (disable-interrupts) - ($current-winders d/e+old-winders) - (in) - ($current-winders (cons (make-winder #t in out) old-winders)) - (enable-interrupts) - (call-with-values - body - (case-lambda - [(x) - (disable-interrupts) - ($current-winders d/e+old-winders) - (out) - ($current-winders old-winders) - (enable-interrupts) - x] - [args - (disable-interrupts) - ($current-winders d/e+old-winders) - (out) - ($current-winders old-winders) - (enable-interrupts) - (apply values args)])))) - - (define (check-args in body out) - (unless (procedure? in) - ($oops 'dynamic-wind "~s is not a procedure" in)) - (unless (procedure? body) - ($oops 'dynamic-wind "~s is not a procedure" body)) - (unless (procedure? out) - ($oops 'dynamic-wind "~s is not a procedure" out))) - - (set! dynamic-wind - (case-lambda - [(in body out) - (check-args in body out) - (dwind in body out)] - [(critical? in body out) - (check-args in body out) - (if critical? - (cwind in body out) - (dwind in body out))])) - - (set-who! #(r6rs: dynamic-wind) - (lambda (in body out) - (#2%dynamic-wind in body out))) - - (set! $do-wind - (lambda (old new) - (define common-tail - (lambda (x y) - (let ([lx (length x)] [ly (length y)]) - (do ([x (if (fx> lx ly) (list-tail x (fx- lx ly)) x) (cdr x)] - [y (if (fx> ly lx) (list-tail y (fx- ly lx)) y) (cdr y)]) - ((eq? x y) x))))) - (let ([tail (common-tail old new)]) - (let f ((old old)) - (unless (eq? old tail) - (let ([w (car old)] [old (cdr old)]) - (if (winder-critical? w) - (begin - (disable-interrupts) - ($current-winders (cons disable/enable old)) - ((winder-out w)) - ($current-winders old) - (enable-interrupts)) - (begin - ($current-winders old) - ((winder-out w)))) - (f old)))) - (let f ([new new]) - (unless (eq? new tail) - (let ([w (car new)]) - (f (cdr new)) - (if (winder-critical? w) - (begin - (disable-interrupts) - ($current-winders (cons disable/enable (cdr new))) - ((winder-in w)) - ($current-winders new) - (enable-interrupts)) - (begin - ((winder-in w)) - ($current-winders new))))))))) -) - - -;;; make-promise and force - -(define-who $make-promise - (lambda (thunk) - (unless (procedure? thunk) - ($oops who "~s is not a procedure" thunk)) - (let ([value (void)] [set? #f]) - (lambda () - (case set? - [(single) value] - [(multiple) (apply values value)] - [else - (call-with-values - thunk - (case-lambda - [(x) - (case set? - [(single) value] - [(multiple) (apply values value)] - [(#f) (set! value x) - (set! set? 'single) - x])] - [x - (case set? - [(single) value] - [(multiple) (apply values value)] - [(#f) (set! value x) - (set! set? 'multiple) - (apply values x)])]))]))))) - -(define-who force - (lambda (promise) - (unless (procedure? promise) - ($oops who "~s is not a procedure" promise)) - (promise))) -) diff --git a/ta6ob/s/4.ta6ob b/ta6ob/s/4.ta6ob deleted file mode 100644 index 763b5b6..0000000 Binary files a/ta6ob/s/4.ta6ob and /dev/null differ diff --git a/ta6ob/s/5_1.ss b/ta6ob/s/5_1.ss deleted file mode 100644 index d0b8180..0000000 --- a/ta6ob/s/5_1.ss +++ /dev/null @@ -1,335 +0,0 @@ -;;; 5_1.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; type and generic predicates - -(begin -(define boolean? - (lambda (x) - (or (eq? x #t) (eq? x #f)))) - -(define not - (lambda (x) - (if x #f #t))) - -(define eqv? - (lambda (x y) - (eqv? x y))) - -(define (equal? x y) - (define k0 200) - (define kb -20) - - #;(define (union-find ht x y) ; hashtable-ref/set! version - (define (find b) ; splitting - (let ([n (car b)]) ; next or census - (if (pair? n) - (let loop ([b b] [n n]) - (let ([nn (car n)]) - (if (pair? nn) - (begin (set-car! b nn) (loop n nn)) - n))) - b))) - (let ([bx (eq-hashtable-ref ht x #f)] - [by (eq-hashtable-ref ht y #f)]) - (if (not bx) - (if (not by) - (let ([b (list 1)]) - (eq-hashtable-set! ht x b) - (eq-hashtable-set! ht y b) - #f) - (begin - (eq-hashtable-set! ht x (find by)) - #f)) - (if (not by) - (begin - (eq-hashtable-set! ht y (find bx)) - #f) - (let ([rx (find bx)] [ry (find by)]) - (or (eq? rx ry) - (let ([nx (car rx)] [ny (car ry)]) - (if (fx> nx ny) - (begin - (set-car! ry rx) - (set-car! rx (fx+ nx ny)) - #f) - (begin - (set-car! rx ry) - (set-car! ry (fx+ ny nx)) - #f))))))))) - - (define (union-find ht x y) ; htcell version - (define (find p n) ; splitting - (if (pair? n) - (let loop ([p p] [n n]) - (let ([nn (cdr n)]) - (if (pair? nn) - (begin (set-cdr! p nn) (loop n nn)) - n))) - p)) - (let ([ax (eq-hashtable-cell ht x 0)] - [ay (eq-hashtable-cell ht y 0)]) - (let ([nx (cdr ax)] [ny (cdr ay)]) - (if (eq? nx 0) - (if (eq? ny 0) - (begin - (set-cdr! ax ay) - (set-cdr! ay 1) - #f) - (begin - (set-cdr! ax (find ay ny)) - #f)) - (if (eq? ny 0) - (begin - (set-cdr! ay (find ax nx)) - #f) - (let ([rx (find ax nx)] [ry (find ay ny)]) - (or (eq? rx ry) - (let ([nx (cdr rx)] [ny (cdr ry)]) - (if (fx> nx ny) - (begin - (set-cdr! ry rx) - (set-cdr! rx (fx+ nx ny)) - #f) - (begin - (set-cdr! rx ry) - (set-cdr! ry (fx+ ny nx)) - #f)))))))))) - - (define (interleave? x y k) - (let ([ht (make-eq-hashtable)]) - (define (e? x y k) - (if (fx<= k 0) - (if (fx= k kb) - (fast? x y (random (* 2 k0))) - (slow? x y k)) - (fast? x y k))) - (define (slow? x y k) - (cond - [(eq? x y) k] - [(pair? x) - (and (pair? y) - (if (union-find ht x y) - 0 - (let ([k (e? (car x) (car y) (fx- k 1))]) - (and k (e? (cdr x) (cdr y) k)))))] - [(vector? x) - (and (vector? y) - (let ([n (vector-length x)]) - (and (fx= (vector-length y) n) - (if (union-find ht x y) - 0 - (let f ([i 0] [k (fx- k 1)]) - (if (fx= i n) - k - (let ([k (e? (vector-ref x i) (vector-ref y i) k)]) - (and k (f (fx+ i 1) k)))))))))] - [(string? x) (and (string? y) (string=? x y) k)] - [(flonum? x) (and (flonum? y) ($fleqv? x y) k)] - [($inexactnum? x) - (and ($inexactnum? y) - ($fleqv? ($inexactnum-real-part x) ($inexactnum-real-part y)) - ($fleqv? ($inexactnum-imag-part x) ($inexactnum-imag-part y)) - k)] - [(bignum? x) (and (bignum? y) (= x y) k)] - [(ratnum? x) (and (ratnum? y) (= x y) k)] - [($exactnum? x) (and ($exactnum? y) (= x y) k)] - [(bytevector? x) (and (bytevector? y) (bytevector=? x y) k)] - [(fxvector? x) - (and (fxvector? y) - (fx= (fxvector-length x) (fxvector-length y)) - (let f ([i (fx- (fxvector-length x) 1)]) - (if (fx< i 0) - k - (and (fx= (fxvector-ref x i) (fxvector-ref y i)) - (f (fx1- i))))))] - [(box? x) - (and (box? y) - (if (union-find ht x y) - 0 - (e? (unbox x) (unbox y) (fx- k 1))))] - [($record? x) - (and ($record? y) - (let ([rec-equal? ($record-equal-procedure x y)]) - (and rec-equal? - (if (union-find ht x y) - 0 - (let ([next-k k] [decr 1]) - (and (rec-equal? x y - (lambda (x1 y1) - ; decrementing only on first subfield, if any, like vectors and pairs - (let ([k (e? x1 y1 (fx- next-k decr))]) - (and k - (begin - (set! next-k k) - (set! decr 0) - #t))))) - next-k))))))] - [else (and (eqv? x y) k)])) - (define (fast? x y k) - (let ([k (fx- k 1)]) - (cond - [(eq? x y) k] - [(pair? x) - (and (pair? y) - (let ([k (e? (car x) (car y) k)]) - (and k (e? (cdr x) (cdr y) k))))] - [(vector? x) - (and (vector? y) - (let ([n (vector-length x)]) - (and (fx= (vector-length y) n) - (let f ([i 0] [k k]) - (if (fx= i n) - k - (let ([k (e? (vector-ref x i) (vector-ref y i) k)]) - (and k (f (fx+ i 1) k))))))))] - [(string? x) (and (string? y) (string=? x y) k)] - [(flonum? x) (and (flonum? y) ($fleqv? x y) k)] - [($inexactnum? x) - (and ($inexactnum? y) - ($fleqv? ($inexactnum-real-part x) ($inexactnum-real-part y)) - ($fleqv? ($inexactnum-imag-part x) ($inexactnum-imag-part y)) - k)] - [(bignum? x) (and (bignum? y) (= x y) k)] - [(ratnum? x) (and (ratnum? y) (= x y) k)] - [($exactnum? x) (and ($exactnum? y) (= x y) k)] - [(bytevector? x) (and (bytevector? y) (bytevector=? x y) k)] - [(fxvector? x) - (and (fxvector? y) - (fx= (fxvector-length x) (fxvector-length y)) - (let f ([i (fx- (fxvector-length x) 1)]) - (if (fx< i 0) - k - (and (fx= (fxvector-ref x i) (fxvector-ref y i)) - (f (fx1- i))))))] - [(box? x) (and (box? y) (e? (unbox x) (unbox y) k))] - [($record? x) - (and ($record? y) - (let ([rec-equal? ($record-equal-procedure x y)]) - (and rec-equal? - (let ([next-k k]) - (and (rec-equal? x y - (lambda (x1 y1) - (let ([k (e? x1 y1 next-k)]) - (and k - (begin - (set! next-k k) - #t))))) - next-k)))))] - [else (and (eqv? x y) k)]))) - (and (e? x y k) #t))) - - (define (precheck? x y k) - (cond - [(eq? x y) k] - [(pair? x) - (and (pair? y) - (if (fx<= k 0) - k - (let ([k (precheck? (car x) (car y) (fx- k 1))]) - (and k (precheck? (cdr x) (cdr y) k)))))] - [(vector? x) - (and (vector? y) - (let ([n (vector-length x)]) - (and (fx= (vector-length y) n) - (let f ([i 0] [k k]) - (if (or (fx= i n) (fx<= k 0)) - k - (let ([k (precheck? - (vector-ref x i) - (vector-ref y i) - (fx- k 1))]) - (and k (f (fx+ i 1) k))))))))] - [(string? x) (and (string? y) (string=? x y) k)] - [(flonum? x) (and (flonum? y) ($fleqv? x y) k)] - [($inexactnum? x) - (and ($inexactnum? y) - ($fleqv? ($inexactnum-real-part x) ($inexactnum-real-part y)) - ($fleqv? ($inexactnum-imag-part x) ($inexactnum-imag-part y)) - k)] - [(bignum? x) (and (bignum? y) (= x y) k)] - [(ratnum? x) (and (ratnum? y) (= x y) k)] - [($exactnum? x) (and ($exactnum? y) (= x y) k)] - [(bytevector? x) (and (bytevector? y) (bytevector=? x y) k)] - [(fxvector? x) - (and (fxvector? y) - (fx= (fxvector-length x) (fxvector-length y)) - (let f ([i (fx- (fxvector-length x) 1)]) - (if (fx< i 0) - k - (and (fx= (fxvector-ref x i) (fxvector-ref y i)) - (f (fx1- i))))))] - [(box? x) - (and (box? y) - (if (fx<= k 0) - k - (precheck? (unbox x) (unbox y) (fx- k 1))))] - [($record? x) - (and ($record? y) - (let ([rec-equal? ($record-equal-procedure x y)]) - (and rec-equal? - (if (fx<= k 0) - k - (let ([next-k k]) - (and (rec-equal? x y - (lambda (x1 y1) - ; decrementing k for each field, like vectors but unlike pairs - (let ([k (precheck? x1 y1 (fx- next-k 1))]) - (and k - (begin - (set! next-k k) - #t))))) - next-k))))))] - [else (and (eqv? x y) k)])) - - (let ([k (precheck? x y k0)]) - (and k (or (fx> k 0) (interleave? x y 0))))) - -(define boolean=? - (case-lambda - [(b1 b2) - (unless (boolean? b1) ($oops 'boolean=? "~s is not a boolean" b1)) - (unless (boolean? b2) ($oops 'boolean=? "~s is not a boolean" b2)) - (#3%boolean=? b1 b2)] - [(b1 b2 . b*) - (unless (boolean? b1) ($oops 'boolean=? "~s is not a boolean" b1)) - (unless (boolean? b2) ($oops 'boolean=? "~s is not a boolean" b2)) - (for-each - (lambda (b) (unless (boolean? b) ($oops 'boolean=? "~s is not a boolean" b))) - b*) - (and (#3%boolean=? b1 b2) - (let f ([b* b*]) - (or (null? b*) - (and (#3%boolean=? (car b*) b1) - (f (cdr b*))))))])) - -(define symbol=? - (case-lambda - [(s1 s2) - (unless (symbol? s1) ($oops 'symbol=? "~s is not a symbol" s1)) - (unless (symbol? s2) ($oops 'symbol=? "~s is not a symbol" s2)) - (#3%symbol=? s1 s2)] - [(s1 s2 . s*) - (unless (symbol? s1) ($oops 'symbol=? "~s is not a symbol" s1)) - (unless (symbol? s2) ($oops 'symbol=? "~s is not a symbol" s2)) - (for-each - (lambda (s) (unless (symbol? s) ($oops 'symbol=? "~s is not a symbol" s))) - s*) - (and (#3%symbol=? s1 s2) - (let f ([s* s*]) - (or (null? s*) - (and (#3%symbol=? (car s*) s1) - (f (cdr s*))))))])) -) diff --git a/ta6ob/s/5_1.ta6ob b/ta6ob/s/5_1.ta6ob deleted file mode 100644 index 21d1d33..0000000 Binary files a/ta6ob/s/5_1.ta6ob and /dev/null differ diff --git a/ta6ob/s/5_2.ss b/ta6ob/s/5_2.ss deleted file mode 100644 index f639471..0000000 --- a/ta6ob/s/5_2.ss +++ /dev/null @@ -1,795 +0,0 @@ -;;; 5_2.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; list and pair functions - -(begin -(define atom? - (lambda (x) - (not (pair? x)))) - -(define list? - (lambda (x) - (let loop ([hare x] [tortoise x]) - (if (pair? hare) - (let ([hare (cdr hare)]) - (if (pair? hare) - (and (not (eq? hare tortoise)) - (loop (cdr hare) (cdr tortoise))) - (null? hare))) - (null? hare))))) - -(define null? - (lambda (x) - (eq? x '()))) - -(define caar (lambda (x) (#2%caar x))) -(define cadr (lambda (x) (#2%cadr x))) -(define cdar (lambda (x) (#2%cdar x))) -(define cddr (lambda (x) (#2%cddr x))) -(define caaar (lambda (x) (#2%caaar x))) -(define caadr (lambda (x) (#2%caadr x))) -(define cadar (lambda (x) (#2%cadar x))) -(define caddr (lambda (x) (#2%caddr x))) -(define cdaar (lambda (x) (#2%cdaar x))) -(define cdadr (lambda (x) (#2%cdadr x))) -(define cddar (lambda (x) (#2%cddar x))) -(define cdddr (lambda (x) (#2%cdddr x))) -(define caaaar (lambda (x) (#2%caaaar x))) -(define caaadr (lambda (x) (#2%caaadr x))) -(define caadar (lambda (x) (#2%caadar x))) -(define caaddr (lambda (x) (#2%caaddr x))) -(define cadaar (lambda (x) (#2%cadaar x))) -(define cadadr (lambda (x) (#2%cadadr x))) -(define caddar (lambda (x) (#2%caddar x))) -(define cadddr (lambda (x) (#2%cadddr x))) -(define cdaaar (lambda (x) (#2%cdaaar x))) -(define cdaadr (lambda (x) (#2%cdaadr x))) -(define cdadar (lambda (x) (#2%cdadar x))) -(define cdaddr (lambda (x) (#2%cdaddr x))) -(define cddaar (lambda (x) (#2%cddaar x))) -(define cddadr (lambda (x) (#2%cddadr x))) -(define cdddar (lambda (x) (#2%cdddar x))) -(define cddddr (lambda (x) (#2%cddddr x))) - -(define $list-length) -(define length) -(define list-ref) -(define list-tail) -(define list-head) - -(let () - (define improper-list-error - (lambda (who ls) - ($oops who "~s is not a proper list" ls))) - (define circular-list-error - (lambda (who ls) - ($oops who "~s is circular" ls))) - (define index-range-error - (lambda (who ls n) - ($oops who "index ~s is out of range for list ~s" n ls))) - (define index-type-error - (lambda (who n) - ($oops who "index ~s is not an exact nonnegative integer" n))) - (define index-range/improper-list-error - (lambda (who tail ls n) - (if (null? tail) - (index-range-error who ls n) - (improper-list-error who ls)))) - (define list-length - (lambda (ls who) - (let loop ([hare ls] [i 0]) - (if (pair? hare) - (let ([hare (cdr hare)]) - (if (pair? hare) - (if (fx<= i 10000) - (loop (cdr hare) (fx+ i 2)) - (let loop ([hare hare] [tortoise hare] [i (fx+ i 1)]) - (if (pair? hare) - (let ([hare (cdr hare)]) - (if (pair? hare) - (if (eq? hare tortoise) - (circular-list-error who ls) - (loop (cdr hare) - (cdr tortoise) - (fx+ i 2))) - (if (null? hare) - (fx+ i 1) - (improper-list-error who ls)))) - (if (null? hare) - i - (improper-list-error who ls))))) - (if (null? hare) - (fx+ i 1) - (improper-list-error who ls)))) - (if (null? hare) - i - (improper-list-error who ls)))))) - (define list-tail-cycle - (lambda (ls n) - (let loop ((fast (cdr ls)) (i 1)) - (if (eq? fast ls) - (let ((i (remainder n i))) - (do ((ls ls (cdr ls)) (i i (fx- i 1))) - ((fx= i 0) ls))) - (loop (cdr fast) (fx+ i 1)))))) - (define fx-list-tail - (lambda (fast slow i) - (if (fx> i 0) - (if (pair? fast) - (let ((fast (cdr fast))) - (if (fx> i 1) - (if (not (eq? fast slow)) - (if (pair? fast) - (fx-list-tail (cdr fast) (cdr slow) (fx- i 2)) - (values 'error fast i)) - (values 'cycle fast (fx- i 1))) - (values 'okay fast (fx- i 1)))) - (values 'error fast i)) - (values 'okay fast i)))) - (set! $list-length (lambda (ls who) (list-length ls who))) - (set! length - (lambda (ls) - (list-length ls 'length))) - (set! list-ref - (lambda (ls n) - (cond - [(and (fixnum? n) (fx<= 0 n 1000)) - (let loop ([l ls] [i n]) - (if (pair? l) - (if (fx> i 1) - (let ([l (cdr l)]) - (if (pair? l) - (loop (cdr l) (fx- i 2)) - (index-range/improper-list-error 'list-ref l ls n))) - (if (fx= i 0) - (car l) - (let ([l (cdr l)]) - (if (pair? l) - (car l) - (index-range/improper-list-error 'list-ref l ls n))))) - (index-range/improper-list-error 'list-ref l ls n)))] - [(and (or (fixnum? n) (bignum? n)) (>= n 0)) - (let ((m (min n (most-positive-fixnum)))) - (call-with-values - (lambda () (fx-list-tail ls ls m)) - (lambda (what fast i) - (cond - [(and (eq? what 'okay) (pair? fast)) - ; can't happen with bignum input - (car fast)] - [(eq? what 'cycle) - (car (list-tail-cycle fast (+ i (- n m))))] - [else (index-range/improper-list-error 'list-ref fast ls n)]))))] - [else (index-type-error 'list-ref n)]))) - (set! list-tail - (lambda (ls n) - (cond - [(and (fixnum? n) (fx<= 0 n 1000)) - (let loop ([l ls] [i n]) - (if (fx> i 1) - (if (pair? l) - (let ([l (cdr l)]) - (if (pair? l) - (loop (cdr l) (fx- i 2)) - (index-range/improper-list-error 'list-tail l ls n))) - (index-range/improper-list-error 'list-tail l ls n)) - (if (fx= i 0) - l - (if (pair? l) - (cdr l) - (index-range/improper-list-error 'list-tail l ls n)))))] - [(and (or (fixnum? n) (bignum? n)) (>= n 0)) - (let ((m (min n (most-positive-fixnum)))) - (call-with-values - (lambda () (fx-list-tail ls ls m)) - (lambda (what fast i) - (cond - [(eq? what 'okay) ; can't happen with bignum input - fast] - [(eq? what 'cycle) (list-tail-cycle fast (+ i (- n m)))] - [else (index-range/improper-list-error 'list-tail fast ls n)]))))] - [else (index-type-error 'list-tail n)]))) - (set! list-head - (lambda (orig-ls orig-n) - (unless (and (fixnum? orig-n) (fx>= orig-n 0)) - ($oops 'list-head "invalid index ~s" orig-n)) - (let f ([ls orig-ls] [n orig-n]) - (cond - [(fx<= n 1) - (if (fx= n 0) - '() - (if (pair? ls) - (list (car ls)) - (index-range/improper-list-error 'list-head ls orig-ls orig-n)))] - [(pair? ls) - (let ([a (car ls)] [ls (cdr ls)]) - (if (pair? ls) - (list* a (car ls) (f (cdr ls) (fx- n 2))) - (index-range/improper-list-error 'list-head ls orig-ls orig-n)))] - [else (index-range/improper-list-error 'list-head ls orig-ls orig-n)])))) - (set! last-pair - (lambda (ls) - (unless (pair? ls) - ($oops 'last-pair "~s is not a pair" ls)) - (let loop ((fast ls) (slow ls)) - (let ((fast1 (cdr fast))) - (if (pair? fast1) - (let ((fast2 (cdr fast1))) - (if (pair? fast2) - (if (not (eq? fast1 slow)) - (loop fast2 (cdr slow)) - (circular-list-error 'last-pair ls)) - fast1)) - fast)))))) - -(define make-list - (rec make-list - (case-lambda - [(n) (make-list n (void))] - [(n x) - (unless (and (fixnum? n) (fx>= n 0)) - ($oops 'make-list "invalid size ~s" n)) - (let loop ([n n] [ls '()]) - (if (fx= n 0) ls (loop (fx- n 1) (cons x ls))))]))) - -(define-who list-copy - (lambda (ls) - ($list-length ls who) - (let f ([ls ls]) - (if (null? ls) - ls - (cons (car ls) (f (cdr ls))))))) - -(define-who append - (rec append - (case-lambda - [() '()] - [(x1 x2) - ($list-length x1 who) - (let f ([ls x1]) - (if (null? ls) x2 (cons (car ls) (f (cdr ls)))))] - [(x1 . xr) - (let f ([x1 x1] [xr xr]) - (if (null? xr) x1 (append x1 (f (car xr) (cdr xr)))))]))) - -(define-who append! - (let () - (define (do-append! x1 x2) - (if (null? x1) - x2 - (let f ([ls x1]) - (if (null? (cdr ls)) - (begin (set-cdr! ls x2) x1) - (f (cdr ls)))))) - (case-lambda - [() '()] - [(x1 x2) - ($list-length x1 who) - (do-append! x1 x2)] - [(x1 . xr) - (let f ([x1 x1] [xr xr]) - (if (null? xr) - x1 - (begin - ($list-length x1 who) ; make sure all checks occur before first set-cdr! - (do-append! x1 (f (car xr) (cdr xr))))))]))) - -(define-who reverse - (lambda (ls) - ($list-length ls who) - (do ([ls ls (cdr ls)] [a '() (cons (car ls) a)]) - ((null? ls) a)))) - -(define-who reverse! - (lambda (ls) - (#%$list-length ls who) - (let loop ([l ls] [a '()]) - (cond - [(pair? l) (let ([x (cdr l)]) (set-cdr! l a) (loop x l))] - [(null? l) a] - [else - (let loop ([l a] [a l]) - (let ([x (cdr l)]) (set-cdr! l a) (loop x l)))])))) - -(let () -(define-syntax do-assoc - (syntax-rules () - ((_ x alist who pred?) - (let loop ((fast alist) (slow alist)) - (cond - [(pair? fast) - (let ((a (car fast))) - (if (pair? a) - (if (pred? (car a) x) - a - (let ((fast (cdr fast))) - (cond - [(pair? fast) - (let ((a (car fast))) - (if (pair? a) - (if (pred? (car a) x) - a - (if (eq? fast slow) - (cyclic-alist who alist) - (loop (cdr fast) (cdr slow)))) - (improper-alist who alist)))] - [(null? fast) #f] - [else (improper-alist who alist)]))) - (improper-alist who alist)))] - [(null? fast) #f] - [else (improper-alist who alist)]))))) - -(define improper-alist - (lambda (who alist) - ($oops who "improperly formed alist ~s" alist))) - -(define cyclic-alist - (lambda (who alist) - ($oops who "cyclic alist ~s" alist))) - -(define ass-eq? - (lambda (x alist who) - (do-assoc x alist who eq?))) - -(set! assq - (lambda (x alist) - (ass-eq? x alist 'assq))) - -(set! assv - (lambda (x alist) - (if (or (symbol? x) (#%$immediate? x)) - (ass-eq? x alist 'assv) - (do-assoc x alist 'assv eqv?)))) - -(set! assoc - (lambda (x alist) - (cond - [(string? x) - (do-assoc x alist 'assoc - (lambda (x y) (and (string? x) (string=? x y))))] - [(or (symbol? x) (#%$immediate? x)) - (ass-eq? x alist 'assoc)] - [else - (do-assoc x alist 'assoc equal?)]))) - -(set! assp - (lambda (pred? alist) - (unless (procedure? pred?) - ($oops 'assp "~s is not a procedure" pred?)) - (let loop ((fast alist) (slow alist)) - (cond - [(pair? fast) - (let ((a (car fast))) - (if (pair? a) - (if (pred? (car a)) - a - (let ((fast (cdr fast))) - (cond - [(pair? fast) - (let ((a (car fast))) - (if (pair? a) - (if (pred? (car a)) - a - (if (eq? fast slow) - (cyclic-alist 'assp alist) - (loop (cdr fast) (cdr slow)))) - (improper-alist 'assp alist)))] - [(null? fast) #f] - [else (improper-alist 'assp alist)]))) - (improper-alist 'assp alist)))] - [(null? fast) #f] - [else (improper-alist 'assp alist)])))) -) - -(let () -(define improper-list - (lambda (who ls) - ($oops who "improper list ~s" ls))) - -(define cyclic-list - (lambda (who ls) - ($oops who "cyclic list ~s" ls))) - -(define-syntax do-member - (syntax-rules () - ((_ x ls who pred?) - (let loop ((fast ls) (slow ls)) - (cond - [(pair? fast) - (if (pred? (car fast) x) - fast - (let ((fast (cdr fast))) - (cond - [(pair? fast) - (if (pred? (car fast) x) - fast - (if (eq? fast slow) - (cyclic-list who ls) - (loop (cdr fast) (cdr slow))))] - [(null? fast) #f] - [else (improper-list who ls)])))] - [(null? fast) #f] - [else (improper-list who ls)]))))) - -(define mem-eq? - (lambda (x ls who) - (do-member x ls who eq?))) - -(set! memq - (lambda (x ls) - (mem-eq? x ls 'memq))) - -(set! memv - (lambda (x ls) - (if (or (symbol? x) (fixnum? x) (char? x) (procedure? x)) - (mem-eq? x ls 'memv) - (do-member x ls 'memv eqv?)))) - -(set! member - (lambda (x ls) - (cond - [(string? x) - (do-member x ls 'member - (lambda (x y) (and (string? x) (string=? x y))))] - [(or (symbol? x) (fixnum? x) (char? x) (procedure? x)) - (mem-eq? x ls 'member)] - [else - (do-member x ls 'member equal?)]))) - -(set! memp - (lambda (pred? ls) - (unless (procedure? pred?) - ($oops 'memp "~s is not a procedure" pred?)) - (let loop ((fast ls) (slow ls)) - (cond - [(pair? fast) - (if (pred? (car fast)) - fast - (let ((fast (cdr fast))) - (cond - [(pair? fast) - (if (pred? (car fast)) - fast - (if (eq? fast slow) - (cyclic-list 'memp ls) - (loop (cdr fast) (cdr slow))))] - [(null? fast) #f] - [else (improper-list 'memp ls)])))] - [(null? fast) #f] - [else (improper-list 'memp ls)])))) - -(set! find - (lambda (pred? ls) - (unless (procedure? pred?) - ($oops 'find "~s is not a procedure" pred?)) - (let loop ((fast ls) (slow ls)) - (cond - [(pair? fast) - (if (pred? (car fast)) - (car fast) - (let ((fast (cdr fast))) - (cond - [(pair? fast) - (if (pred? (car fast)) - (car fast) - (if (eq? fast slow) - (cyclic-list 'find ls) - (loop (cdr fast) (cdr slow))))] - [(null? fast) #f] - [else (improper-list 'find ls)])))] - [(null? fast) #f] - [else (improper-list 'find ls)])))) -) - -(let () -(define improper-list - (lambda (who ls) - ($oops who "~s is not a proper list" ls))) - -(define-syntax do-remove - (syntax-rules () - ((_ x ls pred?) - (let f ((x x) (fast ls) (slow ls)) - (if (pair? fast) - (let ((fast1 (cdr fast))) - (if (pair? fast1) - (and (not (eq? fast1 slow)) - (let ((fast2 (cdr fast1))) - (let ((rest (f x fast2 (cdr slow)))) - (and rest - (if (not (pred? (car fast) x)) - (if (not (pred? (car fast1) x)) - (if (eq? rest fast2) - fast - (list* (car fast) (car fast1) rest)) - (cons (car fast) rest)) - (if (not (pred? (car fast1) x)) - (if (eq? rest fast2) - fast1 - (cons (car fast1) rest)) - rest)))))) - (and (null? fast1) - (if (not (pred? (car fast) x)) - fast - '())))) - (and (null? fast) '())))))) - -(define rem-eq? - (lambda (x l) - (do-remove x l eq?))) - -(set! remq - (lambda (x ls) - (or (rem-eq? x ls) - (improper-list 'remq ls)))) - -(set! remv - (lambda (x ls) - (or (if (or (symbol? x) (fixnum? x) (char? x) (procedure? x)) - (rem-eq? x ls) - (do-remove x ls eqv?)) - (improper-list 'remv ls)))) - -(set! remove - (lambda (x ls) - (or (cond - [(string? x) - (do-remove x ls - (lambda (x y) (and (string? x) (string=? x y))))] - [(or (symbol? x) (fixnum? x) (char? x) (procedure? x)) - (rem-eq? x ls)] - [else - (do-remove x ls equal?)]) - (improper-list 'remove ls)))) - -(set! remp - (lambda (pred? ls) - (unless (procedure? pred?) - ($oops 'remp "~s is not a procedure" pred?)) - (or (let f ((pred? pred?) (fast ls) (slow ls)) - (if (pair? fast) - (let ((fast1 (cdr fast))) - (if (pair? fast1) - (and (not (eq? fast1 slow)) - (let ((fast2 (cdr fast1))) - (let ((rest (f pred? fast2 (cdr slow)))) - (and rest - (if (not (pred? (car fast))) - (if (not (pred? (car fast1))) - (if (eq? rest fast2) - fast - (list* (car fast) (car fast1) rest)) - (cons (car fast) rest)) - (if (not (pred? (car fast1))) - (if (eq? rest fast2) - fast1 - (cons (car fast1) rest)) - rest)))))) - (and (null? fast1) - (if (not (pred? (car fast))) - fast - '())))) - (and (null? fast) '()))) - (improper-list 'remp ls)))) - - -(set! filter - (lambda (pred? ls) - (unless (procedure? pred?) - ($oops 'filter "~s is not a procedure" pred?)) - (or (let f ((pred? pred?) (fast ls) (slow ls)) - (if (pair? fast) - (let ((fast1 (cdr fast))) - (if (pair? fast1) - (and (not (eq? fast1 slow)) - (let ((fast2 (cdr fast1))) - (let ((rest (f pred? fast2 (cdr slow)))) - (and rest - (if (pred? (car fast)) - (if (pred? (car fast1)) - (if (eq? rest fast2) - fast - (list* (car fast) (car fast1) rest)) - (cons (car fast) rest)) - (if (pred? (car fast1)) - (if (eq? rest fast2) - fast1 - (cons (car fast1) rest)) - rest)))))) - (and (null? fast1) - (if (pred? (car fast)) - fast - '())))) - (and (null? fast) '()))) - (improper-list 'filter ls)))) - -(set! partition - (lambda (pred? ls) - (unless (procedure? pred?) - ($oops 'partition "~s is not a procedure" pred?)) - (let f ([pred? pred?] [fast ls] [slow ls] [ls ls]) - (if (pair? fast) - (let ([fast1 (cdr fast)]) - (if (pair? fast1) - (if (eq? fast1 slow) - (improper-list 'partition ls) - (let ([fast2 (cdr fast1)]) - (let-values ([(ins outs) (f pred? fast2 (cdr slow) ls)]) - (if (pred? (car fast)) - (if (pred? (car fast1)) - (values - (if (eq? ins fast2) - fast - (list* (car fast) (car fast1) ins)) - outs) - (values - (cons (car fast) ins) - (if (eq? outs fast2) - fast1 - (cons (car fast1) outs)))) - (if (pred? (car fast1)) - (values - (if (eq? ins fast2) - fast1 - (cons (car fast1) ins)) - (cons (car fast) outs)) - (values - ins - (if (eq? outs fast2) - fast - (list* (car fast) (car fast1) outs)))))))) - (if (null? fast1) - (if (pred? (car fast)) - (values fast '()) - (values '() fast)) - (improper-list 'partition ls)))) - (if (null? fast) - (values '() '()) - (improper-list 'partition ls)))))) -) - -(let () -(define-syntax do-rem! - (syntax-rules () - ((_ pred?) - (rec rem! - (lambda (x ls) - (if (not (null? ls)) - (if (not (pred? (car ls) x)) - (begin - (let loop ((ls (cdr ls)) (prev ls)) - (unless (null? ls) - (if (not (pred? (car ls) x)) - (loop (cdr ls) ls) - (set-cdr! prev (rem! x (cdr ls)))))) - ls) - (rem! x (cdr ls))) - '())))))) - -(define rem-eq?! (do-rem! eq?)) - -(set! remq! - (lambda (x ls) - ($list-length ls 'remq!) - (rem-eq?! x ls))) - -(set! remv! - (lambda (x ls) - ($list-length ls 'remv!) - (if (or (symbol? x) (fixnum? x) (char? x) (procedure? x)) - (rem-eq?! x ls) - ((do-rem! eqv?) x ls)))) - -(set! remove! - (lambda (x ls) - ($list-length ls 'remove!) - (if (or (symbol? x) (fixnum? x) (char? x) (procedure? x)) - (rem-eq?! x ls) - ((do-rem! equal?) x ls)))) -) - -(define substq - (lambda (new old tree) - (let f ([tree tree]) - (if (eq? old tree) - new - (if (pair? tree) - (let ([a (f (car tree))] [d (f (cdr tree))]) - (if (and (eq? a (car tree)) (eq? d (cdr tree))) - tree - (cons a d))) - tree))))) - -(define substq! - (lambda (new old tree) - (let f ([tree tree]) - (if (eq? old tree) - new - (if (pair? tree) - (begin - (set-car! tree (f (car tree))) - (set-cdr! tree (f (cdr tree))) - tree) - tree))))) - -(define substv - (lambda (new old tree) - (let f ([tree tree]) - (if (eqv? old tree) - new - (if (pair? tree) - (let ([a (f (car tree))] [d (f (cdr tree))]) - (if (and (eq? a (car tree)) (eq? d (cdr tree))) - tree - (cons a d))) - tree))))) - -(define substv! - (lambda (new old tree) - (let f ([tree tree]) - (if (eqv? old tree) - new - (if (pair? tree) - (begin - (set-car! tree (f (car tree))) - (set-cdr! tree (f (cdr tree))) - tree) - tree))))) - -(define subst - (lambda (new old tree) - (let f ([tree tree]) - (if (equal? old tree) - new - (if (pair? tree) - (let ([a (f (car tree))] [d (f (cdr tree))]) - (if (and (eq? a (car tree)) (eq? d (cdr tree))) - tree - (cons a d))) - tree))))) - -(define subst! - (lambda (new old tree) - (let f ([tree tree]) - (if (equal? old tree) - new - (if (pair? tree) - (begin - (set-car! tree (f (car tree))) - (set-cdr! tree (f (cdr tree))) - tree) - tree))))) - -(let () - (define ($iota n ls) - (if (fx> n 0) - ($iota (fx- n 2) (list* (fx- n 1) n ls)) - (if (fx= n 0) - (cons 0 ls) - ls))) - - ; (iota n) => (0 1 ... n-1) - (set! iota - (lambda (n) - (unless (and (fixnum? n) (fx>= n 0)) - ($oops 'iota "~s is not a nonnegative fixnum" n)) - ($iota (fx- n 1) '()))) - - ; (enumerate '(a1 a2 ... aN)) => (0 1 ... n-1) - (set! enumerate - (lambda (ls) - ($iota (fx- ($list-length ls 'enumerate) 1) '())))) -) diff --git a/ta6ob/s/5_2.ta6ob b/ta6ob/s/5_2.ta6ob deleted file mode 100644 index 07405eb..0000000 Binary files a/ta6ob/s/5_2.ta6ob and /dev/null differ diff --git a/ta6ob/s/5_3.ss b/ta6ob/s/5_3.ss deleted file mode 100644 index 6759e1c..0000000 --- a/ta6ob/s/5_3.ss +++ /dev/null @@ -1,3093 +0,0 @@ -;;; 5_3.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; Care must be take with floating point constants to permit cross -;;; compilation between machines with differing floating point styles. -;;; Negative zero, infinities, large or small numbers, non-binary -;;; fractions, and precise numbers are dangerous and should be calculated. -;;; positive zero, NAN, small integers, and binary fractions with only a few -;;; significant bits are safe on all current machines. -;;; examples: -;;; dangerous: -0.0, +inf.0, -inf.0, 1e100, 1e-100, 0.1 -;;; safe: 0.0, +nan.0, 1.0, 2.0, 0.5 - -(begin -(eval-when (compile) - - (define-constant max-float-exponent - (float-type-case - [(ieee) 1023])) - - (define-constant min-float-exponent - (float-type-case - [(ieee) -1023])) - - (define-constant float-mantissa-bits - (float-type-case - [(ieee) 53])) - -) - -(let () -; could use foreign-entry? primitive if foreign.ss were loaded first -(define op-if-entry? - (let () - (define lookup - (foreign-procedure "(cs)lookup_foreign_entry" (string) - void*)) - (lambda (op name) - (and (not (eqv? (lookup name) 0)) - (op name))))) - -(let () - -(define cflop1 - (lambda (x) - (foreign-procedure x (double-float) double-float))) - -(define cflop2 - (lambda (x) - (foreign-procedure x (double-float double-float) double-float))) - -(define schemeop1 - (lambda (x) - (foreign-procedure x (scheme-object) scheme-object))) - -(define schemeop2 - (lambda (x) - (foreign-procedure x (scheme-object scheme-object) scheme-object))) - -(let () - -(define biglength (schemeop1 "(cs)s_integer_length")) -(define bigodd? (schemeop1 "(cs)s_bigoddp")) -(define float (schemeop1 "(cs)s_float")) - -(define big= - (foreign-procedure "(cs)s_big_eq" (scheme-object scheme-object) - boolean)) -(define big< - (foreign-procedure "(cs)s_big_lt" (scheme-object scheme-object) - boolean)) -(define big-negate (schemeop1 "(cs)s_big_negate")) -(define integer-ash (schemeop2 "(cs)s_ash")) -(define integer+ (schemeop2 "(cs)add")) -(define integer* (schemeop2 "(cs)mul")) -(define integer- (schemeop2 "(cs)sub")) -(define integer/ (schemeop2 "(cs)s_div")) -(define intquotient (schemeop2 "(cs)ss_trunc")) -(define intquotient-remainder (schemeop2 "(cs)ss_trunc_rem")) -(define intremainder (schemeop2 "(cs)rem")) - -(define $flsin (cflop1 "(cs)sin")) - -(define $flcos (cflop1 "(cs)cos")) - -(define $flasin (cflop1 "(cs)asin")) - -(define $flacos (cflop1 "(cs)acos")) -(define $flfloor (cflop1 "(cs)floor")) -(define $flceiling (cflop1 "(cs)ceil")) - -(let () - -(define omega - (float-type-case - [(ieee) (float #e1.7976931348623157e308)])) - -(define $flexpt - (machine-case - [(i3nt ti3nt a6s2 ta6s2 i3s2 ti3s2 i3nb ti3nb a6nb ta6nb) - ; pow(nan,+0.0) => nan instead of +1.0 - (let ([cexpt (cflop2 "(cs)pow")]) - (lambda (x y) - (cond - [(fl= y 0.0) 1.0] - [else (cexpt x y)])))] - [else (cflop2 "(cs)pow")])) - -(define $fltan (cflop1 "(cs)tan")) - -(define flcosh (cflop1 "(cs)cosh")) - -(define fltanh - (machine-case - [(i3fb ti3fb) - ; broken for -0.0, +/-inf - (let ([ctanh (cflop1 "(cs)tanh")]) - (lambda (x) - (cond - [(fl= x 0.0) x] - [(infinity? x) (if (negated-flonum? x) -1.0 1.0)] - [else (ctanh x)])))] - [(i3nb ti3nb a6nb ta6nb) - ; broken for -0.0 - (let ([ctanh (cflop1 "(cs)tanh")]) - (lambda (x) - (cond - [(fl= x 0.0) x] - [else (ctanh x)])))] - [else (cflop1 "(cs)tanh")])) - -(define $flexp (cflop1 "(cs)exp")) - -(define $fllog - (machine-case - [(a6s2 ta6s2 i3s2 ti3s2 i3ob ti3ob i3nb ti3nb a6nb ta6nb a6ob ta6ob) - ; broken for -inf.0 - (let ([clog (cflop1 "(cs)log")]) - (lambda (x) (if (and (infinity? x) (negated-flonum? x)) +nan.0 (clog x))))] - [else (cflop1 "(cs)log")])) - -(define $flsqrt (cflop1 "(cs)sqrt")) - -(define flatan2 - (machine-case - [(i3nt ti3nt) - ; atan2(+inf.0,+inf.0) => pi/2 instead of pi/4 - ; atan2(-inf.0,-inf.0) => -pi/2 instead of -3pi/4 - ; atan2(+inf.0,-inf.0) => NAN instead of 3pi/4 - ; atan2(-inf.0,+inf.0) => NAN instead of -pi/4 - ; atan2(+0.0,-0.0) => +0.0 instead of +pi - ; atan2(-0.0,-0.0) => -0.0 instead of -pi - ; atan2(-0.0,-1.0) => pi instead of -pi - (let ([catan2 (cflop2 "(cs)atan2")]) - (let ([pi (catan2 0.0 -1.0)]) - (lambda (y x) - (cond - [(and (infinity? y) (infinity? x)) - (let ([y (if (negated-flonum? y) -1.0 1.0)] - [x (if (negated-flonum? x) -1.0 1.0)]) - (catan2 y x))] - [(and (fl= y 0.0) (not ($nan? x))) - (if (negated-flonum? y) - (if (negated-flonum? x) (fl- pi) (fl- 0.0)) - (if (negated-flonum? x) pi 0.0))] - [else (catan2 y x)]))))] - [(i3ob ti3ob a6ob ta6ob a6s2 ta6s2 i3s2 ti3s2 i3nb ti3nb a6nb ta6nb) - ; atan2(-0.0,+0.0) => +0.0 instead of -0.0 - ; atan2(+0.0,-0.0) => +0.0 instead of +pi - ; atan2(-0.0,-0.0) => +0.0 instead of -pi - (let ([catan2 (cflop2 "(cs)atan2")]) - (let ([pi (catan2 0.0 -1.0)]) - (lambda (y x) - (cond - [(and (fl= y 0.0) (not ($nan? x))) - (if (negated-flonum? y) - (if (negated-flonum? x) (fl- pi) (fl- 0.0)) - (if (negated-flonum? x) pi 0.0))] - [else (catan2 y x)]))))] - [else (cflop2 "(cs)atan2")])) - -(define $flatan (cflop1 "(cs)atan")) - -(define flsinh (cflop1 "(cs)sinh")) - -(define flatanh - (or (op-if-entry? cflop1 "(cs)atanh") - ; |x| <= 1 - ; principal expression: - ; (log(1+x)-log(1-x))/2 - ; should use "log1p" but it doesn't exist on the 88k - (let ([f (lambda (x) - (fl* 0.5 (fl- ($fllog (fl+ 1.0 x)) ($fllog (fl- 1.0 x)))))]) - (lambda (x) - (if (negated-flonum? x) (fl- (f (fl- x))) (f x)))))) - -(define fllog1+ - (or (op-if-entry? cflop1 "(cs)log1p") - (lambda (x) ($fllog (fl+ 1.0 x))))) - -(let () - -(define log2 ($fllog 2.0)) - -(define flhypot (cflop2 "(cs)hypot")) - -(define flasinh - ; scheme-coded version needs "log2" - (or (op-if-entry? cflop1 "(cs)asinh") - ; principal expression: - ; log(x + sqrt(xx + 1)) - ; avoids spurious overflows - ; avoids underflow problems from negative x by using identity - ; asinh(-x) = -asinh(x) - ; should use "log1p" for small x but it doesn't exist on the 88k - (let ([f (lambda (x) - (if (fl= (fl+ x 1.0) x) - (fl+ ($fllog x) log2) - ($fllog (fl+ x ($flsqrt (fl+ (fl* x x) 1.0))))))]) - (lambda (x) - (if (negated-flonum? x) (fl- (f (fl- x))) (f x)))))) - -(define flacosh - ; scheme-coded version needs "log2" - (or (op-if-entry? cflop1 "(cs)acosh") - ; x >= 1 - ; principal expression: - ; log(x + sqrt(xx - 1)) - ; avoids spurious overflows - (lambda (x) - (if (fl= (fl- x 1.0) x) - (fl+ ($fllog x) log2) - ($fllog (fl+ x ($flsqrt (fl- (fl* x x) 1.0)))))))) - -(let () - -(define pi (flatan2 0.0 -1.0)) -(define sqrt-omega ($flsqrt omega)) -(define log-omega ($fllog omega)) -(define acosh-omega (flacosh omega)) - -(let () - -(define-syntax define-trig-op - (syntax-rules () - [(_ who flop cflop zero-value) - (set! who - (lambda (x) - (type-case x - [(flonum?) (flop x)] - [($inexactnum?) (cflop x)] - [(fixnum?) (if (fx= x 0) zero-value (who (fixnum->flonum x)))] - [(bignum? ratnum? $exactnum?) (who (inexact x))] - [else (nonnumber-error 'who x)])))])) - -(define $flinteger-or-inf? - (lambda (x) - (fl= ($flfloor x) x))) - -(define $flinteger? - (lambda (x) - (and ($flinteger-or-inf? x) - (not (exceptional-flonum? x))))) - -(define nonnumber-error - (lambda (who what) - ($oops who "~s is not a number" what))) - -(define noncomplex-error - (lambda (who what) - ($oops who "~s is not a complex number" what))) - -(define nonreal-error - (lambda (who what) - ($oops who "~s is not a real number" what))) - -(define nonrational-error - (lambda (who what) - ($oops who "~s is not a rational number" what))) - -(define noninteger-error - (lambda (who what) - ($oops who "~s is not an integer" what))) - -(define nonexact-integer-error - (lambda (who what) - ($oops who "~s is not an exact integer" what))) - -(define noncflonum-error - (lambda (who what) - ($oops who "~s is not a cflonum" what))) - -(define domain-error - (lambda (who what) - ($oops who "undefined for ~s" what))) - -(define domain-error2 - (lambda (who x y) - ($oops who "undefined for values ~s and ~s" x y))) - -; note: (cfl*i z) =/= (* +i z) if RP(z) == -0.0 -(define cfl*i - (lambda (z) - (fl-make-rectangular (fl- (cfl-imag-part z)) (cfl-real-part z)))) - -; note: (cfl/i z) =/= (/ z +i) or (* -i z) if IP(z) == -0.0 -(define cfl/i - (lambda (z) - (fl-make-rectangular (cfl-imag-part z) (fl- (cfl-real-part z))))) - -; Some of the following is based on -; W. Kahan's "Branch Cuts for Complex Elementary Functions" -; in "The State of the Art of Numerical Analysis" -; (IMA/SIAM proceedings, 1986, pp 165-211) -; ed. by A. Iserles and M.J.D. Powell - -; Kahan gives principal expressions and algorithms for several -; complex functions. The principal expressions are mathematically -; correct, but not necessarily good computationally. They -; do, however, make good test expressions for ordinary inputs. - -; Steele's "Common Lisp: the Language" (second edition) was used -; to determine valid domains for some of the functions. - -(define cflmagnitude - (lambda (z) - (flhypot (cfl-real-part z) (cfl-imag-part z)))) - -(define cflangle - (lambda (z) - (flatan2 (cfl-imag-part z) (cfl-real-part z)))) - -(define cfllog - ; principal expression from Kahan: - ; log(z) = log(|z|) + angle(z)i - ; Kahan uses a different algorithm to calculate the real part. - (let ([f (lambda (x y) - ; x >= y - (let ([r (fl/ y x)]) - (fl+ ($fllog x) (fl* .5 (fllog1+ (fl* r r))))))] - [k (fl* .5 log2)]) - (lambda (z) - (let ([x (cfl-real-part z)] [y (cfl-imag-part z)]) - (fl-make-rectangular - (let ([x (flabs x)] [y (flabs y)]) - (cond - [(fl> x y) (f x y)] - [(fl< x y) (f y x)] - [(fl= x y) (fl+ ($fllog x) k)] - [(infinity? x) x] - [(infinity? y) y] - [($nan? x) x] - [else y])) - (flatan2 y x)))))) - -(define cflsqrt - ; principal expression from Kahan: - ; sqrt(z) = expt(z,1/2) - ; Kahan's algorithm except for the calculation of "a" - (let ([f (let ([k ($flsqrt (fl* .5 (fl+ ($flsqrt 2.0) 1.0)))]) - (lambda (x y) - ; sqrt(|x+yi| + |x|)/2 - (cond - [(fl> x y) - (let ([r (fl/ y x)]) - (fl* ($flsqrt x) - ($flsqrt (fl* .5 (fl+ ($flsqrt (fl+ 1.0 (fl* r r))) - 1.0)))))] - [(fl< x y) - (let ([r (fl/ x y)]) - (fl* ($flsqrt y) - ($flsqrt (fl* .5 (fl+ ($flsqrt (fl+ (fl* r r) 1.0)) - r)))))] - [(fl= x y) (fl* ($flsqrt x) k)] - [(infinity? x) x] - [(infinity? y) y] - [($nan? x) x] - [else y])))]) - (lambda (z) - (let ([x (cfl-real-part z)] [y (cfl-imag-part z)]) - (let ([a (f (flabs x) (flabs y))]) - (if (fl= a 0.0) - (fl-make-rectangular a y) - (let ([b (if (infinity? y) y (fl* (fl/ y a) .5))]) - (if (fl< x 0.0) - (fl-make-rectangular - (flabs b) - (if (negated-flonum? y) (fl- a) a)) - (fl-make-rectangular a b))))))))) - -(define cflexp - ; exp(a+bi) = exp(a)cos(b) + exp(a)sin(b)i - (lambda (z) - (let ([a (cfl-real-part z)] [b (cfl-imag-part z)]) - (cond - ; perhaps misguidedly treat x+0.0i the same as x - [(fl= b 0.0) (fl-make-rectangular ($flexp a) b)] - [(fl<= a log-omega) - (let ([e^a ($flexp a)]) - (fl-make-rectangular (fl* e^a ($flcos b)) (fl* e^a ($flsin b))))] - [else (fl-make-rectangular - (let ([cosb ($flcos b)]) - (if (fl< cosb 0.0) - (fl- ($flexp (fl+ a ($fllog (fl- cosb))))) - ($flexp (fl+ a ($fllog cosb))))) - (let ([sinb ($flsin b)]) - (if (fl< sinb 0.0) - (fl- ($flexp (fl+ a ($fllog (fl- sinb))))) - ($flexp (fl+ a ($fllog sinb))))))])))) - -(define cflslowsinh - ; probably not the best way to handle this - (let ([f (lambda (z -z) - (cfl- (cflexp (cfl- z log2)) (cfl* .5 (cflexp -z))))]) - (lambda (z) - (if (fl< (cfl-real-part z) 0.0) - (cfl- (f (cfl- z) z)) - (f z (cfl- z)))))) - -(define cflslowcosh - ; probably not the best way to handle this - (let ([f (lambda (z -z) - (cfl+ (cflexp (cfl- z log2)) (cfl* .5 (cflexp -z))))]) - (lambda (z) - (if (fl< (cfl-real-part z) 0.0) - (f (cfl- z) z) - (f z (cfl- z)))))) - -(define cflsin - ; sin(a+bi) = sin(a)cosh(b)+cos(a)sinh(b)i - (lambda (z) - (let ([a (cfl-real-part z)] [b (cfl-imag-part z)]) - (if (fl<= (flabs b) acosh-omega) - (fl-make-rectangular (fl* ($flsin a) (flcosh b)) - (fl* ($flcos a) (flsinh b))) - (cfl/i (cflslowsinh (cfl*i z))))))) - -(define cflcos - ; cos(a+bi) = cos(a)cosh(b)-sin(a)sinh(b)i - (lambda (z) - (let ([a (cfl-real-part z)] [b (cfl-imag-part z)]) - (if (fl<= (flabs b) acosh-omega) - (fl-make-rectangular (fl* ($flcos a) (flcosh b)) - (fl- (fl* ($flsin a) (flsinh b)))) - (cflslowcosh (cfl*i z)))))) - -(define cfltan - ; from Kahan - (lambda (z) - (cfl/i (cfltanh (cfl*i z))))) - -(define cflacos - ; from Kahan - ; principal expression: - ; 2log(sqrt((1+z)/2) + sqrt((1-z)/2)i)/i = pi/2 - asin(z) - ; returns a+bi where - ; a = 2atan(RP(sqrt(1-z))/RP(sqrt(1+z))) - ; b = asinh(IP(conjugate(sqrt(1+z)))sqrt(1-z)) - (lambda (z) - (let ([z- (cflsqrt (cfl- 1.0 z))] - [z+ (cflsqrt (cfl+ 1.0 z))]) - (let ([a (cfl-real-part z-)] [b (cfl-imag-part z-)] - [c (cfl-real-part z+)] [d (cfl-imag-part z+)]) - (fl-make-rectangular (fl* 2.0 ($flatan (fl/ a c))) - (flasinh (fl- (fl* b c) (fl* a d)))))))) - -(define cflasin - ; from Kahan - ; principal expression: - ; asinh(iz)/i - ; returns a+bi where - ; a = atan(RP(z)/RP(sqrt(1-z)sqrt(1+z))) - ; b = asinh(IP(conjugate(sqrt(1-z))sqrt(1+z))) - (lambda (z) - (let ([z- (cflsqrt (cfl- 1.0 z))] - [z+ (cflsqrt (cfl+ 1.0 z))]) - (let ([a (cfl-real-part z-)] [b (cfl-imag-part z-)] - [c (cfl-real-part z+)] [d (cfl-imag-part z+)]) - (fl-make-rectangular - ($flatan (fl/ (cfl-real-part z) (fl- (fl* a c) (fl* b d)))) - (flasinh (fl- (fl* a d) (fl* b c)))))))) - -(define cflasinh - ; from Kahan - ; principal expression: - ; log(z + sqrt(1 + zz)) - (lambda (z) - (cfl/i (cflasin (cfl*i z))))) - -(define cflsinh - ; sinh(a+bi) = sinh(a)cos(b)+cosh(a)sin(b)i - (lambda (z) - (let ([a (cfl-real-part z)] [b (cfl-imag-part z)]) - (if (fl<= a acosh-omega) - (fl-make-rectangular (fl* (flsinh a) ($flcos b)) - (fl* (flcosh a) ($flsin b))) - (cflslowsinh z))))) - -(define cflcosh - ; cosh(a+bi) = cosh(a)cos(b)+sinh(a)sin(b)i - (lambda (z) - (let ([a (cfl-real-part z)] [b (cfl-imag-part z)]) - (if (fl<= a acosh-omega) - (fl-make-rectangular (fl* (flcosh a) ($flcos b)) - (fl* (flsinh a) ($flsin b))) - (cflslowcosh z))))) - -(define cfltanh - ; from Kahan - (let ([theta (fl/ acosh-omega 4.0)]) - (lambda (z) - (let ([x (cfl-real-part z)] [y (cfl-imag-part z)]) - (let ([ax (flabs x)]) - (if (fl> ax theta) - (fl-make-rectangular - (if (negated-flonum? x) -1.0 1.0) - (if (negated-flonum? y) (fl- 0.0) 0.0)) - (let ([t ($fltan y)] - [s (flsinh x)]) - (let ([beta (fl+ 1.0 (fl* t t))] - [ss (fl* s s)]) - (let ([rho ($flsqrt (fl+ 1.0 ss))]) - (if (infinity? t) - (fl-make-rectangular (fl/ rho s) (/ t)) - (let ([k (/ (fl+ 1.0 (fl* beta ss)))]) - (fl-make-rectangular (fl* beta rho s k) - (fl* t k))))))))))))) - -(define cflacosh - ; from Kahan - ; principal expression: - ; 2log(sqrt((z+1)/2) + sqrt((z-1)/2)) - ; returns a+bi where - ; a = (asinh (real-part (* (conjugate (sqrt (- z 1))) (sqrt (+ z 1))))) - ; b = (* 2 (atan (/ (imag-part (sqrt (- z 1))) (real-part (sqrt (+ z 1)))))) - (lambda (z) - (let ([z- (cflsqrt (cfl- z 1.0))] - [z+ (cflsqrt (cfl+ z 1.0))]) - (let ([a (cfl-real-part z-)] [b (cfl-imag-part z-)] - [c (cfl-real-part z+)] [d (cfl-imag-part z+)]) - (fl-make-rectangular (flasinh (fl+ (fl* a c) (fl* b d))) - (fl* 2.0 ($flatan (fl/ b c)))))))) - -(define cflatanh - ; principal expression from Kahan: - ; (log(1+z) - log(1-z))/2 - (let ([f (let ([theta (fl/ sqrt-omega 4.0)] [pi/2 (flatan2 1.0 0.0)]) - (let ([rho (fl/ theta)] [-pi/2 (fl- pi/2)]) - (lambda (x y) - ; x is positive - (let ([ay (abs y)]) - (cond - [(or (fl> x theta) (fl> ay theta)) - ; RP(1/z) +/- (pi/2)i - (fl-make-rectangular - (cond - [(fl> x ay) (fl/ (fl+ x (fl* (fl/ y x) y)))] - [(fl< x ay) (let ([r (fl/ y x)]) - (fl/ r (fl+ (fl* x r) y)))] - [else (fl/ (fl+ x ay))]) - (if (negated-flonum? y) pi/2 -pi/2))] - [(fl= x 1.0) - (let ([k (fl+ ay rho)]) - (fl-make-rectangular - ($fllog (fl/ ($flsqrt ($flsqrt (fl+ 4.0 - (* y y)))) - ($flsqrt k))) - (fl/ (fl+ pi/2 ($flatan (fl/ k 2.0))) - (if (negated-flonum? y) 2.0 -2.0))))] - [else - (let ([1-x (fl- 1.0 x)] - [k (let ([k (fl+ ay rho)]) (fl* k k))]) - (fl-make-rectangular - (fl/ (fllog1+ (fl/ (fl* 4.0 x) - (fl+ (fl* 1-x 1-x) k))) - 4.0) - (fl/ (flatan2 (fl* 2.0 y) - (fl- (fl* 1-x (fl+ 1.0 x)) k)) - -2.0)))])))))]) - (lambda (z) - (let ([x (cfl-real-part z)] [y (cfl-imag-part z)]) - (if (negated-flonum? x) - (cfl- (f (fl- x) y)) - (f x (fl- y))))))) - -(define cflatan - ; from Kahan - ; principal expression: - ; arctanh(zi)/i - (lambda (z) - (cfl/i (cflatanh (cfl*i z))))) - -(define exact-inexact+ - (lambda (x y) - (cond - [(fixnum? x) (if (fx= x 0) y (fl+ (fixnum->flonum x) y))] - [(or (floatable? x) (fl= y 0.0)) (fl+ (inexact x) y)] - [(exceptional-flonum? y) y] - [else (inexact (+ x (exact y)))]))) - -(define exact-inexact- - (lambda (x y) - (cond - [(fixnum? x) (if (fx= x 0) (fl- y) (fl- (fixnum->flonum x) y))] - [(or (floatable? x) (fl= y 0.0)) (fl- (inexact x) y)] - [(exceptional-flonum? y) (fl- y)] - [else (inexact (- x (exact y)))]))) - -(define inexact-exact- - (lambda (x y) - (cond - [(fixnum? y) (fl- x (fixnum->flonum y))] - [(or (floatable? y) (fl= x 0.0)) (fl- x (inexact y))] - [(exceptional-flonum? x) x] - [else (inexact (- (exact x) y))]))) - -(define exact-inexact* - (lambda (x y) - (cond - [(fixnum? x) (if (fx= x 0) 0 (fl* (fixnum->flonum x) y))] - [(floatable? x) (fl* (inexact x) y)] - [(or (fl= y 0.0) (exceptional-flonum? y)) (if (< x 0) (fl- y) y)] - [else (inexact (* x (exact y)))]))) - -(define exact-inexact/ - (lambda (x y) - (cond - [(fixnum? x) (fl/ (fixnum->flonum x) y)] - [(floatable? x) (fl/ (inexact x) y)] - [(or (fl= y 0.0) (exceptional-flonum? y)) - (if (< x 0) (fl/ -1.0 y) (fl/ y))] - [else (inexact (/ x (exact y)))]))) - -(define inexact-exact/ - (lambda (x y) - (cond - [(fixnum? y) (fl/ x (fixnum->flonum y))] - [(floatable? y) (fl/ x (inexact y))] - [(or (fl= x 0.0) (exceptional-flonum? x)) (if (< y 0) (fl- x) x)] - [else (inexact (/ (exact x) y))]))) - -(define floatable? - ; x is "floatable" if it can be made inexact without overflow or underflow - (lambda (x) - (type-case x - [(fixnum?) #t] - [(bignum?) (fx<= (integer-length x) (constant max-float-exponent))] - [(ratnum?) (fx<= (constant min-float-exponent) - (fx- (integer-length (numerator x)) - (integer-length (denominator x))) - (constant max-float-exponent))] - [($exactnum?) (and (floatable? (real-part x)) - (floatable? (imag-part x)))] - [else #t]))) - -(define fixnum-floatable-wlop? - ;; floatable without loss of precision - (lambda (x) - (if (<= (- (fixnum-width) 1) (constant float-mantissa-bits)) - #t - (let ([hi (expt 2 (constant float-mantissa-bits))]) - (fx<= (- hi) x hi))))) - -(define exact-inexact-compare? - ; e is an exact number, i is a flonum - ; Preserve transitivity by making i exact, - ; unless i is +/-infinity or a NAN, in which case any normal flonum - ; is a safe representation of e for comparative purposes. - (lambda (pred? e i) - (float-type-case - [(ieee) - (if (exceptional-flonum? i) - (pred? 0.0 i) - (pred? e (exact i)))] - [else (pred? e (exact i))]))) - -(define exact-sqrt - ; x must be exact - ; returns the exact square root if it exists, otherwise an approximation - (lambda (x) - (type-case x - [(fixnum? bignum?) - (if (< x 0) (make-rectangular 0 (isqrt (abs x))) (isqrt x))] - [(ratnum?) - (/ (exact-sqrt (numerator x)) (exact-sqrt (denominator x)))] - [else - (let ([rp (exact-sqrt (/ (+ (exact-sqrt (magnitude-squared x)) - (real-part x)) - 2))]) - (make-rectangular rp (/ (imag-part x) (* 2 rp))))]))) - -(define ($fldiv-and-mod x y) - (if (negated-flonum? y) - (let ([q ($flfloor (fl/ x (fl- y)))]) - (values (fl- q) (fl+ x (fl* y q)))) - (let ([q ($flfloor (fl/ x y))]) - (values q (fl- x (fl* y q)))))) - -(define ($fldiv x y) - (if (negated-flonum? y) - (fl- ($flfloor (fl/ x (fl- y)))) - ($flfloor (fl/ x y)))) - -(define ($flmod x y) - (if (negated-flonum? y) - (fl+ x (fl* y ($flfloor (fl/ x (fl- y))))) - (fl- x (fl* y ($flfloor (fl/ x y)))))) - -(define ($fldiv0-and-mod0 x y) - ; there doesn't seem to be an easy way to do this... - (let-values ([(d m) ($fldiv-and-mod x y)]) - (if (fl> y 0.0) - (if (fl< m (fl/ y 2.0)) - (values d m) - (values (fl+ d 1.0) (fl- m y))) - (if (fl< m (fl/ y -2.0)) - (values d m) - (values (fl- d 1.0) (fl+ m y)))))) - -(define ($fldiv0 x y) - (let-values ([(d m) ($fldiv-and-mod x y)]) - (if (fl> y 0.0) - (if (fl< m (fl/ y 2.0)) d (fl+ d 1.0)) - (if (fl< m (fl/ y -2.0)) d (fl- d 1.0))))) - -(define ($flmod0 x y) - (let ([m ($flmod x y)]) - (if (fl> y 0.0) - (if (fl< m (fl/ y 2.0)) m (fl- m y)) - (if (fl< m (fl/ y -2.0)) m (fl+ m y))))) - -(define ($fxdiv-and-mod x y who) ; signal error on overflow if who != #f, otherwise return bignum - (if (fx< x 0) - (if (fx< y 0) - (if (fx> x y) ; |x| < |y| => q = 0, r = x != 0 - (values 1 (fx- x y)) - (if (and (fx= y -1) (fx= x (most-negative-fixnum))) - (if who - ($impoops who "fixnum overflow with arguments ~s and ~s" x y) - (values (- (most-negative-fixnum)) 0)) - (let* ([q (fxquotient x y)] [r (fx- x (fx* y q))]) - (if (fx= r 0) (values q 0) (values (fx+ q 1) (fx- r y)))))) - (if (fx> x (fx- y)) ; |x| < |y| => q = 0, r = x != 0 - (values -1 (fx+ x y)) - (let* ([q (fxquotient x y)] [r (fx- x (fx* y q))]) - (if (fx= r 0) (values q 0) (values (fx- q 1) (fx+ r y)))))) - (if (or (fx< x y) (fx> (fx- x) y)) ; |x| < |y| => q = 0, r = x - (values 0 x) - (let ([q (fxquotient x y)]) - (values q (fx- x (fx* y q))))))) - -(define ($fxdiv x y who) ; signal error on overflow if who != #f, otherwise return bignum - (if (fx< x 0) - (if (fx< y 0) - (if (fx> x y) ; |x| < |y| => q = 0, r = x != 0 - 1 - (if (and (fx= y -1) (fx= x (most-negative-fixnum))) - (if who - ($impoops who "fixnum overflow with arguments ~s and ~s" x y) - (- (most-negative-fixnum))) - (let ([q (fxquotient x y)]) - (if (fx= x (fx* y q)) q (fx+ q 1))))) - (if (fx> x (fx- y)) ; |x| < |y| => q = 0, r = x != 0 - -1 - (let ([q (fxquotient x y)]) - (if (fx= x (fx* y q)) q (fx- q 1))))) - (if (or (fx< x y) (fx> (fx- x) y)) ; |x| < |y| => q = 0, r = x - 0 - (fxquotient x y)))) - -(define ($fxmod x y) ; no overflow possible - (if (fx< x 0) - (if (fx< y 0) - (if (fx> x y) ; |x| < |y| => q = 0, r = x != 0 - (fx- x y) - (if (and (fx= y -1) (fx= x (most-negative-fixnum))) - 0 - (let* ([q (fxquotient x y)] [r (fx- x (fx* y q))]) - (if (fx= r 0) 0 (fx- r y))))) - (if (fx> x (fx- y)) ; |x| < |y| => q = 0, r = x != 0 - (fx+ x y) - (let* ([q (fxquotient x y)] [r (fx- x (fx* y q))]) - (if (fx= r 0) 0 (fx+ r y))))) - (if (or (fx< x y) (fx> (fx- x) y)) ; |x| < |y| => q = 0, r = x - x - (fx- x (fx* y (fxquotient x y)))))) - -(define ($fxdiv0-and-mod0 x y who) - (let-values ([(d m) ($fxdiv-and-mod x y who)]) - (if (fx> y 0) - (if (fx< m (if (fx= y (most-positive-fixnum)) - (ash (+ (most-positive-fixnum) 1) -1) - (fxsrl (fx+ y 1) 1))) - (values d m) - (values (fx+ d 1) (fx- m y))) - (if (fx< m (if (fx= y (most-negative-fixnum)) - (ash (- 1 (most-negative-fixnum)) -1) - (fxsrl (fx- 1 y) 1))) - (values d m) - (values (fx- d 1) (fx+ m y)))))) - -(define ($fxdiv0 x y who) - (let-values ([(d m) ($fxdiv-and-mod x y who)]) - (if (fx> y 0) - (if (fx< m (if (fx= y (most-positive-fixnum)) - (ash (+ (most-positive-fixnum) 1) -1) - (fxsrl (fx+ y 1) 1))) - d - (fx+ d 1)) - (if (fx< m (if (fx= y (most-negative-fixnum)) - (ash (- 1 (most-negative-fixnum)) -1) - (fxsrl (fx- 1 y) 1))) - d - (fx- d 1))))) - -(define ($fxmod0 x y) - (let ([m ($fxmod x y)]) - (if (fx> y 0) - (if (fx< m (if (fx= y (most-positive-fixnum)) - (ash (+ (most-positive-fixnum) 1) -1) - (fxsrl (fx+ y 1) 1))) - m - (fx- m y)) - (if (fx< m (if (fx= y (most-negative-fixnum)) - (ash (- 1 (most-negative-fixnum)) -1) - (fxsrl (fx- 1 y) 1))) - m - (fx+ m y))))) - -(define ($exdiv-and-mod x y) ; like $fldiv-and-mod - (if (< y 0) - (let ([q (floor (/ x (- y)))]) - (values (- q) (+ x (* y q)))) - (let ([q (floor (/ x y))]) - (values q (- x (* y q)))))) - -(define ($exdiv0-and-mod0 x y) - (let-values ([(d m) ($exdiv-and-mod x y)]) - (if (> y 0) - (if (< m (/ y 2)) - (values d m) - (values (+ d 1) (- m y))) - (if (< m (/ y -2)) - (values d m) - (values (- d 1) (+ m y)))))) - -(define ($exdiv x y) ; like $fldiv - (if (< y 0) - (- (floor (/ x (- y)))) - (floor (/ x y)))) - -(define ($exmod x y) ; like $flmod - (if (< y 0) - (+ x (* y (floor (/ x (- y))))) - (- x (* y (floor (/ x y)))))) - -(define $sll - (lambda (who x n) - (type-case n - [(fixnum?) - (unless (fx>= n 0) ($oops who "~s is not a nonnegative exact integer" n)) - (type-case x - [(fixnum?) - (let ([max-fx-shift (- (constant fixnum-bits) 1)]) - (if (fx> n max-fx-shift) - (integer-ash x n) - (let ([m (#3%fxsll x n)]) - (if (fx= (fxsra m n) x) - m - (integer-ash x n)))))] - [(bignum?) (integer-ash x n)] - [else (nonexact-integer-error who x)])] - [(bignum?) - (unless ($bigpositive? n) ($oops who "~s is not a nonnegative exact integer" n)) - (type-case x - [(fixnum? bignum?) - (let ([k (most-positive-fixnum)]) - ($sll who ($sll who x k) (- n k)))] - [else (nonexact-integer-error who x)])] - [else (nonexact-integer-error who n)]))) - -(define $sra - (lambda (who x n) - (type-case n - [(fixnum?) - (unless (fx>= n 0) ($oops who "~s is not a nonnegative exact integer" n)) - (type-case x - [(fixnum?) - (let ([max-fx-shift (- (constant fixnum-bits) 1)]) - (fxsra x (if (fx> n max-fx-shift) max-fx-shift n)))] - [(bignum?) (integer-ash x (- n))] - [else (nonexact-integer-error who x)])] - [(bignum?) - (unless ($bigpositive? n) ($oops who "~s is not a nonnegative exact integer" n)) - (type-case x - [(fixnum? bignum?) - (let ([k (most-positive-fixnum)]) - ($sra who ($sra who x k) (- n k)))] - [else (nonexact-integer-error who x)])] - [else (nonexact-integer-error who n)]))) - -(define $negate - (lambda (who x) - (type-case x - [(fixnum?) - (if (fx= x (most-negative-fixnum)) - (let-syntax ([a (lambda (x) (- (constant most-negative-fixnum)))]) a) - (fx- x))] - [(bignum?) (big-negate x)] - [(flonum?) (fl- x)] - [(ratnum?) (integer/ (- ($ratio-numerator x)) ($ratio-denominator x))] - [($exactnum? $inexactnum?) (make-rectangular (- (real-part x)) (- (imag-part x)))] - [else (nonnumber-error who x)]))) - -(set! integer? - (lambda (x) - (type-case x - [(fixnum? bignum?) #t] - [(flonum?) ($flinteger? x)] - [else #f]))) - -(set! integer-valued? - (lambda (x) - (type-case x - [(fixnum? bignum?) #t] - [(flonum?) ($flinteger? x)] - [($inexactnum?) - (and (fl= ($inexactnum-imag-part x) 0.0) - ($flinteger? ($inexactnum-real-part x)))] - [else #f]))) - -(set! rational? - (lambda (x) - (type-case x - [(fixnum? bignum? ratnum?) #t] - [(flonum?) (not (exceptional-flonum? x))] - [else #f]))) - -(set! rational-valued? - (lambda (x) - (type-case x - [(fixnum? bignum? ratnum?) #t] - [(flonum?) (not (exceptional-flonum? x))] - [($inexactnum?) - (and (fl= ($inexactnum-imag-part x) 0.0) - (not (exceptional-flonum? ($inexactnum-real-part x))))] - [else #f]))) - -(set! real? - (lambda (x) - (type-case x - [(fixnum? flonum? bignum? ratnum?) #t] - [else #f]))) - -(set! real-valued? - (lambda (x) - (type-case x - [(fixnum? flonum? bignum? ratnum?) #t] - [($inexactnum?) (fl= ($inexactnum-imag-part x) 0.0)] - [else #f]))) - -(set! complex? - ; same as number? - (lambda (x) - (type-case x - [(fixnum? cflonum? bignum? ratnum? $exactnum?) #t] - [else #f]))) - -(set! number? - ; same as complex? - (lambda (x) - (type-case x - [(fixnum? cflonum? bignum? ratnum? $exactnum?) #t] - [else #f]))) - -(set! exact? - (lambda (x) - (type-case x - [(fixnum?) #t] - [(cflonum?) #f] - [(bignum? ratnum? $exactnum?) #t] - [else (nonnumber-error 'exact? x)]))) - -(set! inexact? - (lambda (x) - (type-case x - [(cflonum?) #t] - [(fixnum? bignum? ratnum? $exactnum?) #f] - [else (nonnumber-error 'inexact? x)]))) - -(set-who! numerator - (lambda (x) - (type-case x - [(ratnum?) ($ratio-numerator x)] - [(fixnum? bignum?) x] - [(flonum?) - (cond - [(exceptional-flonum? x) (nonrational-error who x)] - [($flinteger-or-inf? x) x] - [else (inexact (numerator (exact x)))])] - [else (nonrational-error who x)]))) - -(set-who! denominator - (lambda (x) - (type-case x - [(ratnum?) ($ratio-denominator x)] - [(fixnum? bignum?) 1] - [(flonum?) - (cond - [(exceptional-flonum? x) (nonrational-error who x)] - [($flinteger-or-inf? x) 1.0] - [else (inexact (denominator (exact x)))])] - [else (nonrational-error who x)]))) - -(set! real-part - (lambda (z) - (type-case z - [($inexactnum?) ($inexactnum-real-part z)] - [($exactnum?) ($exactnum-real-part z)] - [(flonum? fixnum? bignum? ratnum?) z] - [else (noncomplex-error 'real-part z)]))) - -(set! imag-part - (lambda (z) - (type-case z - [($inexactnum?) ($inexactnum-imag-part z)] - [($exactnum?) ($exactnum-imag-part z)] - [(flonum?) 0] - [(fixnum? bignum? ratnum?) 0] - [else (noncomplex-error 'imag-part z)]))) - -(set! modulo - (lambda (x y) - (unless (integer? x) (noninteger-error 'modulo x)) - (unless (integer? y) (noninteger-error 'modulo y)) - (when (= y 0) (domain-error 'modulo y)) - (let ([r (remainder x y)]) - (if (if (negative? y) (positive? r) (negative? r)) - (+ r y) - r)))) - -(set! expt-mod - ; (modulo (expt x y) z) - (lambda (x y z) - (unless (integer? x) - ($oops 'expt-mod "~s is not an integer" x)) - (unless (and (integer? y) (not (negative? y))) - ($oops 'expt-mod "~s is not a nonnegative integer" y)) - (unless (and (integer? z) (not (zero? z))) - ($oops 'expt-mod "~s is not a nonzero integer" z)) - (if (= y 0) - (modulo 1 z) - (do ([w 1 (if (even? y) w (remainder (* w b) z))] - [y y (quotient y 2)] - [b (remainder x z) (remainder (* b b) z)]) - ((= y 1) (modulo (* w b) z)))))) - -(set-who! negative? - (lambda (x) - (type-case x - [(fixnum?) (fx< x 0)] - [(flonum?) (fl< x 0.0)] - [(bignum?) (not ($bigpositive? x))] - [(ratnum?) (< ($ratio-numerator x) 0)] - [else (nonreal-error who x)]))) - -(set-who! nonnegative? - (lambda (x) - (type-case x - [(fixnum?) (fx>= x 0)] - [(flonum?) (fl>= x 0.0)] - [(bignum?) ($bigpositive? x)] - [(ratnum?) (>= ($ratio-numerator x) 0)] - [else (nonreal-error who x)]))) - -(set-who! positive? - (lambda (x) - (type-case x - [(fixnum?) (fx> x 0)] - [(flonum?) (fl> x 0.0)] - [(bignum?) ($bigpositive? x)] - [(ratnum?) (> ($ratio-numerator x) 0)] - [else (nonreal-error who x)]))) - -(set-who! nonpositive? - (lambda (x) - (type-case x - [(fixnum?) (fx<= x 0)] - [(flonum?) (fl<= x 0.0)] - [(bignum?) (not ($bigpositive? x))] - [(ratnum?) (<= ($ratio-numerator x) 0)] - [else (nonreal-error who x)]))) - -(set-who! min - (rec min - (case-lambda - [(x y) - (type-case x - [(flonum?) - (type-case y - [(flonum?) (if (or (fl< x y) ($nan? x)) x y)] - [(fixnum? bignum? ratnum?) (min x (inexact y))] - [else (nonreal-error who y)])] - [(fixnum?) - (type-case y - [(fixnum?) (if (fx< x y) x y)] - [(bignum? ratnum?) (if (< x y) x y)] - [(flonum?) (min (inexact x) y)] - [else (nonreal-error who y)])] - [(bignum? ratnum?) - (type-case y - [(fixnum? bignum? ratnum?) (if (< x y) x y)] - [(flonum?) (min (inexact x) y)] - [else (nonreal-error who y)])] - [else (nonreal-error who x)])] - [(x) (if (real? x) x (nonreal-error who x))] - [(x y . z) - (let loop ([x (min x y)] [z z]) - (if (null? z) - x - (loop (min x (car z)) (cdr z))))]))) - -(set-who! max - (rec max - (case-lambda - [(x y) - (type-case x - [(flonum?) - (type-case y - [(flonum?) (if (or (fl> x y) ($nan? x)) x y)] - [(fixnum? bignum? ratnum?) (max x (inexact y))] - [else (nonreal-error who y)])] - [(fixnum?) - (type-case y - [(fixnum?) (if (fx> x y) x y)] - [(bignum? ratnum?) (if (> x y) x y)] - [(flonum?) (max (inexact x) y)] - [else (nonreal-error who y)])] - [(bignum? ratnum?) - (type-case y - [(fixnum? bignum? ratnum?) (if (> x y) x y)] - [(flonum?) (max (inexact x) y)] - [else (nonreal-error who y)])] - [else (nonreal-error who x)])] - [(x) (if (real? x) x (nonreal-error who x))] - [(x y . z) - (let loop ([x (max x y)] [z z]) - (if (null? z) - x - (loop (max x (car z)) (cdr z))))]))) - -(let () - (define exgcd - (foreign-procedure "(cs)gcd" - (scheme-object scheme-object) - scheme-object)) - - (define (exlcm x1 x2) - (if (or (eqv? x1 0) (eqv? x2 0)) - 0 - (* (abs x1) (/ (abs x2) (exgcd x1 x2))))) - - (set-who! gcd - (rec gcd - (case-lambda - [() 0] - [(x1) (gcd x1 x1)] - [(x1 x2) - (if (and (or (fixnum? x1) (bignum? x1)) - (or (fixnum? x2) (bignum? x2))) - (exgcd x1 x2) - (begin - (unless (integer? x1) (noninteger-error who x1)) - (unless (integer? x2) (noninteger-error who x2)) - (inexact (exgcd (exact x1) (exact x2)))))] - [(x1 x2 . xr) - (let f ([x1 x1] [x2 x2] [xr xr]) - (let ([x1 (gcd x1 x2)]) - (if (null? xr) x1 (f x1 (car xr) (cdr xr)))))]))) - - (set-who! lcm - (rec lcm - (case-lambda - [() 1] - [(x) (lcm x x)] - [(x1 x2) - (if (and (or (fixnum? x1) (bignum? x1)) - (or (fixnum? x2) (bignum? x2))) - (exlcm x1 x2) - (begin - (unless (integer? x1) (noninteger-error who x1)) - (unless (integer? x2) (noninteger-error who x2)) - (inexact (exlcm (exact x1) (exact x2)))))] - [(x1 x2 . xr) - (let f ([x1 x1] [x2 x2] [xr xr]) - (let ([x1 (lcm x1 x2)]) - (if (null? xr) x1 (f x1 (car xr) (cdr xr)))))])))) - -(let () - (define convert-to-inexact - (lambda (z who) - (type-case z - [(fixnum?) (fixnum->flonum z)] - [(bignum? ratnum?) (float z)] - [($exactnum?) - (fl-make-rectangular (inexact ($exactnum-real-part z)) - (inexact ($exactnum-imag-part z)))] - [(cflonum?) z] - [else (nonnumber-error who z)]))) - (set-who! inexact (lambda (z) (convert-to-inexact z who))) - (set-who! exact->inexact (lambda (z) (convert-to-inexact z who)))) - -(let () - (define convert-to-exact - (lambda (z who) - (type-case z - [(flonum?) - (when (exceptional-flonum? z) - ($oops 'exact "no exact representation for ~s" z)) - (let ([dx (decode-float z)]) - (let ([mantissa (* (vector-ref dx 0) (vector-ref dx 2))] - [exponent (vector-ref dx 1)]) - (if (fx< exponent 0) - (/ mantissa (ash 1 (fx- exponent))) - (* mantissa (ash 1 exponent)))))] - [($inexactnum?) - (make-rectangular - (exact ($inexactnum-real-part z)) - (exact ($inexactnum-imag-part z)))] - [(fixnum? bignum? ratnum? $exactnum?) z] - [else (nonnumber-error who z)]))) - (set-who! exact (lambda (z) (convert-to-exact z who))) - (set-who! inexact->exact (lambda (z) (convert-to-exact z who)))) - -(set! rationalize - ; Alan Bawden's algorithm - (letrec - ([rat1 ; x < y - (lambda (x y) - (cond - [(> x 0) (rat2 x y)] - [(< y 0) (- (rat2 (- y) (- x)))] - [else (if (and (exact? x) (exact? y)) 0 0.0)]))] - [rat2 ; 0 < x < y - (lambda (x y) - (let ([fx (floor x)] [fy (floor y)]) - (cond - [(= fx x) fx] - [(= fx fy) (+ fx (/ (rat2 (/ (- y fy)) (/ (- x fx)))))] - [else (+ fx 1)])))]) - (lambda (x e) - (unless (real? x) (nonreal-error 'rationalize x)) - (unless (real? e) (nonreal-error 'rationalize e)) - (let ([x (- x e)] [y (+ x e)]) - (cond - [(< x y) (rat1 x y)] - [(< y x) (rat1 y x)] - [else x]))))) - -(set! abs - (lambda (z) - (type-case z - [(fixnum?) (if (fx< z 0) (if (fx= z (most-negative-fixnum)) (- (most-negative-fixnum)) (fx- z)) z)] - [(flonum?) (flabs z)] - [(bignum?) (if ($bigpositive? z) z (- z))] - [(ratnum?) (if (< z 0) (- z) z)] - [else (nonreal-error 'abs z)]))) - -(set! magnitude - (lambda (z) - (type-case z - [(flonum?) (flabs z)] - [(fixnum?) (if (fx< z 0) (- z) z)] - [($inexactnum?) (cflmagnitude z)] - [($exactnum?) - (let ([x ($exactnum-real-part z)] [y ($exactnum-imag-part z)]) - (sqrt (+ (* x x) (* y y))))] - [(bignum?) (if ($bigpositive? z) z (- z))] - [(ratnum?) (if (< z 0) (- z) z)] - [else (noncomplex-error 'magnitude z)]))) - -(set! angle - (lambda (z) - (type-case z - [(flonum?) (if (negated-flonum? z) pi 0.0)] - [($inexactnum?) (cflangle z)] - [(fixnum? bignum? ratnum?) - (cond - [(< z 0) pi] - [(> z 0) 0] - [else (domain-error 'angle z)])] - [($exactnum?) - ; use single argument atan to avoid precision loss - ; cases from Kahan - (let ([x ($exactnum-real-part z)] [y ($exactnum-imag-part z)]) - (cond - [(> (abs y) (abs x)) - (- (fl* pi (if (< y 0) -.5 .5)) (atan (/ x y)))] - [(< x 0) - (if (< y 0) - (- (atan (/ y x)) pi) - (+ (atan (/ y x)) pi))] - [else (atan (/ y x))]))] - [else (noncomplex-error 'angle z)]))) - -(set-who! make-rectangular - (lambda (x y) - (type-case y - [(flonum?) - (fl-make-rectangular - (type-case x - [(flonum?) x] - [(fixnum? bignum? ratnum?) (inexact x)] - [else (nonreal-error who x)]) - y)] - [(fixnum? bignum? ratnum?) - (if (eq? y 0) - (if (real? x) x (nonreal-error who x)) - (type-case x - [(fixnum? bignum? ratnum?) ($make-exactnum x y)] - [(flonum?) (fl-make-rectangular x (inexact y))] - [else (nonreal-error who x)]))] - [else (nonreal-error who y)]))) - -(set-who! make-polar - (lambda (x y) - (unless (real? x) (nonreal-error 'make-polar x)) - (unless (real? y) (nonreal-error 'make-polar y)) - (cond - [(eq? y 0) x] - [(eq? x 0) 0] - [else (make-rectangular (* x (cos y)) (* x (sin y)))]))) - -(set! log - (rec log - (case-lambda - [(x) - (type-case x - [(flonum?) - (if (negated-flonum? x) - (fl-make-rectangular ($fllog (fl- x)) pi) - ($fllog x))] - [($inexactnum?) (cfllog x)] - [(fixnum?) - (cond - [(fx> x 1) ($fllog (fixnum->flonum x))] - [(fx= x 1) 0] - [(fx< x 0) (make-rectangular (log (- x)) pi)] - [else (domain-error 'log x)])] - [(bignum?) - (let ([len (integer-length x)]) - (if (fx<= len (constant max-float-exponent)) - (log (inexact x)) - (+ (* len log2) (log (inexact (/ x (ash 1 len)))))))] - [(ratnum?) - (if (floatable? x) - (log (inexact x)) - (- (log (numerator x)) (log (denominator x))))] - [($exactnum?) - (make-rectangular - (/ (log (magnitude-squared x)) 2) - (angle x))] - [else (nonnumber-error 'log x)])] - [(x y) (/ (log x) (log y))]))) - -(define-trig-op exp $flexp cflexp 1) -(define-trig-op sin $flsin cflsin 0) -(define-trig-op cos $flcos cflcos 1) -(define-trig-op tan $fltan cfltan 0) - -(set! asin - (lambda (x) - (type-case x - [(flonum?) - ; make sure NANs go the "$flasin" route - (if (or (fl< x -1.0) (fl> x 1.0)) - (cflasin x) - ($flasin x))] - [($inexactnum?) (cflasin x)] - [(fixnum?) (if (fx= x 0) 0 (asin (fixnum->flonum x)))] - [(bignum? ratnum? $exactnum?) (asin (inexact x))] - [else (nonnumber-error 'asin x)]))) - -(set! acos - (lambda (x) - (type-case x - [(flonum?) - ; make sure NANs go the "$flacos" route - (if (or (fl< x -1.0) (fl> x 1.0)) - (cflacos x) - ($flacos x))] - [($inexactnum?) (cflacos x)] - [(fixnum?) (if (fx= x 1) 0 (acos (fixnum->flonum x)))] - [(bignum? ratnum? $exactnum?) (acos (inexact x))] - [else (nonnumber-error 'acos x)]))) - -(set! atan - (case-lambda - [(x) - (type-case x - [(flonum?) ($flatan x)] - [($inexactnum?) (cflatan x)] - [(fixnum?) (if (fx= x 0) 0 (atan (fixnum->flonum x)))] - [(bignum? ratnum?) (atan (inexact x))] - [($exactnum?) - (when (or (= x +i) (= x -i)) (domain-error 'atan x)) - (atan (inexact x))] - [else (nonnumber-error 'atan x)])] - [(y x) - (cond - [(and (flonum? y) (flonum? x)) - (flatan2 y x)] - [(and (fixnum? y) (fixnum? x)) - (if (fx= y 0) - (cond - [(fx> x 0) 0] - [(fx< x 0) pi] - [else (domain-error2 'atan2 y x)]) - (flatan2 (fixnum->flonum y) (fixnum->flonum x)))] - [else - (unless (real? y) (nonreal-error 'atan y)) - (unless (real? x) (nonreal-error 'atan x)) - (angle (make-rectangular x y))])])) - -(define-trig-op sinh flsinh cflsinh 0) -(define-trig-op cosh flcosh cflcosh 1) -(define-trig-op tanh fltanh cfltanh 0) -(define-trig-op asinh flasinh cflasinh 0) - -(set! acosh - (lambda (x) - (type-case x - [(flonum?) - ; make sure NANs go the "flacosh" route - (if (fl< x 1.0) (cflacosh x) (flacosh x))] - [($inexactnum?) (cflacosh x)] - [(fixnum?) (if (fx= x 1) 0 (acosh (fixnum->flonum x)))] - [(bignum? ratnum? $exactnum?) (acosh (inexact x))] - [else (nonnumber-error 'acosh x)]))) - -(set! atanh - (lambda (x) - (type-case x - [(flonum?) - ; make sure NANs go the "flatanh" route - (if (or (fl< x -1.0) (fl> x 1.0)) - (cflatanh x) - (flatanh x))] - [($inexactnum?) (cflatanh x)] - [(fixnum?) - (cond - [(or (fx> x 1) (fx< x -1)) (atanh (fixnum->flonum x))] - [(fx= x 0) 0] - [else (domain-error 'atan x)])] - [(bignum? ratnum? $exactnum?) (atanh (inexact x))] - [else (nonnumber-error 'atanh x)]))) - -; exceptional cases from Steele(CLtL), page 311 -(set! expt - (lambda (x y) - (type-case y - [(fixnum? bignum?) - (cond - [(and (eq? y 0) (number? x)) 1] - [(eq? x 0) - (if (< y 0) - ($impoops 'expt "undefined for values ~s and ~s" x y) - 0)] - [(eq? x 1) 1] - [(eq? x 2) (if (< y 0) (/ (ash 1 (- y))) (ash 1 y))] - [(and (flonum? x) (floatable? y)) ($flexpt x (inexact y))] - [(and ($inexactnum? x) (floatable? y)) (exp (* y (log x)))] - [(not (number? x)) (nonnumber-error 'expt x)] - [(ratnum? x) - (if (< y 0) - (let ([y (- y)]) - (/ (expt (denominator x) y) (expt (numerator x) y))) - (/ (expt (numerator x) y) (expt (denominator x) y)))] - [else - (let () - (define (f x n) - (if (eq? n 1) - x - (let ([s (f x (ash n -1))]) - (if (even? n) (* s s) (* (* s s) x))))) - (if (< y 0) - (if (or (fixnum? x) (bignum? x)) - (/ (f x (- y))) - (f (/ x) (- y))) - (f x y)))])] - [(flonum?) - (type-case x - [(flonum?) - (if (and (fl< x 0.0) (not ($flinteger-or-inf? y))) - (exp (* y (log x))) - ($flexpt x y))] - [($inexactnum? $exactnum?) (exp (* y (log x)))] - [(fixnum? bignum? ratnum?) - (if (floatable? x) - (expt (inexact x) y) - (exp (* y (log x))))] - [else (nonnumber-error 'expt x)])] - [($inexactnum?) - (if (or (eq? x 0) (and (flonum? x) (= x 0.0))) - 0.0 - (begin - (unless (number? x) (nonnumber-error 'expt x)) - (exp (* y (log x)))))] - [(ratnum? $exactnum?) - (unless (number? x) (nonnumber-error 'expt x)) - (cond - [(eq? x 0) - (if (> (real-part y) 0) - 0 - ($impoops 'expt "undefined for values ~s and ~s" x y))] - [(floatable? y) (expt x (inexact y))] - [else (exp (* y (log x)))])] - [else (nonnumber-error 'expt y)]))) - -(set! sqrt - (lambda (x) - (type-case x - [(flonum?) - (if (and (negated-flonum? x) (not ($nan? x))) - (fl-make-rectangular 0.0 ($flsqrt (flabs x))) - ($flsqrt x))] - [($inexactnum?) (cflsqrt x)] - [(fixnum? bignum? ratnum? $exactnum?) - (let ([y (exact-sqrt x)]) - (let ([yy (* y y)]) - (cond - [(= yy x) y] - [(floatable? x) (sqrt (inexact x))] - [else (* y (sqrt (inexact (/ x yy))))])))] - [else (nonnumber-error 'sqrt x)]))) - -(set! isqrt - ; Based on code credited to "boyland@aspen.Berkeley.EDU" by - ; Akira Kurihara (d34676@tansei.cc.u-tokyo.ac.jp) - (lambda (n) - (cond - [(and (or (fixnum? n) (bignum? n)) (>= n 0)) - (let isqrt ([n n]) - (cond - [(>= n 16) ; ensures k > 0 - (let ([a1 (let ([k (ash (- (integer-length n) 1) -2)]) - (ash (isqrt (ash n (- (ash k 1)))) k))]) - (let ([q&r ($quotient-remainder n a1)]) - (let ([a2 (car q&r)]) - (let ([a3 (ash (+ a1 a2) -1)]) - (if (odd? a2) - a3 - (let ([d (- a3 a1)]) - (if (> (* d d) (cdr q&r)) - (- a3 1) - a3)))))))] - [(>= n 9) 3] - [(>= n 4) 2] - [(>= n 1) 1] - [else 0]))] - [(and (integer? n) (>= n 0)) (floor (sqrt n))] - [else ($oops 'isqrt "~s is not a nonnegative integer" n)]))) - -(set-who! floor - (lambda (x) - (type-case x - [(fixnum? bignum?) x] - [(flonum?) ($flfloor x)] - [(ratnum?) - (let ([y (quotient ($ratio-numerator x) ($ratio-denominator x))]) - (if (< x 0) (- y 1) y))] - [else (nonreal-error who x)]))) - -(set-who! ceiling - (lambda (x) - (type-case x - [(fixnum? bignum?) x] - [(flonum?) ($flceiling x)] - [(ratnum?) - (let ([y (quotient ($ratio-numerator x) ($ratio-denominator x))]) - (if (< x 0) y (+ y 1)))] - [else (nonreal-error who x)]))) - -(set-who! truncate - (lambda (x) - (type-case x - [(fixnum? bignum?) x] - [(flonum?) (if (negated-flonum? x) (fl- ($flfloor (flabs x))) ($flfloor x))] - [(ratnum?) (quotient ($ratio-numerator x) ($ratio-denominator x))] - [else (nonreal-error who x)]))) - -(set-who! quotient - (let ([f (lambda (x y) (truncate (/ x y)))]) - (lambda (x y) - (type-case y - [(fixnum?) - (when (fx= y 0) (domain-error who y)) - (cond - [(fx= y 1) (unless (integer? x) (noninteger-error who x)) x] - [(fx= y -1) (unless (integer? x) (noninteger-error who x)) ($negate who x)] - [else - (type-case x - [(fixnum?) (if (and (fx= y -1) (fx= x (most-negative-fixnum))) - (- (most-negative-fixnum)) - (fxquotient x y))] - [(bignum?) (intquotient x y)] - [else - (unless (integer? x) (noninteger-error who x)) - (f x y)])])] - [(bignum?) - (type-case x - [(fixnum? bignum?) (intquotient x y)] - [else - (unless (integer? x) (noninteger-error who x)) - (f x y)])] - [else - (unless (integer? y) (noninteger-error who y)) - (unless (integer? x) (noninteger-error who x)) - (when (= y 0) (domain-error who y)) - (f x y)])))) - -(set-who! div-and-mod - (lambda (x y) - (type-case y - [(fixnum?) - (type-case x - [(fixnum?) - (when (fx= y 0) (domain-error who y)) - ($fxdiv-and-mod x y #f)] - [(flonum?) ($fldiv-and-mod x (fixnum->flonum y))] - [(bignum?) - (cond - [(fx= y 1) (values x 0)] - [(fx= y -1) (values (big-negate x) 0)] - [else - (when (fx= y 0) (domain-error who y)) - (let ([q.r (intquotient-remainder x y)]) - (if ($bigpositive? x) - (values (car q.r) (cdr q.r)) - (if (eq? (cdr q.r) 0) - (values (car q.r) 0) - (if (fx< y 0) - (values (+ (car q.r) 1) (fx- (cdr q.r) y)) - (values (- (car q.r) 1) (fx+ (cdr q.r) y))))))])] - [(ratnum?) - (when (fx= y 0) (domain-error who y)) - ($exdiv-and-mod x y)] - [else (domain-error who x)])] - [(flonum?) - (type-case x - [(fixnum?) ($fldiv-and-mod (fixnum->flonum x) y)] - [(flonum?) ($fldiv-and-mod x y)] - [(bignum? ratnum?) ($fldiv-and-mod (real->flonum x) y)] - [else (domain-error who x)])] - [(bignum?) - (type-case x - [(fixnum?) ; know |x| < |y| => q = 0, r = x - (if (fx< x 0) - (if ($bigpositive? y) (values -1 (+ x y)) (values 1 (- x y))) - (values 0 x))] - [(flonum?) ($fldiv-and-mod x (real->flonum y))] - [(bignum?) - (let ([q.r (intquotient-remainder x y)]) - (if ($bigpositive? x) - (values (car q.r) (cdr q.r)) - (if (eq? (cdr q.r) 0) - (values (car q.r) 0) - (if ($bigpositive? y) - (values (- (car q.r) 1) (+ (cdr q.r) y)) - (values (+ (car q.r) 1) (- (cdr q.r) y))))))] - [(ratnum?) ($exdiv-and-mod x y)] - [else (domain-error who x)])] - [(ratnum?) - (type-case x - [(fixnum? bignum? ratnum?) ($exdiv-and-mod x y)] - [(flonum?) ($fldiv-and-mod x (real->flonum y))] - [else (domain-error who x)])] - [else (domain-error who y)]))) - -(set-who! div - (lambda (x y) - (type-case y - [(fixnum?) - (type-case x - [(fixnum?) - (when (fx= y 0) (domain-error who y)) - ($fxdiv x y #f)] - [(flonum?) ($fldiv x (fixnum->flonum y))] - [(bignum?) - (when (fx= y 0) (domain-error who y)) - (cond - [(fx= y 1) x] - [(fx= y -1) (big-negate x)] - [else - (if ($bigpositive? x) - (intquotient x y) - (let ([q.r (intquotient-remainder x y)]) - (if (eq? (cdr q.r) 0) - (car q.r) - (if (fx< y 0) - (+ (car q.r) 1) - (- (car q.r) 1)))))])] - [(ratnum?) - (when (fx= y 0) (domain-error who y)) - ($exdiv x y)] - [else (domain-error who x)])] - [(flonum?) - (type-case x - [(fixnum?) ($fldiv (fixnum->flonum x) y)] - [(flonum?) ($fldiv x y)] - [(bignum? ratnum?) ($fldiv (real->flonum x) y)] - [else (domain-error who x)])] - [(bignum?) - (type-case x - [(fixnum?) ; know |x| < |y| => q = 0, r = x - (if (fx< x 0) (if ($bigpositive? y) -1 1) 0)] - [(flonum?) ($fldiv x (real->flonum y))] - [(bignum?) - (if ($bigpositive? x) - (intquotient x y) - (let ([q.r (intquotient-remainder x y)]) - (if (eq? (cdr q.r) 0) - (car q.r) - (if ($bigpositive? y) - (- (car q.r) 1) - (+ (car q.r) 1)))))] - [(ratnum?) ($exdiv x y)] - [else (domain-error who x)])] - [(ratnum?) - (type-case x - [(fixnum? bignum? ratnum?) ($exdiv x y)] - [(flonum?) ($fldiv x (real->flonum y))] - [else (domain-error who x)])] - [else (domain-error who y)]))) - -(set-who! mod - (lambda (x y) - (type-case y - [(fixnum?) - (type-case x - [(fixnum?) - (when (fx= y 0) (domain-error who y)) - ($fxmod x y)] - [(flonum?) ($flmod x (fixnum->flonum y))] - [(bignum?) - (when (fx= y 0) (domain-error who y)) - (cond - [(or (fx= y 1) (fx= y -1)) 0] - [else - (if ($bigpositive? x) - (intremainder x y) - (let ([q.r (intquotient-remainder x y)]) - (if (eq? (cdr q.r) 0) - 0 - (if (fx< y 0) - (fx- (cdr q.r) y) - (fx+ (cdr q.r) y)))))])] - [(ratnum?) - (when (fx= y 0) (domain-error who y)) - ($exmod x y)] - [else (domain-error who x)])] - [(flonum?) - (type-case x - [(fixnum?) ($flmod (fixnum->flonum x) y)] - [(flonum?) ($flmod x y)] - [(bignum? ratnum?) ($flmod (real->flonum x) y)] - [else (domain-error who x)])] - [(bignum?) - (type-case x - [(fixnum?) ; know |x| < |y| => q = 0, r = x - (if (fx< x 0) (if ($bigpositive? y) (+ x y) (- x y)) x)] - [(flonum?) ($flmod x (real->flonum y))] - [(bignum?) - (if ($bigpositive? x) - (intremainder x y) - (let ([q.r (intquotient-remainder x y)]) - (if (eq? (cdr q.r) 0) - 0 - (if ($bigpositive? y) - (+ (cdr q.r) y) - (- (cdr q.r) y)))))] - [(ratnum?) ($exmod x y)] - [else (domain-error who x)])] - [(ratnum?) - (type-case x - [(fixnum? bignum? ratnum?) ($exmod x y)] - [(flonum?) ($flmod x (real->flonum y))] - [else (domain-error who x)])] - [else (domain-error who y)]))) - -(set-who! div0-and-mod0 - (lambda (x y) - (type-case y - [(fixnum?) - (type-case x - [(fixnum?) - (when (fx= y 0) (domain-error who y)) - ($fxdiv0-and-mod0 x y #f)] - [(flonum?) ($fldiv0-and-mod0 x (fixnum->flonum y))] - [(bignum?) - (cond - [(fx= y 1) (values x 0)] - [(fx= y -1) (values (big-negate x) 0)] - [else - (when (fx= y 0) (domain-error who y)) - ($exdiv0-and-mod0 x y)])] - [(ratnum?) - (when (fx= y 0) (domain-error who y)) - ($exdiv0-and-mod0 x y)] - [else (domain-error who x)])] - [(flonum?) - (type-case x - [(fixnum?) ($fldiv0-and-mod0 (fixnum->flonum x) y)] - [(flonum?) ($fldiv0-and-mod0 x y)] - [(bignum? ratnum?) ($fldiv0-and-mod0 (real->flonum x) y)] - [else (domain-error who x)])] - [(bignum?) - (type-case x - [(fixnum? bignum? ratnum?) ($exdiv0-and-mod0 x y)] - [(flonum?) ($fldiv0-and-mod0 x (real->flonum y))] - [else (domain-error who x)])] - [(ratnum?) - (type-case x - [(fixnum? bignum? ratnum?) ($exdiv0-and-mod0 x y)] - [(flonum?) ($fldiv0-and-mod0 x (real->flonum y))] - [else (domain-error who x)])] - [else (domain-error who y)]))) - -(set-who! div0 - (lambda (x y) - (define (exdiv0 x y) - (let-values ([(d m) ($exdiv-and-mod x y)]) - (if (> y 0) - (if (< m (/ y 2)) d (+ d 1)) - (if (< m (/ y -2)) d (- d 1))))) - (type-case y - [(fixnum?) - (type-case x - [(fixnum?) - (when (fx= y 0) (domain-error who y)) - ($fxdiv0 x y #f)] - [(flonum?) ($fldiv0 x (fixnum->flonum y))] - [(bignum?) - (cond - [(fx= y 1) x] - [(fx= y -1) (big-negate x)] - [else - (when (fx= y 0) (domain-error who y)) - (exdiv0 x y)])] - [(ratnum?) - (when (fx= y 0) (domain-error who y)) - (exdiv0 x y)] - [else (domain-error who x)])] - [(flonum?) - (type-case x - [(fixnum?) ($fldiv0 (fixnum->flonum x) y)] - [(flonum?) ($fldiv0 x y)] - [(bignum? ratnum?) ($fldiv0 (real->flonum x) y)] - [else (domain-error who x)])] - [(bignum?) - (type-case x - [(fixnum? bignum? ratnum?) (exdiv0 x y)] - [(flonum?) ($fldiv0 x (real->flonum y))] - [else (domain-error who x)])] - [(ratnum?) - (type-case x - [(fixnum? bignum? ratnum?) (exdiv0 x y)] - [(flonum?) ($fldiv0 x (real->flonum y))] - [else (domain-error who x)])] - [else (domain-error who y)]))) - -(set-who! mod0 - (lambda (x y) - (define (exmod0 x y) - (let ([m ($exmod x y)]) - (if (> y 0) - (if (< m (/ y 2)) m (- m y)) - (if (< m (/ y -2)) m (+ m y))))) - (type-case y - [(fixnum?) - (type-case x - [(fixnum?) - (when (fx= y 0) (domain-error who y)) - ($fxmod0 x y)] - [(flonum?) ($flmod0 x (fixnum->flonum y))] - [(bignum?) - (cond - [(or (fx= y 1) (fx= y -1)) 0] - [else - (when (fx= y 0) (domain-error who y)) - (exmod0 x y)])] - [(ratnum?) - (when (fx= y 0) (domain-error who y)) - (exmod0 x y)] - [else (domain-error who x)])] - [(flonum?) - (type-case x - [(fixnum?) ($flmod0 (fixnum->flonum x) y)] - [(flonum?) ($flmod0 x y)] - [(bignum? ratnum?) ($flmod0 (real->flonum x) y)] - [else (domain-error who x)])] - [(bignum?) - (type-case x - [(fixnum? bignum? ratnum?) (exmod0 x y)] - [(flonum?) ($flmod0 x (real->flonum y))] - [else (domain-error who x)])] - [(ratnum?) - (type-case x - [(fixnum? bignum? ratnum?) (exmod0 x y)] - [(flonum?) ($flmod0 x (real->flonum y))] - [else (domain-error who x)])] - [else (domain-error who y)]))) - -(set-who! remainder - (let* ([fmod (cflop2 "(cs)mod")] - [f (lambda (x y) - (cond - [(eqv? x 0) 0] - [else - (let ([r (fmod (real->flonum x) (real->flonum y))]) - (if (fl= r 0.0) - ;; Always return positive 0.0 --- not sure why, - ;; but Racket and other Schemes seem to agree - 0.0 - r))]))]) - (lambda (x y) - (type-case y - [(fixnum?) - (when (fx= y 0) (domain-error who y)) - (cond - [(or (fx= y 1) (fx= y -1)) (unless (integer? x) (noninteger-error who x)) 0] - [else - (type-case x - [(fixnum?) (fxremainder x y)] - [(bignum?) (intremainder x y)] - [else - (unless (integer? x) (noninteger-error who x)) - (f x y)])])] - [(bignum?) - (type-case x - [(fixnum? bignum?) (intremainder x y)] - [else - (unless (integer? x) (noninteger-error who x)) - (f x y)])] - [else - (unless (integer? y) (noninteger-error who y)) - (unless (integer? x) (noninteger-error who x)) - (when (= y 0) (domain-error who y)) - (f x y)])))) - -(set-who! even? - (lambda (x) - (type-case x - [(fixnum?) (fxeven? x)] - [(bignum?) (not (bigodd? x))] - [(flonum?) - (when (exceptional-flonum? x) (noninteger-error who x)) - (let ([y (fl* ($flfloor (fl/ x 2.0)) 2.0)]) - (cond - [(fl= x y) #t] - [(fl= (fl+ y 1.0) x) #f] - [else (noninteger-error who x)]))] - [else - (unless (integer? x) (noninteger-error who x)) - (even? (real-part x))]))) - -(set-who! odd? - (lambda (x) - (type-case x - [(fixnum?) (fxodd? x)] - [(bignum?) (bigodd? x)] - [(flonum?) - (when (exceptional-flonum? x) (noninteger-error who x)) - (let ([y (fl* ($flfloor (fl/ x 2.0)) 2.0)]) - (cond - [(fl= x y) #f] - [(fl= (fl+ y 1.0) x) #t] - [else (noninteger-error who x)]))] - [else - (unless (integer? x) (noninteger-error who x)) - (odd? (real-part x))]))) - -(set-who! round - (lambda (x) - (type-case x - [(flonum?) (flround x)] - [(fixnum? bignum?) x] - [(ratnum?) - (let ([x1 (+ x 1/2)]) - (let ([x2 (floor x1)]) - (if (and (= x1 x2) (odd? x2)) - (- x2 1) - x2)))] - [else (nonreal-error who x)]))) - -;;; help routines used by library entries -;;; they are fully generic, but the cases are organized to catch those -;;; the library routines don't check first - -(set! $= - (lambda (who x y) - (type-case x - [(fixnum?) - (type-case y - [(fixnum?) (fx= x y)] - [(bignum? ratnum? $exactnum?) #f] - [(cflonum?) (if (fixnum-floatable-wlop? x) (cfl= (fixnum->flonum x) y) (exact-inexact-compare? = x y))] - [else (nonnumber-error who y)])] - [(bignum?) - (type-case y - [(fixnum?) #f] - [(bignum?) (big= x y)] - [(ratnum? $exactnum?) #f] - [(flonum?) (exact-inexact-compare? = x y)] - [($inexactnum?) (and (fl= ($inexactnum-imag-part y) 0.0) (= x ($inexactnum-real-part y)))] - [else (nonnumber-error who y)])] - [(ratnum?) - (type-case y - [(fixnum? bignum? $exactnum?) #f] - [(ratnum?) - (and (= ($ratio-numerator x) ($ratio-numerator y)) - (= ($ratio-denominator x) ($ratio-denominator y)))] - [(flonum?) (exact-inexact-compare? = x y)] - [($inexactnum?) (and (fl= ($inexactnum-imag-part y) 0.0) (= x ($inexactnum-real-part y)))] - [else (nonnumber-error who y)])] - [($exactnum? $inexactnum?) - (unless (number? y) (nonnumber-error who y)) - (and (= (real-part x) (real-part y)) (= (imag-part x) (imag-part y)))] - [(flonum?) - (type-case y - [(cflonum?) (cfl= x y)] - [(fixnum?) (if (fixnum-floatable-wlop? y) (fl= x (fixnum->flonum y)) (exact-inexact-compare? = y x))] - [(bignum? ratnum?) (exact-inexact-compare? = y x)] - [($exactnum?) #f] - [else (nonnumber-error who y)])] - [else (nonnumber-error who x)]))) - -(set! $< - (lambda (who x y) - (type-case x - [(fixnum?) - (type-case y - [(fixnum?) (fx< x y)] - [(bignum?) ($bigpositive? y)] - [(ratnum?) (< (* ($ratio-denominator y) x) ($ratio-numerator y))] - [(flonum?) (if (fixnum-floatable-wlop? x) (< (fixnum->flonum x) y) (exact-inexact-compare? < x y))] - [else (nonreal-error who y)])] - [(bignum?) - (type-case y - [(bignum?) (big< x y)] - [(fixnum?) (not ($bigpositive? x))] - [(ratnum?) (< (* ($ratio-denominator y) x) ($ratio-numerator y))] - [(flonum?) (exact-inexact-compare? < x y)] - [else (nonreal-error who y)])] - [(ratnum?) - (type-case y - [(fixnum? bignum?) - (< ($ratio-numerator x) (* ($ratio-denominator x) y))] - [(ratnum?) - (< (* ($ratio-numerator x) ($ratio-denominator y)) - (* ($ratio-numerator y) ($ratio-denominator x)))] - [(flonum?) (exact-inexact-compare? < x y)] - [else (nonreal-error who y)])] - [(flonum?) - (type-case y - [(flonum?) (fl< x y)] - [(fixnum?) (if (fixnum-floatable-wlop? y) (fl< x (fixnum->flonum y)) (exact-inexact-compare? > y x))] - [(bignum? ratnum?) (exact-inexact-compare? > y x)] - [else (nonreal-error who y)])] - [else (nonreal-error who x)]))) - -(set! $<= - (lambda (who x y) - (type-case x - [(fixnum?) - (type-case y - [(fixnum?) (fx<= x y)] - [(bignum?) ($bigpositive? y)] - [(ratnum?) - (<= (* ($ratio-denominator y) x) ($ratio-numerator y))] - [(flonum?) (if (fixnum-floatable-wlop? x) (<= (fixnum->flonum x) y) (exact-inexact-compare? <= x y))] - [else (nonreal-error who y)])] - [(bignum?) - (type-case y - [(bignum?) (not (big< y x))] - [(fixnum?) (not ($bigpositive? x))] - [(ratnum?) - (<= (* ($ratio-denominator y) x) ($ratio-numerator y))] - [(flonum?) (exact-inexact-compare? <= x y)] - [else (nonreal-error who y)])] - [(ratnum?) - (type-case y - [(fixnum? bignum?) - (<= ($ratio-numerator x) (* ($ratio-denominator x) y))] - [(ratnum?) - (<= (* ($ratio-numerator x) ($ratio-denominator y)) - (* ($ratio-numerator y) ($ratio-denominator x)))] - [(flonum?) (exact-inexact-compare? <= x y)] - [else (nonreal-error who y)])] - [(flonum?) - (type-case y - [(flonum?) (fl<= x y)] - [(fixnum?) (if (fixnum-floatable-wlop? y) (fl<= x (fixnum->flonum y)) (exact-inexact-compare? >= y x))] - [(bignum? ratnum?) (exact-inexact-compare? >= y x)] - [else (nonreal-error who y)])] - [else (nonreal-error who x)]))) - -(set! $+ - (lambda (who x y) - (define (exint-unknown+ who x y) - (type-case y - [(fixnum? bignum?) (integer+ x y)] - [(ratnum?) - (let ([d ($ratio-denominator y)]) - (integer/ (+ (* x d) ($ratio-numerator y)) d))] - [(flonum?) (exact-inexact+ x y)] - [($exactnum? $inexactnum?) - (make-rectangular (+ x (real-part y)) (imag-part y))] - [else (nonnumber-error who y)])) - (cond - [(eqv? y 0) (unless (number? x) (nonnumber-error who x)) x] - [else - (type-case x - [(fixnum?) - (cond - [(fx= x 0) (unless (number? y) (nonnumber-error who y)) y] - [else (exint-unknown+ who x y)])] - [(bignum?) (exint-unknown+ who x y)] - [(ratnum?) - (type-case y - [(fixnum? bignum?) - (let ([d ($ratio-denominator x)]) - (integer/ (+ (* y d) ($ratio-numerator x)) d))] - [(ratnum?) - (let ([xd ($ratio-denominator x)] [yd ($ratio-denominator y)]) - (integer/ - (+ (* ($ratio-numerator x) yd) (* ($ratio-numerator y) xd)) - (* xd yd)))] - [($exactnum? $inexactnum?) - (make-rectangular (+ x (real-part y)) (imag-part y))] - [(flonum?) (exact-inexact+ x y)] - [else (nonnumber-error who y)])] - [(flonum?) - (type-case y - [(cflonum?) (cfl+ x y)] - [(fixnum? bignum? ratnum?) (exact-inexact+ y x)] - [($exactnum?) - (make-rectangular (+ x (real-part y)) (imag-part y))] - [else (nonnumber-error who y)])] - [($exactnum? $inexactnum?) - (type-case y - [(fixnum? bignum? ratnum? flonum?) - (make-rectangular (+ (real-part x) y) (imag-part x))] - [($exactnum? $inexactnum?) - (make-rectangular (+ (real-part x) (real-part y)) - (+ (imag-part x) (imag-part y)))] - [else (nonnumber-error who y)])] - [else (nonnumber-error who x)])]))) - -(set! $* - (lambda (who x y) - (define (exint-unknown* who x y) - (type-case y - [(fixnum? bignum?) (integer* x y)] - [(ratnum?) (integer/ (* x ($ratio-numerator y)) ($ratio-denominator y))] - [($exactnum? $inexactnum?) - (make-rectangular (* x (real-part y)) (* x (imag-part y)))] - [(flonum?) (exact-inexact* x y)] - [else (nonnumber-error who y)])) - (cond - [(and (fixnum? y) ($fxu< (#3%fx+ y 1) 3)) - (cond - [(fx= y 0) (unless (number? x) (nonnumber-error who x)) 0] - [(fx= y 1) (unless (number? x) (nonnumber-error who x)) x] - [else ($negate who x)])] - [else - (type-case x - [(fixnum?) - (cond - [($fxu< (#3%fx+ x 1) 3) - (cond - [(fx= x 0) (unless (number? y) (nonnumber-error who y)) 0] - [(fx= x 1) (unless (number? y) (nonnumber-error who y)) y] - [else ($negate who y)])] - [else (exint-unknown* who x y)])] - [(bignum?) (exint-unknown* who x y)] - [(ratnum?) - (type-case y - [(fixnum? bignum?) - (integer/ (* y ($ratio-numerator x)) ($ratio-denominator x))] - [(ratnum?) - (integer/ - (* ($ratio-numerator x) ($ratio-numerator y)) - (* ($ratio-denominator x) ($ratio-denominator y)))] - [($exactnum? $inexactnum?) - (make-rectangular (* x (real-part y)) (* x (imag-part y)))] - [(flonum?) (exact-inexact* x y)] - [else (nonnumber-error who y)])] - [(flonum?) - (type-case y - [(cflonum?) (cfl* x y)] - [(fixnum? bignum? ratnum?) (exact-inexact* y x)] - [($exactnum?) - (make-rectangular (* x (real-part y)) (* x (imag-part y)))] - [else (nonnumber-error who y)])] - [($exactnum? $inexactnum?) - (type-case y - [(fixnum? bignum? ratnum? flonum?) - (make-rectangular (* (real-part x) y) (* (imag-part x) y))] - [($exactnum? $inexactnum?) - (let ([a (real-part x)] [b (imag-part x)] - [c (real-part y)] [d (imag-part y)]) - (make-rectangular (- (* a c) (* b d)) (+ (* a d) (* b c))))] - [else (nonnumber-error who y)])] - [else (nonnumber-error who x)])]))) - -(set! $- - (lambda (who x y) - (define (exint-unknown- who x y) - (type-case y - [(fixnum? bignum?) (integer- x y)] - [(ratnum?) - (let ([d ($ratio-denominator y)]) - (integer/ (- (* x d) ($ratio-numerator y)) d))] - [($exactnum? $inexactnum?) - (make-rectangular (- x (real-part y)) (- (imag-part y)))] - [(flonum?) (exact-inexact- x y)] - [else (nonnumber-error who y)])) - (cond - [(eqv? y 0) (unless (number? x) (nonnumber-error who x)) x] - [else - (type-case x - [(fixnum?) - (cond - [(eqv? x 0) ($negate who y)] - [else (exint-unknown- who x y)])] - [(bignum?) (exint-unknown- who x y)] - [(ratnum?) - (type-case y - [(fixnum? bignum?) - (let ([d ($ratio-denominator x)]) - (integer/ (- ($ratio-numerator x) (* y d)) d))] - [(ratnum?) - (let ([xd ($ratio-denominator x)] [yd ($ratio-denominator y)]) - (integer/ - (- (* ($ratio-numerator x) yd) (* ($ratio-numerator y) xd)) - (* xd yd)))] - [($exactnum? $inexactnum?) - (make-rectangular (- x (real-part y)) (- (imag-part y)))] - [(flonum?) (exact-inexact- x y)] - [else (nonnumber-error who y)])] - [(flonum?) - (type-case y - [(cflonum?) (cfl- x y)] - [(fixnum? bignum? ratnum?) (inexact-exact- x y)] - [($exactnum?) - (make-rectangular (- x (real-part y)) (- (imag-part y)))] - [else (nonnumber-error who y)])] - [($exactnum? $inexactnum?) - (type-case y - [(fixnum? bignum? ratnum? flonum?) - (make-rectangular (- (real-part x) y) (imag-part x))] - [($exactnum? $inexactnum?) - (make-rectangular (- (real-part x) (real-part y)) - (- (imag-part x) (imag-part y)))] - [else (nonnumber-error who y)])] - [else (nonnumber-error who x)])]))) - -(set! $/ - (lambda (who x y) - (define (unknown-exint/ who x y) - (type-case x - [(fixnum?) - (when (eqv? y 0) (domain-error who y)) - (if (eqv? x 0) 0 (integer/ x y))] - [(bignum?) - (when (eqv? y 0) (domain-error who y)) - (integer/ x y)] - [(ratnum?) - (when (eqv? y 0) (domain-error who y)) - (integer/ ($ratio-numerator x) (* y ($ratio-denominator x)))] - [($exactnum?) - (when (eqv? y 0) (domain-error who y)) - (make-rectangular (/ (real-part x) y) (/ (imag-part x) y))] - [($inexactnum?) - (make-rectangular (/ (real-part x) y) (/ (imag-part x) y))] - [(flonum?) (inexact-exact/ x y)] - [else (nonnumber-error who x)])) - (type-case y - [(fixnum?) - (cond - [(fx= y 1) (unless (number? x) (nonnumber-error who x)) x] - [(fx= y -1) (unless (number? x) (nonnumber-error who x)) ($negate who x)] - [else (unknown-exint/ who x y)])] - [(bignum?) (unknown-exint/ who x y)] - [(ratnum?) - (type-case x - [(fixnum? bignum?) - (integer/ (* x ($ratio-denominator y)) ($ratio-numerator y))] - [(ratnum?) - (integer/ (* ($ratio-numerator x) ($ratio-denominator y)) - (* ($ratio-denominator x) ($ratio-numerator y)))] - [($exactnum? $inexactnum?) - (make-rectangular (/ (real-part x) y) (/ (imag-part x) y))] - [(flonum?) (inexact-exact/ x y)] - [else (nonnumber-error who x)])] - [(flonum?) - (type-case x - [(cflonum?) (cfl/ x y)] - [(fixnum? bignum? ratnum?) (exact-inexact/ x y)] - [($exactnum?) - (make-rectangular (/ (real-part x) y) (/ (imag-part x) y))] - [else (nonnumber-error who x)])] - [($exactnum? $inexactnum?) - (type-case x - [(fixnum? bignum? ratnum? flonum?) - ;; a / c+di => c(a/(cc+dd)) + (-d(a/cc+dd))i - (let ([c (real-part y)] [d (imag-part y)]) - (let ([t (/ x (+ (* c c) (* d d)))]) - (make-rectangular (* c t) (- (* d t)))))] - [($exactnum? $inexactnum?) - ;; a+bi / c+di => (ac+bd)/(cc+dd) + ((bc-ad)/(cc+dd))i - (let ([a (real-part x)] [b (imag-part x)] - [c (real-part y)] [d (imag-part y)]) - (let ([t (+ (* c c) (* d d))]) - (make-rectangular (/ (+ (* a c) (* b d)) t) - (/ (- (* b c) (* a d)) t))))] - [else (nonnumber-error who x)])] - [else (nonnumber-error who y)]))) - -(set! conjugate - (lambda (x) - (type-case x - [(flonum? fixnum? ratnum? bignum?) x] - [($inexactnum?) - (fl-make-rectangular ($inexactnum-real-part x) - (fl- ($inexactnum-imag-part x)))] - [($exactnum?) - ($make-exactnum ($exactnum-real-part x) - (- ($exactnum-imag-part x)))] - [else (nonnumber-error 'conjugate x)]))) - -(set! magnitude-squared - (lambda (x) - (type-case x - [(flonum?) (fl* x x)] - [($inexactnum?) - (let ([a ($inexactnum-real-part x)] [b ($inexactnum-imag-part x)]) - (fl+ (fl* a a) (fl* b b)))] - [(fixnum? ratnum? bignum?) (* x x)] - [($exactnum?) - (let ([a ($exactnum-real-part x)] [b ($exactnum-imag-part x)]) - (+ (* a a) (* b b)))] - [else (nonnumber-error 'magnitude-squared x)]))) - -(set! cfl-magnitude-squared - (lambda (x) - (type-case x - [(flonum?) (fl* x x)] - [($inexactnum?) - (let ([a ($inexactnum-real-part x)] [b ($inexactnum-imag-part x)]) - (fl+ (fl* a a) (fl* b b)))] - [else (noncflonum-error 'cfl-magnitude-squared x)]))) - -(set! zero? - (lambda (z) - (type-case z - [(fixnum?) (fx= z 0)] - [(flonum?) (fl= z 0.0)] - [($inexactnum?) (cfl= z 0.0)] - [(bignum? ratnum? $exactnum?) #f] - [else (nonnumber-error 'zero? z)]))) - -(set-who! nan? - (lambda (x) - (type-case x - [(flonum?) ($nan? x)] - [(fixnum? bignum? ratnum?) #f] - [else (nonreal-error who x)]))) - -(set-who! infinite? - (lambda (x) - (type-case x - [(flonum?) (infinity? x)] - [(fixnum? bignum? ratnum?) #f] - [else (nonreal-error who x)]))) - -(set-who! finite? - (lambda (x) - (type-case x - [(flonum?) (not (exceptional-flonum? x))] - [(fixnum? bignum? ratnum?) #t] - [else (nonreal-error who x)]))) - -(let () - (define $ash - (lambda (who x n) - (type-case n - [(fixnum?) - (type-case x - [(fixnum?) - (let ([max-fx-shift (- (constant fixnum-bits) 1)]) - (if (fx< n 0) - ; can't just go for it since (- n) may not be representable - (if (fx< n (- max-fx-shift)) - (fxsra x max-fx-shift) - (fxsra x (fx- n))) - (if (fx> n max-fx-shift) - (integer-ash x n) - (let ([m (#3%fxsll x n)]) - (if (fx= (fxsra m n) x) - m - (integer-ash x n))))))] - [(bignum?) (integer-ash x n)] - [else (nonexact-integer-error who x)])] - [(bignum?) - (type-case x - [(fixnum? bignum?) - (let ([k (if (negative? n) - (most-negative-fixnum) - (most-positive-fixnum))]) - (ash (ash x k) (- n k)))] - [else (nonexact-integer-error who x)])] - [else (nonexact-integer-error who n)]))) - - (set-who! ash (lambda (x n) ($ash who x n))) - - (set-who! bitwise-arithmetic-shift (lambda (x n) ($ash who x n)))) - -(set-who! bitwise-arithmetic-shift-left (lambda (x n) ($sll who x n))) - -(set-who! bitwise-arithmetic-shift-right (lambda (x n) ($sra who x n))) - -(set-who! integer-length - (lambda (x) - (type-case x - [(fixnum?) (fxlength x)] - [(bignum?) (biglength x)] - [else (nonexact-integer-error who x)]))) - -(set-who! bitwise-length ; same as integer-length - (lambda (x) - (type-case x - [(fixnum?) (fxlength x)] - [(bignum?) (biglength x)] - [else (nonexact-integer-error who x)]))) - -(set-who! bitwise-if - (lambda (x y z) - (define big-if - (lambda (ei1 ei2 ei3) - (bitwise-ior (bitwise-and ei1 ei2) - (bitwise-and (bitwise-not ei1) ei3)))) - (type-case x - [(fixnum?) - (type-case y - [(fixnum?) - (type-case z - [(fixnum?) (fxif x y z)] - [(bignum?) (big-if x y z)] - [else (nonexact-integer-error who z)])] - [(bignum?) - (type-case z - [(fixnum? bignum?) (big-if x y z)] - [else (nonexact-integer-error who z)])] - [else (nonexact-integer-error who y)])] - [(bignum?) - (type-case y - [(fixnum? bignum?) - (type-case z - [(fixnum? bignum?) (big-if x y z)] - [else (nonexact-integer-error who z)])] - [else (nonexact-integer-error who y)])] - [else (nonexact-integer-error who x)]))) - -(set-who! bitwise-copy-bit - (lambda (x y b) - (unless (and (integer? x) (exact? x)) - ($oops who "~s is not an exact integer" x)) - (unless (or (and (fixnum? y) (fxnonnegative? y)) - (and (bignum? y) ($bigpositive? y))) - ($oops who "~s is not a nonnegative exact integer" y)) - (cond - [(eq? b 0) (logbit0 y x)] - [(eq? b 1) (logbit1 y x)] - [else ($oops who "bit argument ~s is not 0 or 1" b)]))) - -(let () - (define count-table - (let () - (define-syntax make-count-table - (lambda (x) - #`'#,(let ([bv (make-bytevector 256)]) - (define slow-bit-count - (lambda (x) - (do ([x x (fxsrl x 1)] [cnt 0 (if (fxodd? x) (fx+ cnt 1) cnt)]) - ((fx= x 0) cnt)))) - (do ([i 0 (fx+ i 1)]) - ((fx= i 256)) - (bytevector-u8-set! bv i (slow-bit-count i))) - bv))) - (make-count-table))) - (define $fxbit-count - (lambda (n) - (if (fx= n 0) - 0 - (constant-case ptr-bits - [(64) - (fx+ (bytevector-u8-ref count-table (fxlogand n #xff)) - (bytevector-u8-ref count-table (fxlogand (fxsrl n 8) #xff)) - (bytevector-u8-ref count-table (fxlogand (fxsrl n 16) #xff)) - (bytevector-u8-ref count-table (fxlogand (fxsrl n 24) #xff)) - (bytevector-u8-ref count-table (fxlogand (fxsrl n 32) #xff)) - (bytevector-u8-ref count-table (fxlogand (fxsrl n 40) #xff)) - (bytevector-u8-ref count-table (fxlogand (fxsrl n 48) #xff)) - (bytevector-u8-ref count-table (fxlogand (fxsrl n 56) #xff)))] - [(32) - (fx+ (bytevector-u8-ref count-table (fxlogand n #xff)) - (bytevector-u8-ref count-table (fxlogand (fxsrl n 8) #xff)) - (bytevector-u8-ref count-table (fxlogand (fxsrl n 16) #xff)) - (bytevector-u8-ref count-table (fxlogand (fxsrl n 24) #xff)))])))) - (define $big-bit-count - (lambda (n) - (let ([end (fx+ (fx* ($bignum-length n) (constant bigit-bytes)) (constant bignum-data-disp))]) - (do ([i (constant bignum-data-disp) (fx+ i 1)] - [cnt 0 (+ cnt (bytevector-u8-ref count-table ($object-ref 'unsigned-8 n i)))]) - ((fx= i end) cnt))))) - (set-who! fxbit-count - (lambda (n) - (unless (fixnum? n) ($oops who "~s is not a fixnum" n)) - (if (fx< n 0) - (fxnot ($fxbit-count (fxnot n))) - ($fxbit-count n)))) - (set-who! bitwise-bit-count - (lambda (n) - (cond - [(fixnum? n) - (if (fx< n 0) - (fxnot ($fxbit-count (fxnot n))) - ($fxbit-count n))] - [(bignum? n) - (if ($bigpositive? n) - ($big-bit-count n) - (fxnot ($big-bit-count (bitwise-not n))))] - [else ($oops who "~s is not an exact integer" n)])))) - -(set-who! bitwise-first-bit-set - (let () - (define $big-first-bit-set - (foreign-procedure "(cs)s_big_first_bit_set" (ptr) ptr)) - (lambda (n) - (cond - [(fixnum? n) (fxfirst-bit-set n)] - [(bignum? n) ($big-first-bit-set n)] - [else ($oops who "~s is not an exact integer" n)])))) - -(set-who! bitwise-bit-field - (let () - ; big-positive-bit-field assumes n is a positive bignum, start and - ; end are nonnegative fixnums, and end > start - (define big-positive-bit-field - (foreign-procedure "(cs)s_big_positive_bit_field" (ptr ptr ptr) ptr)) - (define (generic-bit-field n start end) - (bitwise-and - ($sra who n start) - (- ($sll who 1 (- end start)) 1))) - (lambda (n start end) - (unless (or (fixnum? n) (bignum? n)) - ($oops who "~s is not an exact integer" n)) - (cond - [(and (fixnum? start) (fixnum? end)) - (unless (fx>= start 0) ($oops who "invalid start index ~s" start)) - (unless (fx>= end start) ($oops who "invalid end index ~s" end)) - (cond - [(fx= end start) 0] - [(and (fixnum? n) (fx< end (fx- (fixnum-width) 1))) - (fxsra (fxand n (fxnot (fxsll -1 end))) start)] - [(and (bignum? n) ($bigpositive? n)) - (big-positive-bit-field n start end)] - [else (generic-bit-field n start end)])] - [else - (unless (or (and (fixnum? start) (fx>= start 0)) - (and (bignum? start) ($bigpositive? start))) - ($oops who "invalid start index ~s" start)) - (unless (or (and (fixnum? end) (>= end start)) - (and (bignum? end) (>= end start))) - ($oops who "invalid end index ~s" end)) - (generic-bit-field n start end)])))) - -(set-who! exact-integer-sqrt - (lambda (n) - (define (big-integer-sqrt n) - ; adapted from SRFI 77 mail-archive posting by Brad Lucier, who derived - ; it from "Karatsuba Square Root" by Paul Zimmermann, INRIA technical report - ; RR-3805, 1999. - (if (and (fixnum? n) (or (not (fixnum? (expt 2 52))) (< n (expt 2 52)))) - (let ([q (flonum->fixnum (flsqrt (fixnum->flonum n)))]) - (values q (fx- n (fx* q q)))) - (let ([b ($sra who (+ (integer-length n) 1) 2)]) - (let-values ([(s^ r^) (big-integer-sqrt ($sra who n (+ b b)))]) - (let* ([q&u (intquotient-remainder - (+ ($sll who r^ b) - (bitwise-bit-field n b (+ b b))) - ($sll who s^ 1))] - [q (car q&u)] - [u (cdr q&u)]) - (let ([s (+ ($sll who s^ b) q)] - [r (- (+ ($sll who u b) - (bitwise-bit-field n 0 b)) - (* q q))]) - (if (negative? r) - (values - (- s 1) - (+ r (- ($sll who s 1) 1))) - (values s r)))))))) - (cond - [(and (fixnum? n) (fx>= n 0)) - (if (or (not (fixnum? (expt 2 52))) - (fx< n (expt 2 52))) - (let ([q (flonum->fixnum (flsqrt (fixnum->flonum n)))]) - (values q (fx- n (fx* q q)))) - (big-integer-sqrt n))] - [(and (bignum? n) (#%$bigpositive? n)) (big-integer-sqrt n)] - [else ($oops who "~s is not a nonnegative exact integer" n)]))) - -(set-who! $quotient-remainder - (lambda (x y) - (type-case y - [(fixnum? bignum?) - (when (eq? y 0) (domain-error who y)) - (type-case x - [(fixnum? bignum?) (intquotient-remainder x y)] - [else (nonexact-integer-error who x)])] - [else (nonexact-integer-error who y)]))) - -(set! random - (let ([fxrandom (foreign-procedure "(cs)s_fxrandom" - (scheme-object) scheme-object)] - [flrandom (foreign-procedure "(cs)s_flrandom" - (scheme-object) scheme-object)]) - (lambda (x) - (cond - [(and (fixnum? x) (fx> x 0)) (fxrandom x)] - [(and (flonum? x) (fl> x 0.0)) (flrandom x)] - [(and (bignum? x) (> x 0)) - (let ([radix (most-positive-fixnum)]) - (do ([i x (quotient i radix)] - [a (fxrandom radix) (+ (* a radix) (fxrandom radix))]) - ((<= i radix) (remainder a x))))] - [else ($oops 'random "invalid argument ~s" x)])))) - -(set! random-seed ; must follow \#- - (let ([limit #xFFFFFFFF] - [get-seed (foreign-procedure "(cs)s_random_seed" - () unsigned-32)] - [set-seed (foreign-procedure "(cs)s_set_random_seed" - (unsigned-32) void)]) - (case-lambda - [() (get-seed)] - [(n) - (unless (and (or (fixnum? n) (bignum? n)) (<= 1 n limit)) - ($oops 'random-seed "invalid argument ~s" n)) - (set-seed n)]))) - -(let () - (define-syntax fl-op - (syntax-rules () - [(_ name $name x ...) - (set-who! name - (lambda (x ...) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - ... - ($name x ...)))])) - (fl-op flexp $flexp x) - (fl-op flsin $flsin x) - (fl-op flcos $flcos x) - (fl-op fltan $fltan x) - (fl-op flasin $flasin x) - (fl-op flacos $flacos x) - (fl-op flsqrt $flsqrt x) - (fl-op flexpt $flexpt x y) - (fl-op flfloor $flfloor x) - (fl-op flceiling $flceiling x)) - -(set-who! flinteger? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - ($flinteger? x))) - -(set-who! fllog - (rec fllog - (case-lambda - [(x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - ($fllog x)] - [(x y) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - (/ ($fllog x) ($fllog y))]))) - -(set-who! flatan - (rec flatan - (case-lambda - [(x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - ($flatan x)] - [(x y) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - (flatan2 x y)]))) - -(set-who! fltruncate - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (if (negated-flonum? x) (fl- ($flfloor (flabs x))) ($flfloor x)))) - -(set-who! flnan? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - ($nan? x))) - -(set-who! flinfinite? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (infinity? x))) - -(set-who! flfinite? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (not (exceptional-flonum? x)))) - -(set-who! flzero? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (fl= x 0.0))) - -(set-who! flpositive? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (fl> x 0.0))) - -(set-who! flnegative? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (fl< x 0.0))) - -(set-who! flnonpositive? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (fl<= x 0.0))) - -(set-who! flnonnegative? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (fl>= x 0.0))) - -(set-who! fleven? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (when (exceptional-flonum? x) (noninteger-error who x)) - (let ([y (fl* ($flfloor (fl/ x 2.0)) 2.0)]) - (cond - [(fl= x y) #t] - [(fl= (fl+ y 1.0) x) #f] - [else (noninteger-error who x)])))) - -(set-who! flodd? - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (when (exceptional-flonum? x) (noninteger-error who x)) - (let ([y (fl* ($flfloor (fl/ x 2.0)) 2.0)]) - (cond - [(fl= x y) #f] - [(fl= (fl+ y 1.0) x) #t] - [else (noninteger-error who x)])))) - -(set-who! flmin - (let ([$flmin (lambda (x y) (if (or (fl< x y) ($nan? x)) x y))]) - (case-lambda - [(x y) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - ($flmin x y)] - [(x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - x] - [(x y . r) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - (let loop ([x ($flmin x y)] [r r]) - (if (null? r) - x - (let ([y (car r)]) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - (loop ($flmin x y) (cdr r)))))]))) - -(set-who! flmax - (let ([$flmax (lambda (x y) (if (or (fl> x y) ($nan? x)) x y))]) - (case-lambda - [(x y) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - ($flmax x y)] - [(x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - x] - [(x y . r) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - (let loop ([x ($flmax x y)] [r r]) - (if (null? r) - x - (let ([y (car r)]) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - (loop ($flmax x y) (cdr r)))))]))) - -(set-who! flnumerator - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (cond - [($flinteger-or-inf? x) x] - [($nan? x) x] - [else (inexact (numerator (exact x)))]))) - -(set-who! fldenominator - (lambda (x) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (cond - [($flinteger-or-inf? x) 1.0] - [($nan? x) x] - [else (inexact (denominator (exact x)))]))) - -(set-who! fldiv-and-mod - (lambda (x y) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - ($fldiv-and-mod x y))) - -(set-who! fldiv - (lambda (x y) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - ($fldiv x y))) - -(set-who! flmod - (lambda (x y) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - ($flmod x y))) - -(set-who! fldiv0-and-mod0 - (lambda (x y) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - ($fldiv0-and-mod0 x y))) - -(set-who! fldiv0 - (lambda (x y) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - ($fldiv0 x y))) - -(set-who! flmod0 - (lambda (x y) - (unless (flonum? x) ($oops who "~s is not a flonum" x)) - (unless (flonum? y) ($oops who "~s is not a flonum" y)) - ($flmod0 x y))) - -(set-who! fxdiv-and-mod - (lambda (x y) - (unless (fixnum? x) ($oops who "~s is not a fixnum" x)) - (unless (fixnum? y) ($oops who "~s is not a fixnum" y)) - (when (fx= y 0) (domain-error who y)) - ($fxdiv-and-mod x y who))) - -(set-who! fxdiv - (lambda (x y) - (unless (fixnum? x) ($oops who "~s is not a fixnum" x)) - (unless (fixnum? y) ($oops who "~s is not a fixnum" y)) - (when (fx= y 0) (domain-error who y)) - ($fxdiv x y who))) - -(set-who! fxmod - (lambda (x y) - (unless (fixnum? x) ($oops who "~s is not a fixnum" x)) - (unless (fixnum? y) ($oops who "~s is not a fixnum" y)) - (when (fx= y 0) (domain-error who y)) - ($fxmod x y))) - -(set-who! fxdiv0-and-mod0 - (lambda (x y) - (unless (fixnum? x) ($oops who "~s is not a fixnum" x)) - (unless (fixnum? y) ($oops who "~s is not a fixnum" y)) - (when (fx= y 0) (domain-error who y)) - ($fxdiv0-and-mod0 x y who))) - -(set-who! fxdiv0 - (lambda (x y) - (unless (fixnum? x) ($oops who "~s is not a fixnum" x)) - (unless (fixnum? y) ($oops who "~s is not a fixnum" y)) - (when (fx= y 0) (domain-error who y)) - ($fxdiv0 x y who))) - -(set-who! fxmod0 - (lambda (x y) - (unless (fixnum? x) ($oops who "~s is not a fixnum" x)) - (unless (fixnum? y) ($oops who "~s is not a fixnum" y)) - (when (fx= y 0) (domain-error who y)) - ($fxmod0 x y))) - -(let () - (define (return n) - (if (fixnum? n) - (values n 0) - (if ($bigpositive? n) - (values (- n (expt 2 (fixnum-width))) 1) - (values (+ n (expt 2 (fixnum-width))) -1)))) - - (set-who! fx+/carry - (lambda (x y z) - (cond - [($fx+? ($fx+? x y) z) => (lambda (n) (values n 0))] - [else - (unless (fixnum? x) ($oops who "~s is not a fixnum" x)) - (unless (fixnum? y) ($oops who "~s is not a fixnum" y)) - (unless (fixnum? z) ($oops who "~s is not a fixnum" z)) - (return (+ x y z))]))) - - (set-who! fx-/carry - (lambda (x y z) - (cond - [($fx-? ($fx-? x y) z) => (lambda (n) (values n 0))] - [else - (unless (fixnum? x) ($oops who "~s is not a fixnum" x)) - (unless (fixnum? y) ($oops who "~s is not a fixnum" y)) - (unless (fixnum? z) ($oops who "~s is not a fixnum" z)) - (return (- x y z))])))) - -(set-who! fx*/carry - (lambda (x y z) - (unless (fixnum? x) ($oops who "~s is not a fixnum" x)) - (unless (fixnum? y) ($oops who "~s is not a fixnum" y)) - (let ([t (* x y)]) - (cond - [($fx+? t z) => (lambda (n) (values n 0))] - [else - (unless (fixnum? z) ($oops who "~s is not a fixnum" z)) - (let-values ([(q r) ($exdiv0-and-mod0 (+ (* x y) z) (expt 2 (fixnum-width)))]) - (values r q))])))) - -(set-who! bitwise-copy-bit-field - (lambda (n start end m) - (unless (or (fixnum? n) (bignum? n)) - ($oops who "~s is not an exact integer" n)) - (unless (or (and (fixnum? start) (fx>= start 0)) - (and (bignum? start) ($bigpositive? start))) - ($oops who "invalid start index ~s" start)) - (unless (or (and (fixnum? end) (fixnum? start) (fx>= end start)) - (and (bignum? end) (>= end start))) - ($oops who "invalid end index ~s" end)) - (unless (or (fixnum? m) (bignum? m)) - ($oops who "~s is not an exact integer" m)) - (let ([mask (- ($sll who 1 (- end start)) 1)]) - (logor - (logand n (lognot ($sll who mask start))) - ($sll who (logand m mask) start))))) - -(set-who! bitwise-rotate-bit-field - (lambda (n start end count) - (unless (or (fixnum? n) (bignum? n)) - ($oops who "~s is not an exact integer" n)) - (unless (or (and (fixnum? start) (fx>= start 0)) - (and (bignum? start) ($bigpositive? start))) - ($oops who "invalid start index ~s" start)) - (unless (or (and (fixnum? end) (fixnum? start) (fx>= end start)) - (and (bignum? end) (>= end start))) - ($oops who "invalid end index ~s" end)) - (unless (or (and (fixnum? count) (fx>= count 0)) - (and (bignum? count) ($bigpositive? count))) - ($oops who "invalid count ~s" count)) - (let ([width (- end start)]) - (if (positive? width) - (let ([count (mod count width)] - [mask ($sll who (- ($sll who 1 width) 1) start)]) - (let ([field (logand n mask)]) - (logxor - (logxor - (logand - (logor ($sll who field count) - ($sra who field (- width count))) - mask) - field) - n))) - n)))) - -(set-who! fxrotate-bit-field - (lambda (n start end count) - (unless (fixnum? n) ($oops who "~s is not a fixnum" n)) - (unless (and (fixnum? end) ($fxu< end (fixnum-width))) - ($oops who "invalid end index ~s" end)) - (unless (and (fixnum? start) (not ($fxu< end start))) - (if (and (fixnum? start) ($fxu< start (fixnum-width))) - ($oops who "start index ~s is greater than end index ~s" start end) - ($oops who "invalid start index ~s" start))) - (let ([width (fx- end start)]) - (unless (and (fixnum? count) (not ($fxu< width count))) - (if (and (fixnum? count) ($fxu< count (fixnum-width))) - ($oops who "count ~s is greater than difference between end index ~s and start index ~s" count end start) - ($oops who "invalid count ~s" count))) - (let ([mask (fxsll (fxsrl -1 (fx- (fixnum-width) width)) start)]) - (let ([field (fxlogand n mask)]) - (fxlogor - (fxlogxor n field) - (fxlogand - (fxlogor - (fxsll (fxlogand field (fxsrl mask count)) count) - (fxsrl field (fx- width count))) - mask))))))) - -(let () - (define rev-table - (let () - (define-syntax make-rev-table - (lambda (x) - #`'#,(let ([bv (make-bytevector 256)]) - (for-each - (lambda (m) - (bytevector-u8-set! bv m - (do ([m m (fxsrl m 1)] - [m^ 0 (fxior (fxsll m^ 1) (fxand m 1))] - [k 8 (fx- k 1)]) - ((fx= k 0) m^)))) - (iota 256)) - bv))) - (make-rev-table))) - - (define $fxreverse - (lambda (m k) - (do ([m m (fxsrl m 8)] - [m^ 0 (fxior (fxsll m^ 8) (bytevector-u8-ref rev-table (fxand m #xff)))] - [k k (fx- k 8)]) - ((fx< k 8) - (fxior - (fxsll m^ k) - (fxsrl (bytevector-u8-ref rev-table m) (fx- 8 k))))))) - - (set-who! fxreverse-bit-field - (lambda (n start end) - (unless (fixnum? n) ($oops who "~s is not a fixnum" n)) - (unless (and (fixnum? start) ($fxu< start (fixnum-width))) - ($oops who "invalid start index ~s" start)) - (unless (and (fixnum? end) ($fxu< end (fixnum-width))) - ($oops who "invalid end index ~s" end)) - (unless (fx<= start end) - ($oops who "start index ~s is greater than end index ~s" start end)) - (fxcopy-bit-field n start end - ($fxreverse (fxbit-field n start end) (fx- end start))))) - - (set-who! bitwise-reverse-bit-field - (lambda (n start end) - (define sra bitwise-arithmetic-shift-right) - (define sll bitwise-arithmetic-shift-left) - (define w-1 (fx- (fixnum-width) 1)) - (define mask (- (sll 1 w-1) 1)) - (unless (or (fixnum? n) (bignum? n)) - ($oops who "~s is not an exact integer" n)) - (unless (or (and (fixnum? start) (fx>= start 0)) - (and (bignum? start) ($bigpositive? start))) - ($oops who "invalid start index ~s" start)) - (unless (or (and (fixnum? end) (fx>= end 0)) - (and (bignum? end) ($bigpositive? end))) - ($oops who "invalid end index ~s" end)) - (unless (<= start end) - ($oops who "start index ~s is greater than end index ~s" start end)) - (bitwise-copy-bit-field n start end - (do ([m (bitwise-bit-field n start end) (sra m w-1)] - [m^ 0 (logor (sll m^ w-1) ($fxreverse (logand m mask) w-1))] - [k (- end start) (- k w-1)]) - ((<= k w-1) (logor (sll m^ k) ($fxreverse m k)))))))) -))))))) -) diff --git a/ta6ob/s/5_3.ta6ob b/ta6ob/s/5_3.ta6ob deleted file mode 100644 index fafd90c..0000000 Binary files a/ta6ob/s/5_3.ta6ob and /dev/null differ diff --git a/ta6ob/s/5_4.ss b/ta6ob/s/5_4.ss deleted file mode 100644 index 37dacbf..0000000 --- a/ta6ob/s/5_4.ss +++ /dev/null @@ -1,833 +0,0 @@ -;;; 5_4.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; character and string functions - -(begin -(define substring - (lambda (s1 m n) - (unless (string? s1) - ($oops 'substring "~s is not a string" s1)) - (let ([k (string-length s1)]) - (unless (and (fixnum? m) (fixnum? n) (fx<= 0 m n k)) - ($oops 'substring - "~s and ~s are not valid start/end indices for ~s" - m n s1)) - (let ([s2 (make-string (fx- n m))]) - (do ([j 0 (fx+ j 1)] [i m (fx+ i 1)]) - ((fx= i n) s2) - (string-set! s2 j (string-ref s1 i))))))) - -(define-who string-append - (case-lambda - [(s1 s2) - (unless (string? s1) ($oops who "~s is not a string" s1)) - (unless (string? s2) ($oops who "~s is not a string" s2)) - (let ([n1 (string-length s1)] [n2 (string-length s2)]) - (let ([n (+ n1 n2)]) - (unless (fixnum? n) ($oops who "result string size ~s is not a fixnum" n)) - (let ([s (make-string n)]) - (string-copy! s1 0 s 0 n1) - (string-copy! s2 0 s n1 n2) - s)))] - [args - (let f ([ls args] [n 0]) - (if (null? ls) - (if (fixnum? n) - (make-string n) - ($oops who "result string size ~s is not a fixnum" n)) - (let ([s1 (car ls)]) - (unless (string? s1) ($oops who "~s is not a string" s1)) - (let ([m (string-length s1)]) - (let ([s2 (f (cdr ls) (+ n m))]) - (string-copy! s1 0 s2 n m) - s2)))))])) - -(define string->list - (lambda (s) - (unless (string? s) - ($oops 'string->list "~s is not a string" s)) - (let loop ([i (fx- (string-length s) 1)] [l '()]) - (if (fx> i 0) - (loop (fx- i 2) - (list* (string-ref s (fx- i 1)) - (string-ref s i) - l)) - (if (fx= i 0) - (cons (string-ref s 0) l) - l))))) - -(define list->string - (lambda (x) - (let ([s (make-string ($list-length x 'list->string))]) - (do ([ls x (cdr ls)] [i 0 (fx+ i 1)]) - ((null? ls) s) - (let ([c (car ls)]) - (unless (char? c) - ($oops 'list->string "~s is not a character" c)) - (string-set! s i c)))))) - -(define-who string-copy - (lambda (s1) - (unless (string? s1) - ($oops who "~s is not a string" s1)) - (let ([n (string-length s1)]) - (let ([s2 (make-string n)]) - ($byte-copy! - s1 (constant string-data-disp) - s2 (constant string-data-disp) - (fx* n (constant string-char-bytes))) - s2)))) - -(define-who string-copy! - (lambda (s1 i1 s2 i2 k) - (unless (string? s1) ($oops who "~s is not a string" s1)) - (unless (mutable-string? s2) ($oops who "~s is not a mutable string" s2)) - (let ([n1 (string-length s1)] [n2 (string-length s2)]) - (unless (and (fixnum? i1) (fx>= i1 0)) - ($oops who "invalid start value ~s" i1)) - (unless (and (fixnum? i2) (fx>= i2 0)) - ($oops who "invalid start value ~s" i2)) - (unless (and (fixnum? k) (fx>= k 0)) - ($oops who "invalid count ~s" k)) - (unless (fx<= k (fx- n1 i1)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" i1 k s1)) - (unless (fx<= k (fx- n2 i2)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" i2 k s2)) - ; whew! - (#3%string-copy! s1 i1 s2 i2 k)))) - -(set-who! string->immutable-string - (lambda (v) - (cond - [(immutable-string? v) v] - [(eqv? v "") ($tc-field 'null-immutable-string ($tc))] - [else - (unless (string? v) ($oops who "~s is not a string" v)) - (let ([v2 (string-copy v)]) - ($string-set-immutable! v2) - v2)]))) - -(define-who substring-fill! - (lambda (s m n c) - (unless (mutable-string? s) - ($oops who "~s is not a mutable string" s)) - (unless (char? c) - ($oops who "~s is not a character" c)) - (let ([k (string-length s)]) - (unless (and (fixnum? m) (fixnum? n) (fx<= 0 m n k)) - ($oops who - "~s and ~s are not valid start/end indices for ~s" - m n s)) - (do ([i m (fx+ i 1)]) - ((fx= i n)) - (string-set! s i c))))) - -(set! string-for-each - (case-lambda - [(p s) - (unless (procedure? p) ($oops 'string-for-each "~s is not a procedure" p)) - (unless (string? s) ($oops 'string-for-each "~s is not a string" s)) - (#3%string-for-each p s)] - [(p s t) - (unless (procedure? p) ($oops 'string-for-each "~s is not a procedure" p)) - (unless (string? s) ($oops 'string-for-each "~s is not a string" s)) - (unless (string? t) ($oops 'string-for-each "~s is not a string" t)) - (let ([n (string-length s)]) - (unless (fx= (string-length t) n) - ($oops 'string-for-each "lengths of input string ~s and ~s differ" s t)) - (unless (fx= n 0) - (let loop ([i 0]) - (let ([j (fx+ i 1)]) - (if (fx= j n) - (p (string-ref s i) (string-ref t i)) - (begin - (p (string-ref s i) (string-ref t i)) - (loop j)))))))] - [(p s . t*) - (unless (procedure? p) ($oops 'string-for-each "~s is not a procedure" p)) - (unless (string? s) ($oops 'string-for-each "~s is not a string" s)) - (for-each (lambda (t) (unless (string? t) ($oops 'string-for-each "~s is not a string" t))) t*) - (let ([n (string-length s)]) - (for-each - (lambda (t) - (unless (fx= (string-length t) n) - ($oops 'string-for-each "lengths of input string ~s and ~s differ" s t))) - t*) - (unless (fx= n 0) - (let loop ([i 0]) - (let ([j (fx+ i 1)]) - (if (fx= j n) - (apply p (string-ref s i) (map (lambda (t) (string-ref t i)) t*)) - (begin - (apply p (string-ref s i) (map (lambda (t) (string-ref t i)) t*)) - (loop j)))))))])) - -;;; The following code is covered by the following copyright/license. - -;;; Copyright (C) 2008 Abdulaziz Ghuloum, R. Kent Dybvig -;;; Copyright (C) 2006,2007 Abdulaziz Ghuloum -;;; -;;; Permission is hereby granted, free of charge, to any person obtaining a -;;; copy of this software and associated documentation files (the "Software"), -;;; to deal in the Software without restriction, including without limitation -;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, -;;; and/or sell copies of the Software, and to permit persons to whom the -;;; Software is furnished to do so, subject to the following conditions: -;;; -;;; The above copyright notice and this permission notice shall be included in -;;; all copies or substantial portions of the Software. -;;; -;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -;;; DEALINGS IN THE SOFTWARE. - -(let () - (include "../unicode/unicode-char-cases.ss") - (include "../unicode/unicode-charinfo.ss") - - (define char-error - (lambda (who what) - ($oops who "~s is not a character" what))) - - (define string-error - (lambda (who what) - ($oops who "~s is not a string" what))) - - (set! $string-char-foldcase (lambda (c) ($str-foldcase c))) - - (let () - (define-syntax define-char-op - (syntax-rules () - [(_ name unsafe-op) - (set-who! name - (lambda (c) - (if (char? c) - (unsafe-op c) - ($oops who "~s is not a character" c))))])) - - (define-char-op char-upcase $char-upcase) - (define-char-op char-downcase $char-downcase) - (define-char-op char-titlecase $char-titlecase) - (define-char-op char-foldcase $char-foldcase) - (define-char-op char-whitespace? $char-whitespace?) - (define-char-op char-lower-case? $char-lower-case?) - (define-char-op char-upper-case? $char-upper-case?) - (define-char-op char-title-case? $char-title-case?) - (define-char-op char-numeric? $char-numeric?) - (define-char-op char-alphabetic? $char-alphabetic?) - (define-char-op char-general-category $char-category) - (define-char-op $constituent? $char-constituent?) - (define-char-op $subsequent? $char-subsequent?) - ) - - (let () - (define (check-chars who ls) - (let loop ([ls ls]) - (and (not (null? ls)) - (let ([x (car ls)]) - (if (char? x) - (loop (cdr ls)) - (char-error who x)))))) - - (define-syntax char-relop - (lambda (x) - (syntax-case x () - [(_ name filter) #'(char-relop name name filter)] - [(_ name pred filter) - (let () - (define (foo xname onearg) - #`(set-who! #,xname - (case-lambda - [(x1 x2) - (if (char? x1) - (if (char? x2) - (#3%pred (filter x1) (filter x2)) - (char-error who x2)) - (char-error who x1))] - [(x1 x2 x3) - (if (char? x1) - (if (char? x2) - (if (char? x3) - (let ([x2 (filter x2)]) - (and (#3%pred (filter x1) x2) - (#3%pred x2 (filter x3)))) - (char-error who x3)) - (char-error who x2)) - (char-error who x1))] - #,@(if onearg (list onearg) '()) - [(x1 x2 . rest) - (if (char? x1) - (let loop ([x1 (filter x1)] [x2 x2] [ls rest]) - (if (char? x2) - (let ([x2 (filter x2)]) - (if (#3%pred x1 x2) - (or (null? ls) (loop x2 (car ls) (cdr ls))) - (check-chars who ls))) - (char-error who x2))) - (char-error who x1))]))) - #`(begin - #,(foo #'#(r6rs: name) #f) - #,(foo #'name #'[(x) (if (char? x) #t (char-error who x))])))]))) - - (char-relop char=? values) - (char-relop char>? values) - - (char-relop char-ci=? char>=? $char-foldcase) - (char-relop char-ci>? char>? $char-foldcase) - ) - - (let () - (define (handle-special str ac) - (define (chars ac n) - (cond - [(null? ac) n] - [else - (chars (cdr ac) - (let f ([p (cdar ac)] [n n]) - (cond - [(pair? p) (f (cdr p) (fx+ n 1))] - [else n])))])) - (define (extend src ac src-len dst-len) - (let f ([str str] [dst (make-string dst-len)] [i 0] [j 0] [ac (reverse ac)] [sigma* '()]) - (cond - [(null? ac) - (string-copy! str i dst j (fx- src-len i)) - (do-sigmas dst sigma*)] - [else - (let ([idx (caar ac)] [c* (cdar ac)] [ac (cdr ac)]) - (let ([cnt (fx- idx i)]) - (string-copy! str i dst j cnt) - (let g ([str str] [dst dst] - [i (fx+ i cnt)] [j (fx+ j cnt)] - [ac ac] [c* c*]) - (cond - [(pair? c*) - (string-set! dst j (car c*)) - (g str dst i (fx+ j 1) ac (cdr c*))] - [(char? c*) - (string-set! dst j c*) - (f str dst (fx+ i 1) (fx+ j 1) ac sigma*)] - [else ; assume c* = sigma - (f str dst (fx+ i 1) (fx+ j 1) ac (cons j sigma*))]))))]))) - (define (do-sigmas str sigma*) - (define nonfinal-sigma #\x3c3) - (define final-sigma #\x3c2) - (define (final? i) - (define (scan i incr n) - (and (not (fx= i n)) - (or ($char-cased? (string-ref str i)) - (and ($char-case-ignorable? (string-ref str i)) - (scan (fx+ i incr) incr n))))) - (and (scan (fx- i 1) -1 -1) (not (scan (fx+ i 1) +1 (string-length str))))) - ; scanning requires we have some character in place...guess nonfinal sigma - (for-each (lambda (i) (string-set! str i nonfinal-sigma)) sigma*) - (for-each (lambda (i) (when (final? i) (string-set! str i final-sigma))) sigma*) - str) - (let* ([src-len (string-length str)] - [dst-len (chars ac src-len)]) - (if (fx= dst-len src-len) - (do-sigmas str (map car ac)) - (extend str ac src-len dst-len)))) - - (define (string-change-case str cvt-char) - (let ([n (string-length str)]) - (let f ([str str] [dst (make-string n)] [i 0] [n n] [ac '()]) - (cond - [(fx= i n) - (if (null? ac) - dst - (handle-special dst ac))] - [else - (let ([c/ls (cvt-char (string-ref str i))]) - (cond - [(char? c/ls) - (string-set! dst i c/ls) - (f str dst (fx+ i 1) n ac)] - [else - (f str dst (fx+ i 1) n - (cons (cons i c/ls) ac))]))])))) - - (set-who! string-upcase - (lambda (s) - (unless (string? s) (string-error who s)) - (string-change-case s $str-upcase))) - - (set-who! string-foldcase - (lambda (s) - (unless (string? s) (string-error who s)) - (string-change-case s $str-foldcase))) - - (set-who! string-downcase - (lambda (s) - (unless (string? s) (string-error who s)) - (string-change-case s $str-downcase))) - - (set-who! string-titlecase - (lambda (str) - (unless (string? str) (string-error who str)) - (let* ([n (string-length str)] [dst (make-string n)]) - (define (trans2 s i seen-cased? ac) - (if (fx= i n) - (handle-special dst ac) - (s i seen-cased? ac))) - (define (trans1 s i c/ls seen-cased? ac) - (cond - [(char? c/ls) - (string-set! dst i c/ls) - (trans2 s (fx+ i 1) seen-cased? ac)] - [else - (trans2 s (fx+ i 1) seen-cased? (cons (cons i c/ls) ac))])) - (define (trans s i c seen-cased? ac) - (if seen-cased? - (trans1 s i ($str-downcase c) #t ac) - (if ($char-cased? c) - (trans1 s i ($str-titlecase c) #t ac) - (trans1 s i c #f ac)))) - ; NB: if used as a pattern for word breaking, take care not to break between CR & LF (WB3) - ; NB: and between regional-indicators (WB13c). also take care not to let handling of WB6 and - ; NB: WB7 here prevent breaks in, e.g., "a." when not followed by, e.g., another letter. - (define (s0 i ac) - (let ([c (string-ref str i)]) - (cond - [($wb-aletter? c) (trans sAletter i c #f ac)] - [($wb-hebrew-letter? c) (trans sHebrewletter i c #f ac)] - [($wb-numeric? c) (trans sNumeric i c #f ac)] - [($wb-katakana? c) (trans sKatakana i c #f ac)] - [($wb-extendnumlet? c) (trans sExtendnumlet i c #f ac)] - [($wb-regional-indicator? c) (trans sRegionalIndicator i c #f ac)] - [else (string-set! dst i c) - (let ([i (fx+ i 1)]) - (if (fx= i n) - (handle-special dst ac) - (s0 i ac)))]))) - (define (extend-format-zwj? c) (or ($wb-extend? c) ($wb-format? c) ($wb-zwj? c))) - (define (sAletter i seen-cased? ac) - (let ([c (string-ref str i)]) - (cond - [($wb-aletter? c) (trans sAletter i c seen-cased? ac)] ; WB5 - [($wb-hebrew-letter? c) (trans sHebrewletter i c seen-cased? ac)] ; WB5 - [(or ($wb-midletter? c) ($wb-midnumlet? c) ($wb-single-quote? c)) (trans sWB6/WB7/WB7a i c seen-cased? ac)] ; WB6/WB7 - [($wb-numeric? c) (trans sNumeric i c seen-cased? ac)] ; WB9 - [($wb-extendnumlet? c) (trans sExtendnumlet i c seen-cased? ac)] ; WB13a - [(extend-format-zwj? c) (trans sAletter i c seen-cased? ac)] ; WB4 - [else (s0 i ac)]))) ; WB14 - (define (sHebrewletter i seen-cased? ac) - (let ([c (string-ref str i)]) - (cond - [($wb-aletter? c) (trans sAletter i c seen-cased? ac)] ; WB5 - [($wb-hebrew-letter? c) (trans sHebrewletter i c seen-cased? ac)] ; WB5 - [(or ($wb-midletter? c) ($wb-midnumlet? c) ($wb-single-quote? c)) (trans sWB6/WB7/WB7a i c seen-cased? ac)] ; WB6/WB7/WB7a - [($wb-double-quote? c) (trans sWB7b/WB7c i c seen-cased? ac)] ; WB7b, WB7c - [($wb-numeric? c) (trans sNumeric i c seen-cased? ac)] ; WB9 - [($wb-extendnumlet? c) (trans sExtendnumlet i c seen-cased? ac)] ; WB13a - [(extend-format-zwj? c) (trans sHebrewletter i c seen-cased? ac)] ; WB4 - [else (s0 i ac)]))) ; WB14 - (define (sWB6/WB7/WB7a i seen-cased? ac) - (let ([c (string-ref str i)]) - (cond - [($wb-aletter? c) (trans sAletter i c seen-cased? ac)] ; WB6, WB7 - [($wb-hebrew-letter? c) (trans sHebrewletter i c seen-cased? ac)] ; WB6, WB7 - [(extend-format-zwj? c) (trans sWB6/WB7/WB7a i c seen-cased? ac)] ; WB4 - ; word break actually should/could have occurred one character earlier if we got here - ; from sAletter rather than sHebrewletter but that was before a midlet, midnumlet, or single - ; quote which has no titlecase - [else (s0 i ac)]))) ; WB14 - (define (sWB7b/WB7c i seen-cased? ac) - (let ([c (string-ref str i)]) - (cond - [($wb-hebrew-letter? c) (trans sHebrewletter i c seen-cased? ac)] ; WB7b, WB7c - [(extend-format-zwj? c) (trans sWB7b/WB7c i c seen-cased? ac)] ; WB4 - ; word break actually should/could have occurred one character earlier - ; but that was before a double quote which has no titlecase - [else (s0 i ac)]))) ; WB14 - (define (sSingleQuote i seen-cased? ac) - (let ([c (string-ref str i)]) - (cond - [($wb-aletter? c) (trans sAletter i c seen-cased? ac)] ; finishing WB6, WB7 - [($wb-hebrew-letter? c) (trans sHebrewletter i c seen-cased? ac)] ; finishing WB6, WB7 - [(extend-format-zwj? c) (trans sSingleQuote i c seen-cased? ac)] ; WB4 - [else (s0 i ac)]))) ; WB14 - (define (sNumeric i seen-cased? ac) - (let ([c (string-ref str i)]) - (cond - [($wb-numeric? c) (trans sNumeric i c seen-cased? ac)] ; WB8 - [($wb-aletter? c) (trans sAletter i c seen-cased? ac)] ; WB10 - [($wb-hebrew-letter? c) (trans sHebrewletter i c seen-cased? ac)] ; WB10 - [(or ($wb-midnum? c) ($wb-midnumlet? c) ($wb-single-quote? c)) (trans sWB11/WB12 i c seen-cased? ac)] ; WB11, WB12 - [($wb-extendnumlet? c) (trans sExtendnumlet i c seen-cased? ac)] - [(extend-format-zwj? c) (trans sNumeric i c seen-cased? ac)] ; WB4 - [else (s0 i ac)]))) ; WB14 - (define (sWB11/WB12 i seen-cased? ac) - (let ([c (string-ref str i)]) - (cond - [($wb-numeric? c) (trans sNumeric i c seen-cased? ac)] - [(extend-format-zwj? c) (trans sWB11/WB12 i c seen-cased? ac)] ; WB4 - ; word break actually should/could have occurred one character earlier - ; but that was before a midnum, midnumlet, or single quote which has no titltecase - [else (s0 i ac)]))) ; WB14 - (define (sKatakana i seen-cased? ac) - (let ([c (string-ref str i)]) - (cond - [($wb-katakana? c) (trans sKatakana i c seen-cased? ac)] ; WB13 - [($wb-extendnumlet? c) (trans sExtendnumlet i c seen-cased? ac)] ; WB13a - [(extend-format-zwj? c) (trans sKatakana i c seen-cased? ac)] ; WB4 - [else (s0 i ac)]))) ; WB14 - (define (sExtendnumlet i seen-cased? ac) - (let ([c (string-ref str i)]) - (cond - [($wb-extendnumlet? c) (trans sExtendnumlet i c seen-cased? ac)] ; WB13a - [($wb-aletter? c) (trans sAletter i c seen-cased? ac)] ; WB13b - [($wb-hebrew-letter? c) (trans sHebrewletter i c seen-cased? ac)] ; WB13b - [($wb-numeric? c) (trans sNumeric i c seen-cased? ac)] ; WB13b - [($wb-katakana? c) (trans sKatakana i c seen-cased? ac)] ; WB13b - [(extend-format-zwj? c) (trans sExtendnumlet i c seen-cased? ac)] ; WB4 - [else (s0 i ac)]))) ; WB14 - (define (sRegionalIndicator i seen-cased? ac) - (let ([c (string-ref str i)]) - (cond - [($wb-regional-indicator? c) (trans sRegionalIndicator i c seen-cased? ac)] ; WB13c - [(extend-format-zwj? c) (trans sExtendnumlet i c seen-cased? ac)] ; WB4 - [else (s0 i ac)]))) ; WB14 - (if (fx= n 0) dst (s0 0 '()))))) - ) - - (let () - (define-syntax string-relop - (syntax-rules () - [(_ (name x1 x2) pred) - (set! name - (rec name - (case-lambda - [(x1 x2) - (if (string? x1) - (if (string? x2) - pred - (string-error 'name x2)) - (string-error 'name x1))] - [(x1) (begin (name x1 "") #t)] - [(x1 x2 . rest) - (let loop ([x1 x1] [x2 x2] [ls rest]) - (if (or (null? ls) (loop x2 (car ls) (cdr ls))) - (name x1 x2) - (begin (name x1 x2) #f)))])))])) - - (define-syntax r6rs:string-relop - (syntax-rules () - [(_ (name x1 x2) pred) - (set-who! #(r6rs: name) ; implies (rec name ---) - (case-lambda - [(x1 x2) - (if (string? x1) - (if (string? x2) - pred - (string-error 'name x2)) - (string-error 'name x1))] - [(x1 x2 . rest) - (let loop ([x1 x1] [x2 x2] [ls rest]) - (if (or (null? ls) (loop x2 (car ls) (cdr ls))) - (name x1 x2) - (begin (name x1 x2) #f)))]))])) - - (define string-equal? - (lambda (s1 s2) - (or (eq? s1 s2) - (let ([n (string-length s1)]) - (and (fx= n (string-length s2)) - (let f ([i 0]) - (or (fx= i n) - (and (char=? (string-ref s1 i) (string-ref s2 i)) - (f (fx+ i 1)))))))))) - - (define string-less? - (lambda (s1 s2) - (and (not (eq? s1 s2)) - (let ([n1 (string-length s1)] [n2 (string-length s2)]) - (let f ([i 0]) - (and (not (fx= i n2)) - (or (fx= i n1) - (let ([c1 (string-ref s1 i)] - [c2 (string-ref s2 i)]) - (or (char? x1 x2) (string-less? x2 x1)) - (string-relop (string<=? x1 x2) (not (string-less? x2 x1))) - (string-relop (string>=? x1 x2) (not (string-less? x1 x2))) - - (string-relop (string-ci=? x1 x2) (string-ci-equal? x1 x2)) - (string-relop (string-ci? x1 x2) (string-ci-less? x2 x1)) - (string-relop (string-ci<=? x1 x2) (not (string-ci-less? x2 x1))) - (string-relop (string-ci>=? x1 x2) (not (string-ci-less? x1 x2))) - - (r6rs:string-relop (string=? x1 x2) (string-equal? x1 x2)) - (r6rs:string-relop (string? x1 x2) (string-less? x2 x1)) - (r6rs:string-relop (string<=? x1 x2) (not (string-less? x2 x1))) - (r6rs:string-relop (string>=? x1 x2) (not (string-less? x1 x2))) - - (r6rs:string-relop (string-ci=? x1 x2) (string-ci-equal? x1 x2)) - (r6rs:string-relop (string-ci? x1 x2) (string-ci-less? x2 x1)) - (r6rs:string-relop (string-ci<=? x1 x2) (not (string-ci-less? x2 x1))) - (r6rs:string-relop (string-ci>=? x1 x2) (not (string-ci-less? x1 x2))) - ) - - (let () - (module (hangul-sbase hangul-slimit $hangul-decomp - hangul-lbase hangul-llimit - hangul-vbase hangul-vlimit - hangul-tbase hangul-tlimit - hangul-vcount hangul-tcount) - ; adapted from UAX #15 - (define SBase #xAC00) - (define LBase #x1100) - (define VBase #x1161) - (define TBase #x11A7) - (define LCount 19) - (define VCount 21) - (define TCount 28) - (define NCount (* VCount TCount)) - (define SCount (* LCount NCount)) - (define hangul-sbase (integer->char SBase)) - (define hangul-slimit (integer->char (+ SBase SCount -1))) - (define hangul-lbase (integer->char LBase)) - (define hangul-llimit (integer->char (+ LBase LCount -1))) - (define hangul-vbase (integer->char VBase)) - (define hangul-vlimit (integer->char (+ VBase VCount -1))) - (define hangul-tbase (integer->char TBase)) - (define hangul-tlimit (integer->char (+ TBase TCount -1))) - (define hangul-vcount VCount) - (define hangul-tcount TCount) - (define ($hangul-decomp c) - (let ([SIndex (char- c hangul-sbase)]) - (let ([L (integer->char (fx+ LBase (fxdiv SIndex NCount)))] - [V (integer->char (fx+ VBase (fxdiv (fxmod SIndex NCount) TCount)))] - [adj (fxmod SIndex TCount)]) - (if (fx= adj 0) - (cons* L V) - (cons* L V (integer->char (fx+ TBase adj)))))))) - - (define $decompose - ; might should optimize for sequences of ascii characters - (lambda (s canonical?) - (let ([n (string-length s)] [ac '()]) - (define (canonical>? c1 c2) - (fx> ($char-combining-class c1) ($char-combining-class c2))) - (define (sort-and-flush comb*) - (unless (null? comb*) - (set! ac (append (list-sort canonical>? comb*) ac)))) - (define ($char-decomp c) - (if (and (char<=? hangul-sbase c) (char<=? c hangul-slimit)) - ($hangul-decomp c) - (if canonical? - ($str-decomp-canon c) - ($str-decomp-compat c)))) - (define (push-and-go c* c** i comb*) - (if (char? c*) - (go c* c** i comb*) - (go (car c*) (cons (cdr c*) c**) i comb*))) - (define (pop-and-go c** i comb*) - (if (null? c**) - (if (fx= i n) - (sort-and-flush comb*) - (go (string-ref s i) '() (fx+ i 1) comb*)) - (push-and-go (car c**) (cdr c**) i comb*))) - (define (go c c** i comb*) - (let ([c* ($char-decomp c)]) - (if (eq? c c*) ; should be eqv? - (if (fxzero? ($char-combining-class c)) - (begin - (sort-and-flush comb*) - (set! ac (cons c ac)) - (pop-and-go c** i '())) - (pop-and-go c** i (cons c comb*))) - (push-and-go c* c** i comb*)))) - (pop-and-go '() 0 '()) - (list->string (reverse ac))))) - - (define $compose - (let ([comp-table #f]) - (define (lookup-composite c1 c2) - (hashtable-ref comp-table (cons c1 c2) #f)) - (define (init!) - (set! comp-table - (make-hashtable - (lambda (x) - (fxxor - (fxsll (char->integer (car x)) 7) - (char->integer (cdr x)))) - (lambda (x y) - (and (char=? (car x) (car y)) - (char=? (cdr x) (cdr y)))))) - (vector-for-each - (lambda (c* c) (hashtable-set! comp-table c* c)) - (car ($composition-pairs)) - (cdr ($composition-pairs)))) - (lambda (s) - (unless comp-table (init!)) - (let ([ac '()] [n (string-length s)]) - (define (dump c acc) - (set! ac (cons c ac)) - (unless (null? acc) (set! ac (append acc ac)))) - (define (s0 i) - (unless (fx= i n) - (let ([c (string-ref s i)]) - (if (fxzero? ($char-combining-class c)) - (s1 (fx+ i 1) c) - (begin (set! ac (cons c ac)) (s0 (fx+ i 1))))))) - (define (s1 i c) - (if (fx= i n) - (set! ac (cons c ac)) - (let ([c1 (string-ref s i)]) - (cond - [(and (and (char<=? hangul-lbase c) - (char<=? c hangul-llimit)) - (and (char<=? hangul-vbase c1) - (char<=? c1 hangul-vlimit))) - (s1 (fx+ i 1) - (let ([lindex (char- c hangul-lbase)] - [vindex (char- c1 hangul-vbase)]) - (integer->char - (fx+ (char->integer hangul-sbase) - (fx* (fx+ (fx* lindex hangul-vcount) vindex) - hangul-tcount)))))] - [(and (and (char<=? hangul-sbase c) - (char<=? c hangul-slimit)) - (and (char<=? hangul-tbase c1) - (char<=? c1 hangul-tlimit)) - (let ([sindex (char- c hangul-sbase)]) - (fxzero? (fxmod sindex hangul-tcount)))) - (let ([tindex (char- c1 hangul-tbase)]) - (s1 (fx+ i 1) (integer->char (fx+ (char->integer c) tindex))))] - [else (s2 i c -1 '())])))) - (define (s2 i c class acc) - (if (fx= i n) - (dump c acc) - (let ([c1 (string-ref s i)]) - (let ([class1 ($char-combining-class c1)]) - (cond - [(and (fx< class class1) (lookup-composite c c1)) => - (lambda (c) (s2 (fx+ i 1) c class acc))] - [(fx= class1 0) - (dump c acc) - (s1 (fx+ i 1) c1)] - [else (s2 (fx+ i 1) c class1 (cons c1 acc))]))))) - (s0 0) - (list->string (reverse ac)))))) - - (set-who! string-normalize-nfd - (lambda (s) - (unless (string? s) (string-error who s)) - ($decompose s #t))) - - (set-who! string-normalize-nfkd - (lambda (s) - (unless (string? s) (string-error who s)) - ($decompose s #f))) - - (set-who! string-normalize-nfc - (lambda (s) - (unless (string? s) (string-error who s)) - ($compose ($decompose s #t)))) - - (set-who! string-normalize-nfkc - (lambda (s) - (unless (string? s) (string-error who s)) - ($compose ($decompose s #f)))) - ) -) -) diff --git a/ta6ob/s/5_4.ta6ob b/ta6ob/s/5_4.ta6ob deleted file mode 100644 index 3716d0d..0000000 Binary files a/ta6ob/s/5_4.ta6ob and /dev/null differ diff --git a/ta6ob/s/5_6.ss b/ta6ob/s/5_6.ss deleted file mode 100644 index 3f3cf96..0000000 --- a/ta6ob/s/5_6.ss +++ /dev/null @@ -1,425 +0,0 @@ -;;; 5_6.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; vector and sorting functions - -(let () -(define ($vector->list v n) - (let loop ([i (fx- n 1)] [ls '()]) - (if (fx> i 0) - (loop - (fx- i 2) - (list* (vector-ref v (fx- i 1)) (vector-ref v i) ls)) - (if (fx= i 0) (cons (vector-ref v 0) ls) ls)))) - -(define ($list->vector ls n) - (let ([v (make-vector n)]) - (let loop ([ls ls] [i 0]) - (unless (null? ls) - (vector-set! v i (car ls)) - (let ([ls (cdr ls)]) - (unless (null? ls) - (vector-set! v (fx+ i 1) (car ls)) - (loop (cdr ls) (fx+ i 2)))))) - v)) - -(define ($vector-copy! v1 v2 n) - (if (fx<= n 10) - (let loop ([i (fx- n 1)]) - (cond - [(fx> i 0) - (vector-set! v2 i (vector-ref v1 i)) - (let ([i (fx- i 1)]) (vector-set! v2 i (vector-ref v1 i))) - (loop (fx- i 2))] - [(fx= i 0) (vector-set! v2 i (vector-ref v1 i))])) - ($ptr-copy! v1 (constant vector-data-disp) v2 - (constant vector-data-disp) n))) - -(define ($vector-copy v1 n) - (let ([v2 (make-vector n)]) - ($vector-copy! v1 v2 n) - v2)) - -(set! vector->list - (lambda (v) - (unless (vector? v) - ($oops 'vector->list "~s is not a vector" v)) - ($vector->list v (vector-length v)))) - -(set! list->vector - (lambda (ls) - ($list->vector ls ($list-length ls 'list->vector)))) - -(set! vector-copy - (lambda (v) - (unless (vector? v) - ($oops 'vector-copy "~s is not a vector" v)) - ($vector-copy v (vector-length v)))) - -(set-who! vector->immutable-vector - (lambda (v) - (cond - [(immutable-vector? v) v] - [(eqv? v '#()) ($tc-field 'null-immutable-vector ($tc))] - [else - (unless (vector? v) ($oops who "~s is not a vector" v)) - (let ([v2 (vector-copy v)]) - ($vector-set-immutable! v2) - v2)]))) - -(set-who! vector-fill! - (lambda (v obj) - (unless (mutable-vector? v) ($oops who "~s is not a mutable vector" v)) - (let ([n (vector-length v)]) - (do ([i 0 (fx+ i 1)]) - ((fx= i n)) - (vector-set! v i obj))))) - -(set! fxvector->list - (lambda (v) - (unless (fxvector? v) - ($oops 'fxvector->list "~s is not an fxvector" v)) - (let loop ([i (fx- (fxvector-length v) 1)] [l '()]) - (if (fx> i 0) - (loop - (fx- i 2) - (list* (fxvector-ref v (fx- i 1)) (fxvector-ref v i) l)) - (if (fx= i 0) (cons (fxvector-ref v 0) l) l))))) - -(set! list->fxvector - (lambda (x) - (let ([v (make-fxvector ($list-length x 'list->fxvector))]) - (do ([ls x (cdr ls)] [i 0 (fx+ i 1)]) - ((null? ls) v) - (let ([n (car ls)]) - (unless (fixnum? n) - ($oops 'list->fxvector "~s is not a fixnum" n)) - (fxvector-set! v i n)))))) - -(set! fxvector-copy - (lambda (fxv1) - (unless (fxvector? fxv1) - ($oops 'fxvector-copy "~s is not an fxvector" fxv1)) - (let ([n (fxvector-length fxv1)]) - (let ([fxv2 (make-fxvector n)]) - (if (fx<= n 10) - (let loop ([i (fx- n 1)]) - (cond - [(fx> i 0) - (fxvector-set! fxv2 i (fxvector-ref fxv1 i)) - (let ([i (fx- i 1)]) (fxvector-set! fxv2 i (fxvector-ref fxv1 i))) - (loop (fx- i 2))] - [(fx= i 0) (fxvector-set! fxv2 i (fxvector-ref fxv1 i))])) - ($ptr-copy! fxv1 (constant fxvector-data-disp) fxv2 - (constant fxvector-data-disp) n)) - fxv2)))) - -(set-who! fxvector->immutable-fxvector - (lambda (v) - (cond - [(immutable-fxvector? v) v] - [(eqv? v '#vfx()) ($tc-field 'null-immutable-fxvector ($tc))] - [else - (unless (fxvector? v) ($oops who "~s is not a fxvector" v)) - (let ([v2 (fxvector-copy v)]) - ($fxvector-set-immutable! v2) - v2)]))) - -(set! vector-map - (case-lambda - [(p v) - (unless (procedure? p) ($oops 'vector-map "~s is not a procedure" p)) - (unless (vector? v) ($oops 'vector-map "~s is not a vector" v)) - (#3%vector-map p v)] - [(p u v) - (unless (procedure? p) ($oops 'vector-map "~s is not a procedure" p)) - (unless (vector? u) ($oops 'vector-map "~s is not a vector" u)) - (unless (vector? v) ($oops 'vector-map "~s is not a vector" v)) - (let ([n (vector-length u)]) - (unless (fx= (vector-length v) n) - ($oops 'vector-map "lengths of input vectors ~s and ~s differ" u v)) - (let f ([i (fx- n 1)]) - (if (fx> i 0) - (let ([x1 (p (vector-ref u i) (vector-ref v i))] - [x2 (let ([j (fx- i 1)]) - (p (vector-ref u j) (vector-ref v j)))]) - (let ([vout (f (fx- i 2))]) - (vector-set! vout i x1) - (vector-set! vout (fx- i 1) x2) - vout)) - (make-vector n - (if (fx= i 0) - (p (vector-ref u 0) (vector-ref v 0)) - 0)))))] - [(p u . v*) - (unless (procedure? p) ($oops 'vector-map "~s is not a procedure" p)) - (unless (vector? u) ($oops 'vector-map "~s is not a vector" u)) - (for-each (lambda (v) (unless (vector? v) ($oops 'vector-map "~s is not a vector" v))) v*) - (let ([n (vector-length u)]) - (for-each - (lambda (v) - (unless (fx= (vector-length v) n) - ($oops 'vector-map "lengths of input vectors ~s and ~s differ" u v))) - v*) - (let f ([i (fx- n 1)]) - (if (fx> i 0) - (let ([x1 (apply p - (vector-ref u i) - (map (lambda (v) (vector-ref v i)) v*))] - [x2 (let ([j (fx- i 1)]) - (apply p - (vector-ref u j) - (map (lambda (v) (vector-ref v j)) v*)))]) - (let ([vout (f (fx- i 2))]) - (vector-set! vout i x1) - (vector-set! vout (fx- i 1) x2) - vout)) - (make-vector n - (if (fx= i 0) - (apply p - (vector-ref u 0) - (map (lambda (v) (vector-ref v 0)) v*)) - 0)))))])) - -(set! vector-for-each - (case-lambda - [(p v) - (unless (procedure? p) ($oops 'vector-for-each "~s is not a procedure" p)) - (unless (vector? v) ($oops 'vector-for-each "~s is not a vector" v)) - (#3%vector-for-each p v)] - [(p u v) - (unless (procedure? p) ($oops 'vector-for-each "~s is not a procedure" p)) - (unless (vector? u) ($oops 'vector-for-each "~s is not a vector" u)) - (unless (vector? v) ($oops 'vector-for-each "~s is not a vector" v)) - (let ([n (vector-length u)]) - (unless (fx= (vector-length v) n) - ($oops 'vector-for-each "lengths of input vectors ~s and ~s differ" u v)) - (unless (fx= n 0) - (let loop ([i 0]) - (let ([j (fx+ i 1)]) - (if (fx= j n) - (p (vector-ref u i) (vector-ref v i)) - (begin - (p (vector-ref u i) (vector-ref v i)) - (loop j)))))))] - [(p u . v*) - (unless (procedure? p) ($oops 'vector-for-each "~s is not a procedure" p)) - (unless (vector? u) ($oops 'vector-for-each "~s is not a vector" u)) - (for-each (lambda (v) (unless (vector? v) ($oops 'vector-for-each "~s is not a vector" v))) v*) - (let ([n (vector-length u)]) - (for-each - (lambda (v) - (unless (fx= (vector-length v) n) - ($oops 'vector-for-each "lengths of input vectors ~s and ~s differ" u v))) - v*) - (unless (fx= n 0) - (let loop ([i 0]) - (let ([j (fx+ i 1)]) - (if (fx= j n) - (apply p (vector-ref u i) (map (lambda (v) (vector-ref v i)) v*)) - (begin - (apply p (vector-ref u i) (map (lambda (v) (vector-ref v i)) v*)) - (loop j)))))))])) - -(let () - (module (dovsort!) - ;; dovsort! is a modified version of Olin Shiver's code for opportunistic - ;; vector merge sort, based on a version found in the MzScheme Version 360 - ;; source code, which contains the following copyright notice. - - ;; This code is - ;; Copyright (c) 1998 by Olin Shivers. - ;; The terms are: You may do as you please with this code, as long as - ;; you do not delete this notice or hold me responsible for any outcome - ;; related to its use. - ;; - ;; Blah blah blah. Don't you think source files should contain more lines - ;; of code than copyright notice? - - ;; This merge sort is "opportunistic" -- the leaves of the merge tree are - ;; contiguous runs of already sorted elements in the vector. In the best - ;; case -- an already sorted vector -- it runs in linear time. Worst case - ;; is still O(n lg n) time. - - ;; RKD: performance is a bit worse on average than a straightforward - ;; merge-sort for random input vectors, but speed for sorted or mostly - ;; sorted vectors is much better. - - ;; RKD: The following issues with the original code have been addressed: - ;; - tail-len is bound but not used. - ;; - len is computed before it is known to be needed; it would be - ;; (marginally) better to remove the binding for len and replace - ;; (= pfxlen len) with (= pfxlen (- r l)). - ;; - In the %vector-merge-sort! loop computing pfxlen2, (fx<= j pfxlen) - ;; should be (fx<= j*2 pfxlen); otherwise pfxlen2 is actually the first - ;; power of two greater than pfxlen. Fixing this improved performance by - ;; about 20% for sort using predicate < for a list of 10^6 random - ;; integers between 0 and 1000. (pfxlen2 computation later flushed - ;; entirely; just using pfxlen, which is simpler and usually faster.) - ;; - The temp need not be a copy of the input vector, just a vector of - ;; the appropriate length. - (define (merge elt< target v1 v2 l len1 len2) - ; assumes target != v1, but v2 may be v1 or target - ; merge v1[l,l+len1-1] and v2[l+len1,l+len1+len2-1] into target[l,l+len1+len2-1] - (let* ([r1 (fx+ l len1)] [r2 (fx+ r1 len2)]) - (let lp ([i l] [j l] [x (vector-ref v1 l)] [k r1] [y (vector-ref v2 r1)]) - (if (elt< y x) - (let ([k (fx+ k 1)]) - (vector-set! target i y) - (if (fx< k r2) - (lp (fx+ i 1) j x k (vector-ref v2 k)) - (vblit v1 j target (fx+ i 1) r1))) - (let ([j (fx+ j 1)]) - (vector-set! target i x) - (if (fx< j r1) - (lp (fx+ i 1) j (vector-ref v1 j) k y) - (unless (eq? v2 target) - (vblit v2 k target (fx+ i 1) r2)))))))) - (define (vblit fromv j tov i n) - (let lp ([j j] [i i]) - (vector-set! tov i (vector-ref fromv j)) - (let ([j (fx+ j 1)]) - (unless (fx= j n) (lp j (fx+ i 1)))))) - (define (getrun elt< v l r) ; assumes l < r - (let lp ([i (fx+ l 1)] [x (vector-ref v l)]) - (if (fx= i r) - (fx- i l) - (let ([y (vector-ref v i)]) - (if (elt< y x) (fx- i l) (lp (fx+ i 1) y)))))) - (define (dovsort! elt< v0 n) - (let ([temp0 (make-vector n)]) - (define (recur l want) - ; sort v0[l,l+len-1] for some len where 0 < want <= len <= (n-l). - ; that is, sort *at least* want elements in v0 starting at index l. - ; may put the result into either v0[l,l+len-1] or temp0[l,l+len-1]. - ; does not alter either vector outside this range. returns two - ; values: the number of values sorted and the vector holding the - ; sorted values. - (let lp ([pfxlen (getrun elt< v0 l n)] [v v0] [temp temp0]) - ; v[l,l+pfxlen-1] holds a sorted version of v0[l,l+pfxlen-1] - (if (or (fx>= pfxlen want) (fx= pfxlen (fx- n l))) - (values pfxlen v) - (let-values ([(outlen outvec) (recur (fx+ l pfxlen) pfxlen)]) - (merge elt< temp v outvec l pfxlen outlen) - (lp (fx+ pfxlen outlen) temp v))))) - ; return v0 or temp0 containing sorted values - (let-values ([(outlen outvec) (recur 0 n)]) outvec)))) - - (define (dolsort elt< ls n) - (cond - [(fx= n 1) (cons (car ls) '())] - [(fx= n 2) - (let ([x (car ls)] [y (cadr ls)]) - (if (elt< y x) (list y x) (list x y)))] - [else - (let ([i (fxsrl n 1)]) - (dolmerge elt< - (dolsort elt< ls i) - (dolsort elt< (list-tail ls i) (fx- n i))))])) - - (define (dolmerge elt< ls1 ls2) - (cond - [(null? ls1) ls2] - [(null? ls2) ls1] - [(elt< (car ls2) (car ls1)) - (cons (car ls2) (dolmerge elt< ls1 (cdr ls2)))] - [else (cons (car ls1) (dolmerge elt< (cdr ls1) ls2))])) - - (define (dolsort! elt< ls n loc) - (if (fx= n 1) - (begin (set-cdr! ls '()) ls) - (let ([i (fxsrl n 1)]) - (let ([tail (list-tail ls i)]) - (dolmerge! elt< - (dolsort! elt< ls i loc) - (dolsort! elt< tail (fx- n i) loc) - loc))))) - - (define (dolmerge! elt< ls1 ls2 loc) - (let loop ([ls1 ls1] [ls2 ls2] [loc loc]) - (cond - [(null? ls1) (set-cdr! loc ls2)] - [(null? ls2) (set-cdr! loc ls1)] - [(elt< (car ls2) (car ls1)) - (set-cdr! loc ls2) - (loop ls1 (cdr ls2) ls2)] - [else (set-cdr! loc ls1) (loop (cdr ls1) ls2 ls1)])) - (cdr loc)) - - (set-who! vector-sort - (lambda (elt< v) - (unless (procedure? elt<) ($oops who "~s is not a procedure" elt<)) - (unless (vector? v) ($oops who "~s is not a vector" v)) - (let ([n (vector-length v)]) - (if (fx<= n 1) v (dovsort! elt< ($vector-copy v n) n))))) - - (set-who! vector-sort! - (lambda (elt< v) - (unless (procedure? elt<) ($oops who "~s is not a procedure" elt<)) - (unless (mutable-vector? v) ($oops who "~s is not a mutable vector" v)) - (let ([n (vector-length v)]) - (unless (fx<= n 1) - (let ([outvec (dovsort! elt< v n)]) - (unless (eq? outvec v) - ($vector-copy! outvec v n))))))) - - (set-who! list-sort - (lambda (elt< ls) - (unless (procedure? elt<) ($oops who "~s is not a procedure" elt<)) - (let ([n ($list-length ls who)]) - (if (fx< n 25) - (if (fx<= n 1) ls (dolsort elt< ls n)) - ($vector->list (dovsort! elt< ($list->vector ls n) n) n))))) - - (set-who! sort - (lambda (elt< ls) - (unless (procedure? elt<) ($oops who "~s is not a procedure" elt<)) - (let ([n ($list-length ls who)]) - (if (fx< n 25) - (if (fx<= n 1) ls (dolsort elt< ls n)) - ($vector->list (dovsort! elt< ($list->vector ls n) n) n))))) - - (set-who! merge - (lambda (elt< ls1 ls2) - (unless (procedure? elt<) - ($oops who "~s is not a procedure" elt<)) - ($list-length ls1 who) - ($list-length ls2 who) - (dolmerge elt< ls1 ls2))) - - (set-who! sort! - (lambda (elt< ls) - (unless (procedure? elt<) ($oops who "~s is not a procedure" elt<)) - (let ([n ($list-length ls who)]) - (if (fx< n 25) - (if (fx<= n 1) ls (dolsort! elt< ls n (list '()))) - (let ([v (dovsort! elt< ($list->vector ls n) n)]) - (let loop ([ls ls] [i 0]) - (unless (null? ls) - (set-car! ls (vector-ref v i)) - (let ([ls (cdr ls)]) - (unless (null? ls) - (set-car! ls (vector-ref v (fx+ i 1))) - (loop (cdr ls) (fx+ i 2)))))) - ls))))) - - (set-who! merge! - (lambda (elt< ls1 ls2) - (unless (procedure? elt<) - ($oops who "~s is not a procedure" elt<)) - ($list-length ls1 who) - ($list-length ls2 who) - (dolmerge! elt< ls1 ls2 (list '()))))) -) diff --git a/ta6ob/s/5_6.ta6ob b/ta6ob/s/5_6.ta6ob deleted file mode 100644 index 32f4e99..0000000 Binary files a/ta6ob/s/5_6.ta6ob and /dev/null differ diff --git a/ta6ob/s/5_7.ss b/ta6ob/s/5_7.ss deleted file mode 100644 index e51e0ac..0000000 --- a/ta6ob/s/5_7.ss +++ /dev/null @@ -1,206 +0,0 @@ -;;; 5_7.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; symbol functions - -(begin -(define property-list - (lambda (s) - (unless (symbol? s) - ($oops 'property-list "~s is not a symbol" s)) - (list-copy ($symbol-property-list s)))) - -(define putprop - (lambda (s p v) - (if (symbol? s) - (let pt ([pl ($symbol-property-list s)]) - (cond - [(null? pl) - ($set-symbol-property-list! s - (cons p (cons v ($symbol-property-list s))))] - [(eq? (car pl) p) - (set-car! (cdr pl) v)] - [else (pt (cdr (cdr pl)))])) - ($oops 'putprop "~s is not a symbol" s)))) - -(define remprop - (lambda (s p) - (if (symbol? s) - (let pt ([pl ($symbol-property-list s)] [prev #f]) - (cond - [(null? pl) (void)] - [(eq? (car pl) p) - (if prev - (set-cdr! prev (cdr (cdr pl))) - ($set-symbol-property-list! s (cdr (cdr pl))))] - [else (pt (cdr (cdr pl)) (cdr pl))])) - ($oops 'remprop "~s is not a symbol" s)))) - -(define $sgetprop - (lambda (s p d) - (unless (symbol? s) ($oops '$sgetprop "~s is not a symbol" s)) - (let gt ([pl ($system-property-list s)]) - (if (null? pl) - d - (if (eq? (car pl) p) - (car (cdr pl)) - (gt (cdr (cdr pl)))))))) - -(define $sputprop - (lambda (s p v) - (unless (symbol? s) ($oops '$sputprop "~s is not a symbol" s)) - (let ((plist ($system-property-list s))) - (let pt ([pl plist]) - (if (null? pl) - ($set-system-property-list! s (cons p (cons v plist))) - (if (eq? (car pl) p) - (set-car! (cdr pl) v) - (pt (cdr (cdr pl))))))))) - -(define $sremprop - (lambda (s p) - (unless (symbol? s) ($oops '$sremprop "~s is not a symbol" s)) - (let rp ([pl ($system-property-list s)] [prev #f]) - (unless (null? pl) - (if (eq? (car pl) p) - (if prev - (set-cdr! prev (cdr (cdr pl))) - ($set-system-property-list! s (cdr (cdr pl)))) - (rp (cdr (cdr pl)) (cdr pl))))))) -) - -(eval-when (compile) (optimize-level 3)) - -(let ([prefix "g"] [count 0]) - (define generate-unique-name - ; a-z must come first in alphabet. separator must not be in alphabet. - (let ([suffix 0]) - (define unique-id (foreign-procedure "(cs)unique_id" () scheme-object)) - (define (make-session-key) - (define alphabet "abcdefghijklmnopqrstuvwxyz0123456789") - (define separator #\-) - (define b (string-length alphabet)) - (define digit->char (lambda (n) (string-ref alphabet n))) - (list->string - (let loop ([n (unique-id)] [a (list separator)]) - (if (< n b) - ; ensure name starts with letter. assumes a-z first in alphabet. - (if (< n 26) - (cons (digit->char n) a) - (cons* (string-ref alphabet 0) (digit->char n) a)) - (loop (quotient n b) (cons (digit->char (remainder n b)) a)))))) - (define (session-key) - (or $session-key - (let ([k (make-session-key)]) - (set! $session-key k) - (set! suffix -1) - k))) - (lambda () - (define alphabet "0123456789") - (define b (string-length alphabet)) - (define digit->char (lambda (n) (string-ref alphabet n))) - (let* ([k (session-key)] [n (string-length k)]) - (set! suffix (fx+ suffix 1)) - (let f ([i 0]) - (if (fx= i n) - (let g ([suffix suffix] [n (fx+ n 1)]) - (if (< suffix b) - (let ([s (make-string n)]) - (string-set! s i (digit->char suffix)) - s) - (let ([s (g (quotient suffix b) (fx+ n 1))]) - (string-set! s (fx+ i (fx- (string-length s) n)) - (digit->char (remainder suffix b))) - s))) - (let ([s (f (fx+ i 1))]) - (string-set! s i (string-ref k i)) - s))))))) - (define generate-pretty-name - (lambda () - (let ([count (let ([n count]) (set! count (+ n 1)) n)] - [prefix prefix]) - (if (and (string? prefix) (fixnum? count)) - (let ([n1 (string-length prefix)]) - (let l1 ([n (fx+ n1 1)] [d 10]) - (if (fx> d count) - (let ([s (make-string n)]) - (let l2 ([i (fx- n1 1)]) - (unless (fx< i 0) - (string-set! s i (string-ref prefix i)) - (l2 (fx- i 1)))) - (let l3 ([i (fx- n 1)] [q count]) - (unless (fx< i n1) - (string-set! s i - (string-ref "0123456789" (fxremainder q 10))) - (l3 (fx- i 1) (fxquotient q 10)))) - s) - (l1 (fx+ n 1) (fx* d 10))))) - (parameterize ([print-radix 10]) - (format "~a~a" prefix count)))))) - (define $strings->gensym - (foreign-procedure "(cs)s_strings_to_gensym" - (scheme-object scheme-object) - scheme-object)) - (set! $gensym->pretty-name - (lambda (x) - (with-tc-mutex - (cond - [($symbol-name x) => cdr] ; someone beat us to it - [else - (let ([name (generate-pretty-name)]) - ($set-symbol-name! x (cons #f name)) - name)])))) - (set-who! gensym->unique-string - (lambda (sym) - (unless (symbol? sym) ($oops who "~s is not a gensym" sym)) - (let ([name ($symbol-name sym)]) - (or (and (pair? name) (car name)) ; get out quick if name already recorded - (begin - (unless (or (not name) (pair? name)) ($oops who "~s is not a gensym" sym)) - (with-tc-mutex - ; grab name again once safely inside the critical section - (let ([name ($symbol-name sym)]) - (if (not name) - (let ([uname (generate-unique-name)]) - ($set-symbol-name! sym - (cons uname (generate-pretty-name))) - ($intern-gensym sym) - uname) - (or (car name) - (let ([uname (generate-unique-name)]) - (set-car! name uname) - ($intern-gensym sym) - uname)))))))))) - (set! gensym-prefix - (case-lambda - [() prefix] - [(x) (set! prefix x)])) - (set! gensym-count - (case-lambda - [() count] - [(x) - (unless (and (or (fixnum? x) (bignum? x)) (>= x 0)) - ($oops 'gensym-count "~s is not a nonnegative integer" x)) - (set! count x)])) - (set-who! gensym - (case-lambda - [() (#3%gensym)] - [(pretty-name) - (unless (string? pretty-name) ($oops who "~s is not a string" pretty-name)) - (#3%gensym pretty-name)] - [(pretty-name unique-name) - (unless (string? pretty-name) ($oops who "~s is not a string" pretty-name)) - (unless (string? unique-name) ($oops who "~s is not a string" unique-name)) - ($strings->gensym pretty-name unique-name)]))) diff --git a/ta6ob/s/5_7.ta6ob b/ta6ob/s/5_7.ta6ob deleted file mode 100644 index 52ec309..0000000 Binary files a/ta6ob/s/5_7.ta6ob and /dev/null differ diff --git a/ta6ob/s/6.ss b/ta6ob/s/6.ss deleted file mode 100644 index 3edcffd..0000000 --- a/ta6ob/s/6.ss +++ /dev/null @@ -1,505 +0,0 @@ -;;; 6.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(begin -(define with-output-to-string - (lambda (th) - (unless (procedure? th) - ($oops 'with-output-to-string "~s is not a procedure" th)) - (parameterize ([current-output-port (open-output-string)]) - (th) - (get-output-string (current-output-port))))) - -(define with-input-from-string - (lambda (s th) - (unless (string? s) - ($oops 'with-input-from-string "~s is not a string" s)) - (unless (procedure? th) - ($oops 'with-input-from-string "~s is not a procedure" th)) - (let ([p (open-input-string s)]) - (call-with-values - (lambda () (parameterize ([current-input-port p]) (th))) - (lambda v (apply values v)))))) - -(let () - (define getwd - (if (foreign-entry? "(cs)s_getwd") - (foreign-procedure "(cs)s_getwd" () string) - (lambda () - (let ([p (process "exec /bin/pwd")]) - (let ([ip (car p)] [op (open-output-string)]) - (let f () - (let ([c (read-char ip)]) - (if (or (eof-object? c) (char=? c #\newline)) - (begin - (close-output-port (cadr p)) - (close-input-port ip) - (get-output-string op)) - (begin (write-char c op) (f)))))))))) - (define chdir - (foreign-procedure "(cs)s_chdir" - (string) - integer-32)) - (define $cd - (case-lambda - [(who) (or (getwd) ($oops who "cannot determine current directory"))] - [(dir who) - (unless (string? dir) ($oops who "~s is not a string" dir)) - (unless (= (chdir dir) 0) - ($oops who "cannot set current directory to ~s" dir))])) - (set-who! current-directory - (case-lambda - [() ($cd who)] - [(dir) ($cd dir who)])) - (set-who! cd - (case-lambda - [() ($cd who)] - [(dir) ($cd dir who)]))) - -(let () - (define who 'mkdir) - - (define fp (foreign-procedure "(cs)mkdir" (string uptr) ptr)) - - (define (do-mkdir path mode) - (unless (string? path) ($oops who "~s is not a string" path)) - (unless (fixnum? mode) ($oops who "~s is not a fixnum" mode)) - (let ([x (fp path mode)]) - (cond - [(eqv? x #t) (void)] - [(string? x) - ($oops/c who - (make-i/o-filename-error path) - "cannot create ~s: ~(~a~)" path x)] - [else - ($oops/c who - (make-i/o-filename-error path) - "cannot create ~s" path)]))) - - (set! mkdir - (case-lambda - [(path) (do-mkdir path #o777)] - [(path mode) (do-mkdir path mode)]))) - -(define-who chmod - (let ([fp (foreign-procedure "(cs)chmod" (string fixnum) ptr)]) - (lambda (path mode) - (unless (string? path) ($oops who "~s is not a string" path)) - (unless (fixnum? mode) ($oops who "~s is not a fixnum" mode)) - (let ([x (fp path mode)]) - (cond - [(eqv? x #t) (void)] - [(string? x) - ($oops/c who - (make-i/o-filename-error path) - "cannot modify ~s: ~(~a~)" path x)] - [else - ($oops/c who - (make-i/o-filename-error path) - "cannot modify ~s" path)]))))) - -(define-who get-mode - (let ([fp (foreign-procedure "(cs)getmod" (string boolean) ptr)]) - (rec get-mode - (case-lambda - [(path) (get-mode path #t)] - [(path follow?) - (define (err x) - (if (string? x) - ($oops/c who - (make-i/o-filename-error path) - "failed for ~s: ~(~a~)" path x) - ($oops/c who - (make-i/o-filename-error path) - "failed for ~s" path))) - (unless (string? path) ($oops who "~s is not a string" path)) - (let ([x (fp path follow?)]) - (if (fixnum? x) - x - (err x)))])))) - -(let () - (define file-x-time - (lambda (who path-fp fd-fp file follow?) - (define (path-err path x) - (if (string? x) - ($oops/c who - (make-i/o-filename-error path) - "failed for ~s: ~(~a~)" path x) - ($oops/c who - (make-i/o-filename-error path) - "failed for ~s" path))) - (unless (or (string? file) (and (port? file) (file-port? file))) - ($oops who "~s is not a string or file port" file)) - (if (string? file) - (let ([x (path-fp file follow?)]) - (if (pair? x) - (make-time 'time-utc (cdr x) (car x)) - (path-err file x))) - (let ([x (fd-fp (port-file-descriptor file))]) - (cond - [(pair? x) (make-time 'time-utc (cdr x) (car x))] - [(string? x) ($oops who "failed for ~s: ~(~a~)" file x)] - [else ($oops who "failed for ~s" file)]))))) - - (define-syntax define-file-x-time - (syntax-rules () - [(_ name path-name fd-name) - (set-who! name - (let ([path-fp (foreign-procedure path-name (string boolean) ptr)] - [fd-fp (foreign-procedure fd-name (fixnum) ptr)]) - (case-lambda - [(file) (file-x-time who path-fp fd-fp file #t)] - [(file follow?) (file-x-time who path-fp fd-fp file follow?)])))])) - - (define-file-x-time file-access-time "(cs)path_atime" "(cs)fd_atime") - (define-file-x-time file-change-time "(cs)path_ctime" "(cs)fd_atime") - (define-file-x-time file-modification-time "(cs)path_mtime" "(cs)fd_mtime")) - -(define directory-separator - (lambda () - (#2%directory-separator))) - -(define directory-separator? - (lambda (c) - (unless (char? c) - ($oops 'directory-separator? "~s is not a character" c)) - (#3%directory-separator? c))) - -(define-who directory-list - (let ([dl (if-feature windows - (let ([wl (foreign-procedure "(cs)find_files" (string) scheme-object)]) - (lambda (path) - (let ([n (string-length path)]) - (unless (and (fx> n 0) - (let nostars? ([i 0]) - (or (fx= i n) - (and (not (char=? (string-ref path i) #\*)) - (nostars? (fx+ i 1)))))) - ($oops who "invalid directory name ~s" path)) - (wl (if (memv (string-ref path (fx- n 1)) '(#\\ #\/ #\:)) - (string-append path "*") - (string-append path "\\*")))))) - (foreign-procedure "(cs)directory_list" (string) scheme-object))]) - (lambda (path) - (unless (string? path) ($oops who "~s is not a string" path)) - (let ([bv* (dl path)]) - (if (string? bv*) - ($oops/c who - (make-i/o-filename-error path) - "failed for ~a: ~(~a~)" path bv*) - (remp (lambda (s) - (let ([n (string-length s)]) - (or (and (fx= n 1) (char=? (string-ref s 0) #\.)) - (and (fx= n 2) - (char=? (string-ref s 0) #\.) - (char=? (string-ref s 1) #\.))))) - (map (if-feature windows - (lambda (bv) (utf16->string bv 'little #t)) - utf8->string) - bv*))))))) - -(define-who file-exists? - (let ([fp (foreign-procedure "(cs)file_existsp" (string boolean) boolean)]) - (rec file-exists? - (case-lambda - [(path) (file-exists? path #t)] - [(path follow?) - (unless (string? path) ($oops who "~s is not a string" path)) - (fp path follow?)])))) - -(define-who #(r6rs: file-exists?) - (lambda (path) - (#2%file-exists? path #t))) - -(define-who file-regular? - (let ([fp (foreign-procedure "(cs)file_regularp" (string boolean) boolean)]) - (rec file-regular? - (case-lambda - [(path) (file-regular? path #t)] - [(path follow?) - (unless (string? path) ($oops who "~s is not a string" path)) - (fp path follow?)])))) - -(define-who file-directory? - (let ([fp (foreign-procedure "(cs)file_directoryp" (string boolean) boolean)]) - (rec file-directory? - (case-lambda - [(path) (file-directory? path #t)] - [(path follow?) - (unless (string? path) ($oops who "~s is not a string" path)) - (fp path follow?)])))) - -(define-who file-symbolic-link? - (let ([fp (foreign-procedure "(cs)file_symbolic_linkp" (string) boolean)]) - (lambda (path) - (unless (string? path) ($oops who "~s is not a string" path)) - (fp path)))) - -(let () - (define fp-delete-file - (foreign-procedure "(cs)delete_file" - (string) - scheme-object)) - - (define fp-delete-directory - (foreign-procedure "(cs)delete_directory" - (string) - scheme-object)) - - (define (do-delete who fp path error?) - (unless (string? path) - ($oops who "~s is not a string" path)) - (let ([x (fp path)]) - (if error? - (cond - [(eqv? x #t) (void)] - [(string? x) - ($oops/c who - (make-i/o-filename-error path) - "failed for ~a: ~(~a~)" path x)] - [else - ($oops/c who - (make-i/o-filename-error path) - "failed for ~a" path)]) - (eq? x #t)))) - - (set-who! delete-file - (case-lambda - [(path) (do-delete who fp-delete-file path #f)] - [(path error?) (do-delete who fp-delete-file path error?)])) - - (set-who! #(r6rs: delete-file) ; implicit rec - (lambda (path) - (do-delete who fp-delete-file path #t))) - - (set-who! delete-directory - (case-lambda - [(path) (do-delete who fp-delete-directory path #f)] - [(path error?) (do-delete who fp-delete-directory path error?)]))) - -(let () - (define fp (foreign-procedure "(cs)rename_file" (string string) ptr)) - - (set-who! rename-file - (lambda (path1 path2) - (unless (string? path1) - ($oops who "~s is not a string" path1)) - (unless (string? path2) - ($oops who "~s is not a string" path2)) - (let ([x (fp path1 path2)]) - (cond - [(eqv? x #t) (void)] - [(string? x) - ($oops/c who - (condition - (make-i/o-filename-error path1) - (make-i/o-filename-error path2)) - "cannot rename ~s to ~s: ~(~a~)" path1 path2 x)] - [else - ($oops/c who - (condition - (make-i/o-filename-error path1) - (make-i/o-filename-error path2)) - "cannot rename ~s to ~s" path1 path2)]))))) - -;;; path procedures - -(let () - (define windows? (if-feature windows #t #f)) - - (define directory-separator-predicate - (lambda (s) - (if (and windows? - (string? s) - (let ([n (string-length s)]) - (and (fx>= n 4) - (char=? (string-ref s 0) #\\) - (char=? (string-ref s 1) #\\) - (char=? (string-ref s 2) #\?) - (char=? (string-ref s 3) #\\)))) - (lambda (c) (char=? c #\\)) - directory-separator?))) - - (define path-base - (lambda (s n) - (cond - [(and windows? - (fx>= n 2) - (char=? (string-ref s 1) #\:) - (let ([c (string-ref s 0)]) - (or (char<=? #\a c #\z) (char<=? #\A c #\Z)))) - (if (and (fx>= n 3) (directory-separator? (string-ref s 2))) 3 2)] - [(and windows? - (fx>= n 4) - (char=? (string-ref s 0) #\\) - (char=? (string-ref s 1) #\\) - (char=? (string-ref s 2) #\?) - (char=? (string-ref s 3) #\\)) - (cond - [(and (fx>= n 6) - (char=? (string-ref s 5) #\:) - (let ([c (string-ref s 4)]) - (or (char<=? #\a c #\z) (char<=? #\A c #\Z)))) - (if (and (fx>= n 7) (char=? (string-ref s 6) #\\)) 7 6)] - [(and windows? - (fx>= n 8) - (char-ci=? (string-ref s 4) #\U) - (char-ci=? (string-ref s 5) #\N) - (char-ci=? (string-ref s 6) #\C) - (char=? (string-ref s 7) #\\)) - (let loop ([i (if (and (fx>= n 9) (char=? (string-ref s 8) #\\)) 9 8)]) - (if (or (fx= i n) (char=? (string-ref s i) #\\)) - i - (loop (fx+ i 1))))] - [else 4])] - [(and windows? - (fx>= n 2) - (directory-separator? (string-ref s 0)) - (directory-separator? (string-ref s 1))) - (let loop ([i 2]) - (if (or (fx= i n) (directory-separator? (string-ref s i))) - i - (loop (fx+ i 1))))] - [(and (fx>= n 1) (directory-separator? (string-ref s 0))) 1] - [(and (fx>= n 1) (char=? (string-ref s 0) #\.)) - (if (or (fx= n 1) (directory-separator? (string-ref s 1))) - 1 - (if (and (char=? (string-ref s 1) #\.) - (or (fx= n 2) (directory-separator? (string-ref s 2)))) - 2 - 0))] - [(and (fx>= n 1) (char=? (string-ref s 0) #\~)) - (if (or (fx= n 1) (directory-separator? (string-ref s 1))) - 1 - (let loop ([i 2]) - (if (or (fx= i n) (directory-separator? (string-ref s i))) - i - (loop (fx+ i 1)))))] - [else 0]))) - - (set-who! path-absolute? - (lambda (s) - (unless (string? s) ($oops who "~s is not a string" s)) - (let ([n (string-length s)]) - (or (and (fx>= n 1) (directory-separator? (string-ref s 0))) - (and (fx>= n 1) (char=? (string-ref s 0) #\~)) - (and windows? - (fx>= n 3) - (char=? (string-ref s 1) #\:) - (let ([c (string-ref s 0)]) - (or (char<=? #\a c #\z) (char<=? #\A c #\Z))) - (directory-separator? (string-ref s 2))))))) - - (set-who! path-extension - (lambda (s) - (define directory-separator? (directory-separator-predicate s)) - (unless (string? s) ($oops who "~s is not a string" s)) - (let* ([n (string-length s)] [base (path-base s n)]) - (let loop ([i n]) - (let ([i (fx- i 1)]) - (if (or (fx< i base) (directory-separator? (string-ref s i))) - "" - (if (char=? (string-ref s i) #\.) - (if (and (fx= i (fx- n 1)) - (or (fx= i base) - (directory-separator? (string-ref s (fx- i 1))) - (and (char=? (string-ref s (fx- i 1)) #\.) - (or (fx= (fx- i 1) base) - (directory-separator? (string-ref s (fx- i 2))))))) - "" - (substring s (fx+ i 1) n)) - (loop i)))))))) - - (set-who! path-root - (lambda (s) - (define directory-separator? (directory-separator-predicate s)) - (unless (string? s) ($oops who "~s is not a string" s)) - (let* ([n (string-length s)] [base (path-base s n)]) - (let loop ([i n]) - (let ([i (fx- i 1)]) - (if (or (fx< i base) (directory-separator? (string-ref s i))) - s - (if (char=? (string-ref s i) #\.) - (if (and (fx= i (fx- n 1)) - (or (fx= i base) - (directory-separator? (string-ref s (fx- i 1))) - (and (char=? (string-ref s (fx- i 1)) #\.) - (or (fx= (fx- i 1) base) - (directory-separator? (string-ref s (fx- i 2))))))) - s - (substring s 0 i)) - (loop i)))))))) - - (set-who! path-last - (lambda (s) - (define directory-separator? (directory-separator-predicate s)) - (unless (string? s) ($oops who "~s is not a string" s)) - (let* ([n (string-length s)] [base (path-base s n)]) - (let loop ([i n]) - (cond - [(fx= i base) (if (fx= base 0) s (substring s base n))] - [(directory-separator? (string-ref s (fx- i 1))) (substring s i n)] - [else (loop (fx- i 1))]))))) - - (set-who! path-parent - (lambda (s) - (define directory-separator? (directory-separator-predicate s)) - (define (skip-sep-backward s i base) - (let ([i (fx- i 1)]) - (if (or (fx= i base) (not (directory-separator? (string-ref s (fx- i 1))))) - i - (skip-sep-backward s i base)))) - (unless (string? s) ($oops who "~s is not a string" s)) - (let* ([n (string-length s)] [base (path-base s n)]) - (let loop ([i n]) - (cond - [(fx= i base) (substring s 0 base)] - [(directory-separator? (string-ref s (fx- i 1))) - (substring s 0 (skip-sep-backward s i base))] - [else (loop (fx- i 1))]))))) - - (set-who! path-first - (lambda (s) - (define directory-separator? (directory-separator-predicate s)) - (unless (string? s) ($oops who "~s is not a string" s)) - (let* ([n (string-length s)] [base (path-base s n)]) - (if (fx= base 0) - (let loop ([i 0]) - (cond - [(fx= i n) ""] - [(directory-separator? (string-ref s i)) (substring s 0 i)] - [else (loop (fx+ i 1))])) - (if (fx= base n) s (substring s 0 base)))))) - - (set-who! path-rest - (lambda (s) - (define directory-separator? (directory-separator-predicate s)) - (define (skip-sep s i n) - (if (or (fx= i n) (not (directory-separator? (string-ref s i)))) - i - (skip-sep s (fx+ i 1) n))) - (unless (string? s) ($oops who "~s is not a string" s)) - (let* ([n (string-length s)] [base (path-base s n)]) - (if (fx= base 0) - (let loop ([i 0]) - (cond - [(fx= i n) s] - [(directory-separator? (string-ref s i)) - (substring s (skip-sep s (fx+ i 1) n) n)] - [else (loop (fx+ i 1))])) - (substring s (skip-sep s base n) n))))) -) -) diff --git a/ta6ob/s/6.ta6ob b/ta6ob/s/6.ta6ob deleted file mode 100644 index 6041d55..0000000 Binary files a/ta6ob/s/6.ta6ob and /dev/null differ diff --git a/ta6ob/s/7.ss b/ta6ob/s/7.ss deleted file mode 100644 index 033a9ff..0000000 --- a/ta6ob/s/7.ss +++ /dev/null @@ -1,1533 +0,0 @@ -;;; 7.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; system operations - -(begin -(define scheme-start - (make-parameter - (lambda fns (for-each load fns) (new-cafe)) - (lambda (p) - (unless (procedure? p) - ($oops 'scheme-start "~s is not a procedure" p)) - p))) - -(define scheme-script - (make-parameter - (lambda (fn . fns) - (command-line (cons fn fns)) - (command-line-arguments fns) - (load fn)) - (lambda (p) - (unless (procedure? p) - ($oops 'scheme-script "~s is not a procedure" p)) - p))) - -(define scheme-program - (make-parameter - (lambda (fn . fns) - (command-line (cons fn fns)) - (command-line-arguments fns) - (load-program fn)) - (lambda (p) - (unless (procedure? p) - ($oops 'scheme-program "~s is not a procedure" p)) - p))) - -(define command-line-arguments - (make-parameter - '() - (lambda (x) - (unless (and (list? x) (andmap string? x)) - ($oops 'command-line-arguments "~s is not a list of strings" x)) - x))) - -(define command-line - (make-parameter - '("") - (lambda (x) - (unless (and (list? x) (not (null? x)) (andmap string? x)) - ($oops 'command-line "~s is not a nonempty list of strings" x)) - x))) - -(define-who #(r6rs: command-line) - (lambda () - (#2%command-line))) - -(define-who bytes-allocated - (let ([ba (foreign-procedure "(cs)bytes_allocated" - (scheme-object scheme-object) - scheme-object)]) - (define filter-generation - (lambda (g) - (cond - [(and (fixnum? g) (fx<= 0 g (collect-maximum-generation))) g] - [(eq? g 'static) (constant static-generation)] - [else ($oops who "invalid generation ~s" g)]))) - (define filter-space - (lambda (s) - (cond - [(assq s (constant real-space-alist)) => cdr] - [else ($oops who "invalid space ~s" s)]))) - (case-lambda - [() (ba -1 -1)] - [(g) (ba (filter-generation g) -1)] - [(g s) (ba (if g (filter-generation g) -1) (if s (filter-space s) -1))]))) - -(define $spaces (lambda () (map car (constant real-space-alist)))) - -(define current-memory-bytes (foreign-procedure "(cs)curmembytes" () uptr)) -(define maximum-memory-bytes (foreign-procedure "(cs)maxmembytes" () uptr)) - -(define reset-maximum-memory-bytes! (foreign-procedure "(cs)resetmaxmembytes" () void)) - -(define-who with-source-path - (lambda (whoarg fn p) - (unless (or (eq? whoarg #f) (string? whoarg) (symbol? whoarg)) ($oops who "invalid who argument ~s" whoarg)) - (unless (string? fn) ($oops who "~s is not a string" fn)) - (unless (procedure? p) ($oops who "~s is not a procedure" p)) - (let ([dirs (source-directories)]) - (if (or (equal? dirs '("")) (equal? dirs '(".")) ($fixed-path? fn)) - (p fn) - (let loop ([ls dirs]) - (if (null? ls) - ($oops whoarg "file ~s not found in source directories" fn) - (let ([path (let ([dir (car ls)]) - (if (or (string=? dir "") (string=? dir ".")) - fn - (format - (if (directory-separator? - (string-ref dir - (fx- (string-length dir) 1))) - "~a~a" - "~a/~a") - dir fn)))]) - (if (guard (c [#t #f]) (close-input-port (open-input-file path)) #t) - (p path) - (loop (cdr ls)))))))))) - -(set! $compressed-warning - (let ([warned? #f]) - (lambda (who p) - (unless warned? - (set! warned? #t) - (warningf who "fasl file content is compressed internally; compressing the file (~s) is redundant and can slow fasl writing and reading significantly" p))))) - -(set-who! fasl-read - (let () - (define $fasl-read (foreign-procedure "(cs)fasl_read" (int fixnum ptr) ptr)) - (define $bv-fasl-read (foreign-procedure "(cs)bv_fasl_read" (ptr ptr) ptr)) - (define (get-uptr p) - (let ([k (get-u8 p)]) - (let f ([k k] [n (fxsrl k 1)]) - (if (fxlogbit? 0 k) - (let ([k (get-u8 p)]) - (f k (logor (ash n 7) (fxsrl k 1)))) - n)))) - (define (get-uptr/bytes p) - (let ([k (get-u8 p)]) - (let f ([k k] [n (fxsrl k 1)] [bytes 1]) - (if (fxlogbit? 0 k) - (let ([k (get-u8 p)]) - (f k (logor (ash n 7) (fxsrl k 1)) (fx+ bytes 1))) - (values n bytes))))) - (define (malformed p what) ($oops who "malformed fasl-object found in ~s (~a)" p what)) - (define (check-header p) - (let ([bv (make-bytevector 8 (constant fasl-type-header))]) - (unless (and (eqv? (get-bytevector-n! p bv 1 7) 7) - (bytevector=? bv (constant fasl-header))) - (malformed p "invalid header"))) - (let ([n (get-uptr p)]) - (unless (= n (constant scheme-version)) - ($oops who "incompatible fasl-object version ~a found in ~s" - ($format-scheme-version n) p))) - (let ([n (get-uptr p)]) - (unless (or (= n (constant machine-type-any)) (= n (constant machine-type))) - (cond - [(assv n (constant machine-type-alist)) => - (lambda (a) - ($oops who "incompatible fasl-object machine-type ~s found in ~s" - (cdr a) p))] - [else (malformed p "unrecognized machine type")]))) - (unless (and (eqv? (get-u8 p) (char->integer #\()) ;) - (let f () - (let ([n (get-u8 p)]) - (and (not (eof-object? n)) ;( - (or (eqv? n (char->integer #\))) (f)))))) - (malformed p "invalid list of base boot files"))) - (define (go p situation) - (define (go1) - (if (and ($port-flags-set? p (constant port-flag-file)) - (or (not ($port-flags-set? p (constant port-flag-compressed))) - (begin ($compressed-warning who p) #f)) - (eqv? (binary-port-input-count p) 0)) - ($fasl-read ($port-info p) situation (port-name p)) - (let fasl-entry () - (let ([ty (get-u8 p)]) - (cond - [(eof-object? ty) ty] - [(eqv? ty (constant fasl-type-header)) - (check-header p) - (fasl-entry)] - [(eqv? ty (constant fasl-type-visit)) - (go2 (eqv? situation (constant fasl-type-revisit)))] - [(eqv? ty (constant fasl-type-revisit)) - (go2 (eqv? situation (constant fasl-type-visit)))] - [(eqv? ty (constant fasl-type-visit-revisit)) - (go2 #f)] - [else (malformed p "invalid situation")]))))) - (define (go2 skip?) - (let ([n (get-uptr p)]) - (if skip? - (begin - (if (and (port-has-port-position? p) (port-has-set-port-position!? p)) - (set-port-position! p (+ (port-position p) n)) - (get-bytevector-n p n)) - (go1)) - (let ([compressed-flag (get-u8 p)]) - (cond - [(or (eqv? compressed-flag (constant fasl-type-gzip)) (eqv? compressed-flag (constant fasl-type-lz4))) - (let-values ([(dest-size dest-size-bytes) (get-uptr/bytes p)]) - (let* ([src-size (- n 1 dest-size-bytes)] - [bv (get-bytevector-n p src-size)] - [bv ($bytevector-uncompress bv dest-size - (if (eqv? compressed-flag (constant fasl-type-gzip)) - (constant COMPRESS-GZIP) - (constant COMPRESS-LZ4)))]) - ($bv-fasl-read bv (port-name p))))] - [(eqv? compressed-flag (constant fasl-type-uncompressed)) - ($bv-fasl-read (get-bytevector-n p (- n 1)) (port-name p))] - [else (malformed p "invalid compression")]))))) - (unless (and (input-port? p) (binary-port? p)) - ($oops who "~s is not a binary input port" p)) - (go1)) - (case-lambda - [(p) (go p (constant fasl-type-visit-revisit))] - [(p situation) - (go p - (case situation - [(visit) (constant fasl-type-visit)] - [(revisit) (constant fasl-type-revisit)] - [(load) (constant fasl-type-visit-revisit)] - [else ($oops who "invalid situation ~s" situation)]))]))) - -(define ($compiled-file-header? ip) - (let ([pos (port-position ip)]) - (let ([cfh? (let* ([bv (constant fasl-header)] [n (bytevector-length bv)]) - (let f ([i 0]) - (or (fx= i n) - (and (eqv? (get-u8 ip) (bytevector-u8-ref bv i)) - (f (fx+ i 1))))))]) - (set-port-position! ip pos) - cfh?))) - -(let () - (define do-load-binary - (lambda (who fn ip situation for-import? importer) - (let ([load-binary (make-load-binary who fn situation for-import? importer)]) - (let ([x (fasl-read ip situation)]) - (unless (eof-object? x) - (let loop ([x x]) - (let ([next-x (fasl-read ip situation)]) - (if (eof-object? next-x) - (load-binary x) - (begin (load-binary x) (loop next-x)))))))))) - - (define (make-load-binary who fn situation for-import? importer) - (module (Lexpand? recompile-info? library/ct-info? library/rt-info? program-info?) - (import (nanopass)) - (include "base-lang.ss") - (include "expand-lang.ss")) - (lambda (x) - (cond - [(procedure? x) (x)] - [(library/rt-info? x) ($install-library/rt-desc x for-import? importer fn)] - [(library/ct-info? x) ($install-library/ct-desc x for-import? importer fn)] - [(program-info? x) ($install-program-desc x)] - [(recompile-info? x) (void)] - [(Lexpand? x) ($interpret-backend x situation for-import? importer fn)] - ; NB: this is here to support the #t inserted by compile-file-help2 after header information - [(eq? x #t) (void)] - [else ($oops who "unexpected value ~s read from ~a" x fn)]))) - - (define (do-load who fn situation for-import? importer ksrc) - (let ([ip ($open-file-input-port who fn)]) - (on-reset (close-port ip) - (let ([fp (let ([start-pos (port-position ip)]) - (if (and (eqv? (get-u8 ip) (char->integer #\#)) - (eqv? (get-u8 ip) (char->integer #\!)) - (let ([b (get-u8 ip)]) (or (eqv? b (char->integer #\space)) (eqv? b (char->integer #\/))))) - (let loop ([fp 3]) - (let ([b (get-u8 ip)]) - (if (eof-object? b) - fp - (let ([fp (+ fp 1)]) - (if (eqv? b (char->integer #\newline)) - fp - (loop fp)))))) - (begin (set-port-position! ip start-pos) 0)))]) - (if ($compiled-file-header? ip) - (begin - (do-load-binary who fn ip situation for-import? importer) - (close-port ip)) - (begin - (unless ksrc - (close-port ip) - ($oops who "~a is not a compiled file" fn)) - (unless (eqv? fp 0) (set-port-position! ip 0)) - (let ([sfd ($source-file-descriptor fn ip (eqv? fp 0))]) - (unless (eqv? fp 0) (set-port-position! ip fp)) - ; whack ip so on-reset close-port call above closes the text port - (set! ip (transcoded-port ip (current-transcoder))) - (ksrc ip sfd ($make-read ip sfd fp))))))))) - - (set! $make-load-binary - (lambda (fn) - (make-load-binary '$make-load-binary fn 'load #f #f))) - - (set-who! load-compiled-from-port - (lambda (ip) - (unless (and (input-port? ip) (binary-port? ip)) - ($oops who "~s is not a binary input port" ip)) - (do-load-binary who (port-name ip) ip 'load #f #f))) - - (set-who! visit-compiled-from-port - (lambda (ip) - (unless (and (input-port? ip) (binary-port? ip)) - ($oops who "~s is not a binary input port" ip)) - (do-load-binary who (port-name ip) ip 'visit #f #f))) - - (set-who! revisit-compiled-from-port - (lambda (ip) - (unless (and (input-port? ip) (binary-port? ip)) - ($oops who "~s is not a binary input port" ip)) - (do-load-binary who (port-name ip) ip 'revisit #f #f))) - - (set-who! load-program - (rec load-program - (case-lambda - [(fn) (load-program fn eval)] - [(fn ev) - (unless (string? fn) ($oops who "~s is not a string" fn)) - (unless (procedure? ev) ($oops who "~s is not a procedure" ev)) - (with-source-path who fn - (lambda (fn) - (do-load who fn 'load #f #f - (lambda (ip sfd do-read) - ($set-port-flags! ip (constant port-flag-r6rs)) - (let loop ([x* '()]) - (let ([x (do-read)]) - (if (eof-object? x) - (begin - (close-port ip) - (ev `(top-level-program ,@(reverse x*))) - (void)) - (loop (cons x x*)))))))))]))) - - (set-who! load-library ; like load, but sets #!r6rs mode - (rec load-library - (case-lambda - [(fn) (load-library fn eval)] - [(fn ev) - (unless (string? fn) ($oops who "~s is not a string" fn)) - (unless (procedure? ev) ($oops who "~s is not a procedure" ev)) - (with-source-path who fn - (lambda (fn) - (do-load who fn 'load #f #f - (lambda (ip sfd do-read) - ($set-port-flags! ip (constant port-flag-r6rs)) - (let loop () - (let ([x (do-read)]) - (unless (eof-object? x) - (ev x) - (loop)))) - (close-port ip)))))]))) - - (set! $load-library ; for syntax.ss load-library - ; like load, but sets #!r6rs mode and does not use with-source-path, - ; since syntax.ss load-library has already determined the path. - ; adds fn's directory to source-directories - (lambda (fn situation importer) - (define who 'import) - (let ([fn (let ([host-fn (format "~a.~s" (path-root fn) (machine-type))]) - (if (file-exists? host-fn) host-fn fn))]) - (do-load who fn situation #t importer - (lambda (ip sfd do-read) - ($set-port-flags! ip (constant port-flag-r6rs)) - (parameterize ([source-directories (cons (path-parent fn) (source-directories))]) - (let loop () - (let ([x (do-read)]) - (unless (eof-object? x) - (eval x) - (loop))))) - (close-port ip)))))) - - (set-who! load - (rec load - (case-lambda - [(fn) (load fn eval)] - [(fn ev) - (unless (string? fn) ($oops who "~s is not a string" fn)) - (unless (procedure? ev) ($oops who "~s is not a procedure" ev)) - (with-source-path who fn - (lambda (fn) - (do-load who fn 'load #f #f - (lambda (ip sfd do-read) - (let loop () - (let ([x (do-read)]) - (unless (eof-object? x) - (ev x) - (loop)))) - (close-port ip)))))]))) - - (set! $visit - (lambda (who fn importer) - (do-load who fn 'visit #t importer #f))) - - (set! $revisit - (lambda (who fn importer) - (do-load who fn 'revisit #t importer #f))) - - (set-who! visit - (lambda (fn) - (do-load who fn 'visit #f #f #f))) - - (set-who! revisit - (lambda (fn) - (do-load who fn 'revisit #f #f #f)))) - -(let () - (module sstats-record (make-sstats sstats? sstats-cpu sstats-real - sstats-bytes sstats-gc-count sstats-gc-cpu - sstats-gc-real sstats-gc-bytes - set-sstats-cpu! set-sstats-real! - set-sstats-bytes! set-sstats-gc-count! - set-sstats-gc-cpu! set-sstats-gc-real! - set-sstats-gc-bytes!) - (define-record-type (sstats make-sstats sstats?) - (nongenerative #{sstats pfwch3jd8ts96giujpitoverj-0}) - (sealed #t) - (fields - (mutable cpu sstats-cpu set-sstats-cpu!) - (mutable real sstats-real set-sstats-real!) - (mutable bytes sstats-bytes set-sstats-bytes!) - (mutable gc-count sstats-gc-count set-sstats-gc-count!) - (mutable gc-cpu sstats-gc-cpu set-sstats-gc-cpu!) - (mutable gc-real sstats-gc-real set-sstats-gc-real!) - (mutable gc-bytes sstats-gc-bytes set-sstats-gc-bytes!)) - (protocol - (lambda (new) - (lambda (cpu real bytes gc-count gc-cpu gc-real gc-bytes) - (new cpu real bytes gc-count gc-cpu gc-real gc-bytes)))))) - (define exact-integer? (lambda (x) (and (integer? x) (exact? x)))) - (set-who! make-sstats - (lambda (cpu real bytes gc-count gc-cpu gc-real gc-bytes) - (define verify-time - (lambda (name x) - (unless (time? x) - ($oops who "~s value ~s is not a time record" name x)))) - (define verify-exact-integer - (lambda (name x) - (unless (exact-integer? x) - ($oops who "~s value ~s is not an exact integer" name x)))) - (import sstats-record) - (verify-time 'cpu cpu) - (verify-time 'real real) - (verify-exact-integer 'bytes bytes) - (verify-exact-integer 'gc-count gc-count) - (verify-time 'gc-cpu gc-cpu) - (verify-time 'gc-real gc-real) - (verify-exact-integer 'gc-bytes gc-bytes) - (make-sstats cpu real bytes gc-count gc-cpu gc-real gc-bytes))) - (set! sstats? (lambda (x) (import sstats-record) (sstats? x))) - (let () - (define verify-sstats - (lambda (who x) - (import sstats-record) - (unless (sstats? x) ($oops who "~s is not an sstats record" x)))) - (define verify-exact-integer - (lambda (who x) - (unless (exact-integer? x) - ($oops who "~s is not an exact integer" x)))) - (define verify-time - (lambda (who x) - (unless (time? x) - ($oops who "~s is not a time record" x)))) - (define-syntax field - (lambda (x) - (syntax-case x () - [(_ name verify-arg) - (with-syntax ([sstats-name (construct-name #'sstats-record "sstats-" #'name)] - [set-sstats-name! (construct-name #'sstats-record "set-sstats-" #'name "!")]) - #'(begin - (set-who! sstats-name - (lambda (x) - (import sstats-record) - (verify-sstats who x) - (sstats-name x))) - (set-who! set-sstats-name! - (lambda (x n) - (import sstats-record) - (verify-sstats who x) - (verify-arg who n) - (set-sstats-name! x n)))))]))) - (field cpu verify-time) - (field real verify-time) - (field bytes verify-exact-integer) - (field gc-count verify-exact-integer) - (field gc-cpu verify-time) - (field gc-real verify-time) - (field gc-bytes verify-exact-integer))) - -(define-who sstats-print - (rec sstats-print - (case-lambda - [(s) (sstats-print s (current-output-port))] - [(s port) - (unless (sstats? s) - ($oops who "~s is not an sstats record" s)) - (unless (and (output-port? port) (textual-port? port)) - ($oops who "~s is not a textual output port" port)) - (let ([collections (sstats-gc-count s)] - [time->string - (lambda (x) - ;; based on record-writer for ts in date.ss - (let ([sec (time-second x)] [nsec (time-nanosecond x)]) - (if (and (< sec 0) (> nsec 0)) - (format "-~d.~9,'0ds" (- -1 sec) (- 1000000000 nsec)) - (format "~d.~9,'0ds" sec nsec))))]) - (if (zero? collections) - (fprintf port -" no collections - ~a elapsed cpu time - ~a elapsed real time - ~s bytes allocated -" - (time->string (sstats-cpu s)) - (time->string (sstats-real s)) - (sstats-bytes s)) - (fprintf port -" ~s collection~:p - ~a elapsed cpu time, including ~a collecting - ~a elapsed real time, including ~a collecting - ~s bytes allocated, including ~s bytes reclaimed -" - collections - (time->string (sstats-cpu s)) (time->string (sstats-gc-cpu s)) - (time->string (sstats-real s)) (time->string (sstats-gc-real s)) - (sstats-bytes s) (sstats-gc-bytes s))))]))) - -(define display-statistics - (case-lambda - [() (display-statistics (current-output-port))] - [(p) - (unless (and (output-port? p) (textual-port? p)) - ($oops 'display-statistics "~s is not a textual output port" p)) - (sstats-print (statistics) p)])) - -(define-who sstats-difference - (lambda (a b) - (unless (sstats? a) - ($oops who "~s is not an sstats record" a)) - (unless (sstats? b) - ($oops who "~s is not an sstats record" b)) - (let ([int-diff (lambda (f a b) (- (f a) (f b)))] - [time-diff (lambda (f a b) (time-difference (f a) (f b)))]) - (make-sstats - (time-diff sstats-cpu a b) - (time-diff sstats-real a b) - (int-diff sstats-bytes a b) - (int-diff sstats-gc-count a b) - (time-diff sstats-gc-cpu a b) - (time-diff sstats-gc-real a b) - (int-diff sstats-gc-bytes a b))))) - -(define collect-generation-radix - (make-parameter - 4 - (lambda (v) - (unless (and (fixnum? v) (fx< 0 v)) - ($oops 'collect-generation-radix "~s is not a positive fixnum" v)) - v))) - -(define $reset-protect - (lambda (body out) - ((call/cc - (lambda (k) - (parameterize ([reset-handler - (lambda () - (k (lambda () - (out) - ((reset-handler)))))]) - (with-exception-handler - (lambda (c) - ; would prefer not to burn bridges even for serious condition - ; if the exception is continuable, but we have no way to know - ; short of grubbing through the continuation - (if (serious-condition? c) - (k (lambda () (out) (raise c))) - (raise-continuable c))) - (lambda () - (call-with-values body - (case-lambda - [(v) (lambda () v)] - [v* (lambda () (apply values v*))])))))))))) - -(define exit-handler) -(define reset-handler) -(define abort-handler) -(let ([c-exit (foreign-procedure "(cs)c_exit" (integer-32) void)]) - (define (integer-32? x) - (and (integer? x) - (exact? x) - (<= #x-80000000 x #x7fffffff))) - - (set! exit-handler - ($make-thread-parameter - (case-lambda - [() (c-exit 0)] - [(x . args) (c-exit (if (eqv? x (void)) 0 (if (integer-32? x) x -1)))]) - (lambda (v) - (unless (procedure? v) - ($oops 'exit-handler "~s is not a procedure" v)) - v))) - - (set! reset-handler - ($make-thread-parameter - (lambda () (c-exit 0)) - (lambda (v) - (unless (procedure? v) - ($oops 'reset-handler "~s is not a procedure" v)) - v))) - - (set! abort-handler - ($make-thread-parameter - (case-lambda - [() (c-exit -1)] - [(x) (c-exit (if (eqv? x (void)) 0 (if (integer-32? x) x -1)))]) - (lambda (v) - (unless (procedure? v) - ($oops 'abort-handler "~s is not a procedure" v)) - v)))) - -(let () - (define (unexpected-return who) - ($oops who (format "unexpected return from ~s handler" who))) - - (set-who! exit - (lambda args - (apply (exit-handler) args) - (unexpected-return who))) - - (set-who! #(r6rs: exit) - (case-lambda - [() ((exit-handler)) (unexpected-return who)] - [(x) ((exit-handler) x) (unexpected-return who)])) - - (set-who! reset - (lambda () - ((reset-handler)) - (unexpected-return who))) - - (set-who! abort - (case-lambda - [() ((abort-handler)) (unexpected-return who)] - [(x) ((abort-handler) x) (unexpected-return who)]))) - -(define $interrupt ($make-thread-parameter void)) - -(define $format-scheme-version - (lambda (n) - (if (= (logand n 255) 0) - (format "~d.~d" - (ash n -16) - (logand (ash n -8) 255)) - (format "~d.~d.~d" - (ash n -16) - (logand (ash n -8) 255) - (logand n 255))))) - -; set in back.ss -(define $scheme-version) - -(define scheme-version-number - (lambda () - (let ([n (constant scheme-version)]) - (values - (ash n -16) - (logand (ash n -8) 255) - (logand n 255))))) - -(define scheme-version - (let ([s #f]) - (lambda () - (unless s - (set! s - (format "~:[Petite ~;~]Chez Scheme Version ~a" - $compiler-is-loaded? - $scheme-version))) - s))) - -(define petite? - (lambda () - (not $compiler-is-loaded?))) - -(define threaded? - (lambda () - (if-feature pthreads #t #f))) - -(define get-process-id (foreign-procedure "(cs)getpid" () integer-32)) - -(set! get-thread-id - (lambda () - ($tc-field 'threadno ($tc)))) - -(define-who sleep - (let ([fp (foreign-procedure "(cs)nanosleep" (ptr ptr) void)]) - (lambda (t) - (unless (and (time? t) (eq? (time-type t) 'time-duration)) - ($oops who "~s is not a time record of type time-duration" t)) - (let ([s (time-second t)]) - (when (>= s 0) - (fp s (time-nanosecond t))))))) - -(define $scheme-greeting - (lambda () - (format "~a\nCopyright 1984-2022 Cisco Systems, Inc.\n" - (scheme-version)))) - -(define $session-key #f) -(define $scheme-init) -(define $scheme) -(define $script) -(define $as-time-goes-by) -(define collect) -(define break-handler) -(define debug) - -(let () - -(define debug-condition* '()) - -(module (docollect collect-init) - (define gc-trip 0) - (define gc-cpu (make-time 'time-collector-cpu 0 0)) - (define gc-real (make-time 'time-collector-real 0 0)) - (define gc-bytes 0) - (define gc-count 0) - (define start-bytes 0) - (define docollect - (let ([do-gc (foreign-procedure "(cs)do_gc" (int int int) void)]) - (lambda (p) - (with-tc-mutex - (unless (= $active-threads 1) - ($oops 'collect "cannot collect when multiple threads are active")) - (let-values ([(trip g gmintarget gmaxtarget) (p gc-trip)]) - (set! gc-trip trip) - (let ([cpu (current-time 'time-thread)] [real (current-time 'time-monotonic)]) - (set! gc-bytes (+ gc-bytes (bytes-allocated))) - (when (collect-notify) - (fprintf (console-output-port) - "~%[collecting generation ~s into generation ~s..." - g gmaxtarget) - (flush-output-port (console-output-port))) - (when (eqv? g (collect-maximum-generation)) - ($clear-source-lines-cache)) - (do-gc g gmintarget gmaxtarget) - ($close-resurrected-files) - (when-feature pthreads - ($close-resurrected-mutexes&conditions)) - (when (collect-notify) - (fprintf (console-output-port) "done]~%") - (flush-output-port (console-output-port))) - (set! gc-bytes (- gc-bytes (bytes-allocated))) - (set! gc-cpu (add-duration gc-cpu (time-difference (current-time 'time-thread) cpu))) - (set! gc-real (add-duration gc-real (time-difference (current-time 'time-monotonic) real))) - (set! gc-count (1+ gc-count)))))))) - (define collect-init - (lambda () - (set! gc-trip 0) - (set! gc-cpu (make-time 'time-collector-cpu 0 0)) - (set! gc-real (make-time 'time-collector-real 0 0)) - (set! gc-count 0) - (set! gc-bytes 0) - (set! start-bytes (bytes-allocated)))) - (set! $gc-real-time (lambda () gc-real)) - (set! $gc-cpu-time (lambda () gc-cpu)) - (set! initial-bytes-allocated (lambda () start-bytes)) - (set! bytes-deallocated (lambda () gc-bytes)) - (set! collections (lambda () gc-count)) - (set! statistics - (lambda () - (make-sstats - (current-time 'time-thread) - (current-time 'time-monotonic) - (+ (- (bytes-allocated) start-bytes) gc-bytes) - gc-count - gc-cpu - gc-real - gc-bytes)))) - -(set-who! collect - (let () - (define collect0 - (lambda () - (docollect - (lambda (gct) - (let ([gct (+ gct 1)]) - (let ([cmg (collect-maximum-generation)]) - (let loop ([g cmg]) - (if (= (modulo gct (expt (collect-generation-radix) g)) 0) - (if (fx= g cmg) - (values 0 g (fxmin g 1) g) - (values gct g 1 (fx+ g 1))) - (loop (fx- g 1)))))))))) - (define collect2 - (lambda (g gmintarget gmaxtarget) - (docollect - (lambda (gct) - (values - ; make gc-trip to look like we've just collected generation g - ; w/o also having collected generation g+1 - (if (fx= g (collect-maximum-generation)) - 0 - (let ([gct (+ gct 1)]) - (define (trip g) - (let ([n (expt (collect-generation-radix) g)]) - (+ gct (modulo (- n gct) n)))) - (let ([next (trip g)] [limit (trip (fx+ g 1))]) - (if (< next limit) next (- limit 1))))) - g gmintarget gmaxtarget))))) - (case-lambda - [() (collect0)] - [(g) - (let ([cmg (collect-maximum-generation)]) - (unless (and (fixnum? g) (fx<= 0 g cmg)) - ($oops who "invalid generation ~s" g)) - (let ([gtarget (if (fx= g cmg) g (fx+ g 1))]) - (collect2 g gtarget gtarget)))] - [(g gtarget) - (let ([cmg (collect-maximum-generation)]) - (unless (and (fixnum? g) (fx<= 0 g cmg)) - ($oops who "invalid generation ~s" g)) - (unless (if (fx= g cmg) - (or (eqv? gtarget g) (eq? gtarget 'static)) - (or (eqv? gtarget g) (eqv? gtarget (fx+ g 1)))) - ($oops who "invalid target generation ~s for generation ~s" gtarget g))) - (let ([gtarget (if (eq? gtarget 'static) (constant static-generation) gtarget)]) - (collect2 g gtarget gtarget))] - [(g gmintarget gmaxtarget) - (let ([cmg (collect-maximum-generation)]) - (unless (and (fixnum? g) (fx<= 0 g cmg)) - ($oops who "invalid generation ~s" g)) - (unless (if (fx= g cmg) - (or (eqv? gmaxtarget g) (eq? gmaxtarget 'static)) - (or (eqv? gmaxtarget g) (eqv? gmaxtarget (fx+ g 1)))) - ($oops who "invalid maximum target generation ~s for generation ~s" gmaxtarget g)) - (unless (or (eqv? gmintarget gmaxtarget) - (and (fixnum? gmintarget) - (fx<= 1 gmintarget (if (fixnum? gmaxtarget) gmaxtarget cmg)))) - ($oops who "invalid minimum target generation ~s for generation ~s and maximum target generation ~s" gmintarget g gmaxtarget))) - (collect2 g - (if (eq? gmintarget 'static) (constant static-generation) gmintarget) - (if (eq? gmaxtarget 'static) (constant static-generation) gmaxtarget))]))) - -(set! collect-rendezvous - (let ([fire-collector (foreign-procedure "(cs)fire_collector" () void)]) - (lambda () - (fire-collector) - ($collect-rendezvous)))) - -(set! keyboard-interrupt-handler - ($make-thread-parameter - (lambda () - (clear-output-port (console-output-port)) - (fresh-line (console-output-port)) - (flush-output-port (console-output-port)) - (($interrupt))) - (lambda (x) - (unless (procedure? x) - ($oops 'keyboard-interrupt-handler "~s is not a procedure" x)) - x))) - -(let () - (define register-scheme-signal - (foreign-procedure "(cs)register_scheme_signal" (iptr) void)) - - (define signal-alist '()) - - (set! register-signal-handler - (lambda (sig handler) - (unless (fixnum? sig) - ($oops 'register-signal-handler "~s is not a fixnum" sig)) - (unless (procedure? handler) - ($oops 'register-signal-handler "~s is not a procedure" handler)) - (critical-section - (register-scheme-signal sig) - (let ((a (assq sig signal-alist))) - (if a - (set-cdr! a handler) - (set! signal-alist (cons (cons sig handler) signal-alist))))))) - - (set! $signal-interrupt-handler - (lambda (sig) - (let ((a (assq sig signal-alist))) - (unless a - ($oops '$signal-interrupt-handler - "unexpected signal number ~d received~%" - sig)) - ((cdr a) sig))))) - -;;; entry point from C kernel - -(set! $scheme-init - (lambda () - (set! debug-condition* '()) - (collect-init) - ($io-init) - (set! $session-key #f) - ($interrupt reset) - ($clear-pass-stats) - (enable-interrupts))) - -(set! $scheme - (lambda (fns) - (define (go) - (call/cc - (lambda (k) - (parameterize ([abort-handler - (case-lambda [() (k -1)] [(x) (k x)])] - [exit-handler - (case-lambda [() (k (void))] [(x . args) (k x)])] - [reset-handler (lambda () (k -1))]) - (apply (scheme-start) fns))))) - (unless (suppress-greeting) - (display ($scheme-greeting) (console-output-port)) - (newline (console-output-port)) - (flush-output-port (console-output-port))) - (if-feature expeditor - (if ($enable-expeditor) ($expeditor go) (go)) - (go)))) - -(set! $script - (lambda (program? fn fns) - (define (go) - (call/cc - (lambda (k) - (parameterize ([abort-handler - (case-lambda [() (k -1)] [(x) (k x)])] - [exit-handler - (case-lambda [() (k (void))] [(x . args) (k x)])] - [reset-handler (lambda () (k -1))]) - (apply (if program? (scheme-program) (scheme-script)) fn fns))))) - (if-feature expeditor - (if ($enable-expeditor) ($expeditor go) (go)) - (go)))) - -(set! $as-time-goes-by - (lambda (e t) - (define sanitize - (lambda (s) - (define sanitize-time - (lambda (t) - (if (< (time-second t) 0) - (make-time 'time-duration 0 0) - t))) - (define sanitize-count - (lambda (n) - (max n 0))) - (make-sstats - (sanitize-time (sstats-cpu s)) - (sanitize-time (sstats-real s)) - (sanitize-count (sstats-bytes s)) - (sanitize-count (sstats-gc-count s)) - (sanitize-time (sstats-gc-cpu s)) - (sanitize-time (sstats-gc-real s)) - (sanitize-count (sstats-gc-bytes s))))) - (define prstats - (lambda (b1 b2) - (let ([a (statistics)]) - (parameterize ([print-level 2] [print-length 2]) - (fprintf (console-output-port) "(time ~s)~%" e)) - (let ([elapsed (sstats-difference a b2)]) - (let ([overhead (sstats-difference b2 b1)]) - (let ([adjusted (sanitize (sstats-difference elapsed overhead))]) - (sstats-print adjusted (console-output-port))))) - (flush-output-port (console-output-port))))) - (let ([b1 (statistics)]) - (let ([b2 (statistics)]) - (call-with-values t - (case-lambda - [(v) (prstats b1 b2) v] - [(v1 v2) (prstats b1 b2) (values v1 v2)] - [(v1 v2 v3) (prstats b1 b2) (values v1 v2 v3)] - [(v1 v2 v3 v4) (prstats b1 b2) (values v1 v2 v3 v4)] - [r (prstats b1 b2) (apply values r)])))))) - -(set! $report-string - (lambda (dest what who msg args) - (let ([what (and (not (equal? what "")) what)] - [who (and (not (equal? who "")) who)]) - (parameterize ([print-level 3] [print-length 6]) - (format dest "~@[~@(~a~)~]~:[~; in ~]~@[~a~]~:[~;: ~]~@[~?~]" - what - (and what who) - who - (and (or what who) (not (equal? msg ""))) - msg - args))))) - -(let () -(define report - (lambda (what who msg args) - (fresh-line (console-output-port)) - ($report-string (console-output-port) what who msg args) - (newline (console-output-port)) - (flush-output-port (console-output-port)))) - -(set! break-handler - ($make-thread-parameter - (case-lambda - [(who msg . args) - (unless (string? msg) - ($oops 'default-break-handler "~s is not a string" msg)) - (report "break" who msg args) - (($interrupt))] - [(who) - (report "break" who "" '()) - (($interrupt))] - [() - (($interrupt))]) - (lambda (x) - (unless (procedure? x) - ($oops 'break-handler "~s is not a procedure" x)) - x))) -) - -(set-who! debug-condition - (case-lambda - [() (cond - [(assv ($tc-field 'threadno ($tc)) debug-condition*) => cdr] - [else #f])] - [(c) - (let ([n ($tc-field 'threadno ($tc))]) - (with-tc-mutex - (set! debug-condition* - (let ([ls (remp (lambda (a) (eqv? (car a) n)) debug-condition*)]) - (if c (cons (cons n c) ls) ls)))))])) - -(set! debug - (lambda () - (define line-limit 74) - (define pad - (lambda (s n p) - (let ([i (string-length s)]) - (when (> n i) (display (make-string (- n i) #\space) p)) - (display s p) - (max i n)))) - (define numbered-line-display - (lambda (point? n c p) - (display (if point? "*" " ")) - (let ([s (with-output-to-string (lambda () (display-condition c)))]) - (let ([k (- line-limit (+ (pad (number->string n) 4 p) 2))]) - (display ": " p) - (let ([i (string-length s)]) - (if (> i k) - (fprintf p "~a ...~%" (substring s 0 (- k 4))) - (fprintf p "~a~%" s))))))) - (define unnumbered-line-display - (lambda (c p) - (let ([s (with-output-to-string (lambda () (display-condition c)))]) - (let ([k (- line-limit 2)]) - (display " " p) - (let ([i (string-length s)]) - (if (> i k) - (fprintf p "~a ...~%" (substring s 0 (- k 4))) - (fprintf p "~a~%" s))))))) - (define printem - (lambda (point ls p) - (if (null? (cdr ls)) - (let ([x (car ls)]) - (unnumbered-line-display (cdr x) p)) - (for-each - (lambda (x) - (numbered-line-display (eq? x point) (car x) (cdr x) p)) - ls)))) - (define debug-cafe - (lambda (point ls) - (parameterize ([$interrupt void]) - (clear-input-port (console-input-port)) - (let ([waiter (call/cc - (lambda (k) - (rec f (lambda () (k f)))))]) - (fprintf (console-output-port) "debug> ") - (flush-output-port (console-output-port)) - (let ([x (let ([x (parameterize ([$interrupt waiter] - [reset-handler waiter]) - (read (console-input-port)))]) - (if (eof-object? x) - (begin - (newline (console-output-port)) - (flush-output-port (console-output-port)) - 'e) - x))]) - (case x - [(i) - (let ([c (cdr point)]) - (if (continuation-condition? c) - (inspect (condition-continuation c)) - (display "the raise continuation is not available\n"))) - (waiter)] - [(c) - (inspect (cdr point)) - (waiter)] - [(q) - (with-tc-mutex - (for-each - (lambda (x) (set! debug-condition* (remq x debug-condition*))) - ls)) - (void)] - [(e) - (void)] - [(s) - (printem point - (sort (lambda (x y) (< (car x) (car y))) ls) - (console-output-port)) - (waiter)] - [(?) - (if (null? (cdr ls)) - (fprintf (console-output-port) -"Type i to inspect the raise continuation (if available) - s to display the condition - c to inspect the condition - e or eof to exit the debugger, retaining error continuation - q to exit the debugger, discarding error continuation -") - (fprintf (console-output-port) -"Type i to inspect the selected thread's raise continuation (if available) - to select thread - s to display the conditions - c to inspect the selected thread's condition - e or eof to exit the debugger, retaining error continuations - q to exit the debugger, discarding error continuations -")) - (flush-output-port (console-output-port)) - (waiter)] - [else - (cond - [(assv x ls) => - (lambda (a) - (set! point a) - (waiter))] - [(and (integer? x) (nonnegative? x)) - (fprintf (console-output-port) - "No saved error continuation for thread ~s.~%" - x) - (flush-output-port (console-output-port)) - (waiter)] - [else - (fprintf (console-output-port) - "Invalid command. Type ? for options.~%") - (flush-output-port (console-output-port)) - (waiter)])])))))) - (let ([ls debug-condition*]) - (cond - [(null? ls) - (fprintf (console-output-port) "Nothing to debug.~%") - (flush-output-port (console-output-port))] - [else - (debug-cafe (car ls) ls)])))) -) - -(define $collect-rendezvous - (lambda () - (define once - (let ([once #f]) - (lambda () - (when (eq? once #t) - ($oops '$collect-rendezvous - "cannot return to the collect-request-handler")) - (set! once #t)))) - (if-feature pthreads - (with-tc-mutex - (let f () - (when $collect-request-pending - (if (= $active-threads 1) ; last one standing - (dynamic-wind - once - (collect-request-handler) - (lambda () - (set! $collect-request-pending #f) - (condition-broadcast $collect-cond))) - (begin - (condition-wait $collect-cond $tc-mutex) - (f)))))) - (critical-section - (dynamic-wind - once - (collect-request-handler) - (lambda () (set! $collect-request-pending #f))))))) - -(define collect-request-handler - (make-parameter - (lambda () (collect)) - (lambda (x) - (unless (procedure? x) - ($oops 'collect-request-handler "~s is not a procedure" x)) - x))) - -(define collect-notify (make-parameter #f (lambda (x) (and x #t)))) - -(define $c-error - (lambda (arg . error-args) - ; error-args may be present along doargerr path, but we presently - ; ignore them - (define-syntax c-error-case - (lambda (x) - (syntax-case x () - [(_ arg [(key) fmls e1 e2 ...] ...) - (with-syntax ([(k ...) (map lookup-constant (datum (key ...)))]) - #'(let ([t arg]) - (record-case t - [(k) fmls e1 e2 ...] - ... - [else ($oops '$c-error "invalid error type ~s" t)])))]))) - (c-error-case arg - [(ERROR_OTHER) args (apply $oops args)] - [(ERROR_CALL_UNBOUND) (cnt symbol arg1?) - ($oops #f "variable ~:s is not bound" symbol)] - [(ERROR_CALL_NONPROCEDURE_SYMBOL) (cnt symbol arg1?) - ($oops #f "attempt to apply non-procedure ~s" - ($top-level-value symbol))] - [(ERROR_CALL_NONPROCEDURE) (cnt nonprocedure arg1?) - ($oops #f "attempt to apply non-procedure ~s" nonprocedure)] - [(ERROR_CALL_ARGUMENT_COUNT) (cnt procedure arg1?) - ($oops #f "incorrect number of arguments to ~s" procedure)] - [(ERROR_RESET) (who msg . args) - ($oops who "~?. Some debugging context lost" msg args)] - [(ERROR_NONCONTINUABLE_INTERRUPT) args - (let ([noncontinuable-interrupt - (lambda () - ((keyboard-interrupt-handler)) - (fprintf (console-output-port) - "Noncontinuable interrupt.~%") - (reset))]) - ;; ruse to get inspector to print "continuation in - ;; noncontinuable-interrupt" instead of "#c-error". - (noncontinuable-interrupt))] - [(ERROR_VALUES) (cnt) - ($oops #f - "returned ~r values to single value return context" - cnt)] - [(ERROR_MVLET) (cnt) - ($oops #f - "incorrect number of values received in multiple value context")]))) - -(define break - (lambda args - (apply (break-handler) args))) - -(define timer-interrupt-handler - ($make-thread-parameter - (lambda () - ($oops 'timer-interrupt - "timer interrupt occurred with no handler defined")) - (lambda (x) - (unless (procedure? x) - ($oops 'timer-interrupt-handler "~s is not a procedure" x)) - x))) - -(define $symbol-type - (lambda (name) - (let ((flags ($sgetprop name '*flags* 0))) - (cond - [(any-set? (prim-mask system) flags) 'system] - [(any-set? (prim-mask primitive) flags) 'primitive] - [(any-set? (prim-mask keyword) flags) - (if (any-set? (prim-mask library-uid) flags) - 'library-uid - 'keyword)] - [(any-set? (prim-mask system-keyword) flags) - (if (any-set? (prim-mask library-uid) flags) - 'system-library-uid - 'system-keyword)] - [else 'unknown])))) - -(let () - ; naive version is good enough for apropos - (define (substring? s1 s2) - (let ([n1 (string-length s1)] [n2 (string-length s2)]) - (let loop2 ([i2 0]) - (let loop1 ([i1 0] [j i2]) - (if (fx= i1 n1) - i2 - (and (not (fx= j n2)) - (if (char=? (string-ref s1 i1) (string-ref s2 j)) - (loop1 (fx+ i1 1) (fx+ j 1)) - (loop2 (fx+ i2 1))))))))) - (define symstring x) (symbol->string y)))) - (define apropos-help - (lambda (s env) - (let ([s (if (symbol? s) (symbol->string s) s)]) - (sort symstring (car ls))) - (cons (car ls) (f (cdr ls))) - (f (cdr ls))))))))) - (define apropos-library-help - (lambda (s) - (define libstring s) s)]) - (sort (lambda (ls1 ls2) (libstring (car x*))) - (cons (car x*) match*) - match*))))))))))) - (define check-s - (lambda (who s) - (unless (or (symbol? s) (string? s)) - ($oops who "~s is not a symbol or string" s)))) - (define check-env - (lambda (who env) - (unless (environment? env) - ($oops 'apropos-list "~s is not an environment" env)))) - (set! apropos-list - (case-lambda - [(s) - (check-s 'apropos-list s) - (append - (apropos-help s (interaction-environment)) - (apropos-library-help s))] - [(s env) - (check-s 'apropos-list s) - (check-env 'apropos-list env) - (append - (apropos-help s env) - (apropos-library-help s))])) - (let () - (define do-apropos - (lambda (who where s env) - (printf "~a environment:\n ~{~<~%~& ~1:; ~s~>~^,~}~&" where (apropos-help s env)) - (for-each - (lambda (x) (printf "~s:\n ~{~<~%~& ~1:; ~s~>~^,~}~&" (car x) (cdr x))) - (apropos-library-help s)))) - (set-who! apropos - (case-lambda - [(s) - (check-s who s) - (do-apropos who "interaction" s (interaction-environment))] - [(s env) - (check-s who s) - (check-env who env) - (do-apropos who "supplied" s env)])))) - -(let () - (define-record-type pass-stats - (nongenerative) - (sealed #t) - (fields - (mutable calls) - (mutable cpu) - (mutable gc-cpu) - (mutable bytes)) - (protocol - (lambda (n) - (lambda () - (let ([t (make-time 'time-duration 0 0)]) - (n 0 t t 0)))))) - - (define field-names '(name calls cpu gc-cpu bytes)) - - (define stats-ht) - - (define-threaded outer-ps #f) - - (set! $clear-pass-stats - (lambda () - (set! stats-ht (make-eq-hashtable)))) - - (set! $enable-pass-timing (make-parameter #f)) - - (set-who! $pass-time - (lambda (name thunk) - (unless (symbol? name) ($oops who "~s is not a symbol" name)) - (unless (procedure? thunk) ($oops who "~s is not a procedure" thunk)) - (if ($enable-pass-timing) - (let ([ps (with-tc-mutex - (let ([a (hashtable-cell stats-ht name #f)]) - (let ([ps (or (cdr a) (let ([ps (make-pass-stats)]) (set-cdr! a ps) ps))]) - (pass-stats-calls-set! ps (+ (pass-stats-calls ps) 1)) - ps)))]) - (dynamic-wind - (lambda () - (with-tc-mutex - (let ([cpu (current-time 'time-thread)] - [gc-cpu (current-time 'time-collector-cpu)] - [bytes (+ (bytes-deallocated) (bytes-allocated))]) - (set-time-type! cpu 'time-duration) - (set-time-type! gc-cpu 'time-duration) - (when outer-ps - (pass-stats-cpu-set! outer-ps (add-duration (pass-stats-cpu outer-ps) cpu)) - (pass-stats-gc-cpu-set! outer-ps (add-duration (pass-stats-gc-cpu outer-ps) gc-cpu)) - (pass-stats-bytes-set! outer-ps (+ (pass-stats-bytes outer-ps) bytes))) - (pass-stats-cpu-set! ps (subtract-duration (pass-stats-cpu ps) cpu)) - (pass-stats-gc-cpu-set! ps (subtract-duration (pass-stats-gc-cpu ps) gc-cpu)) - (pass-stats-bytes-set! ps (- (pass-stats-bytes ps) bytes))))) - (lambda () (fluid-let ([outer-ps ps]) (thunk))) - (lambda () - (with-tc-mutex - (let ([cpu (current-time 'time-thread)] - [gc-cpu (current-time 'time-collector-cpu)] - [bytes (+ (bytes-deallocated) (bytes-allocated))]) - (set-time-type! cpu 'time-duration) - (set-time-type! gc-cpu 'time-duration) - (when outer-ps - (pass-stats-cpu-set! outer-ps (subtract-duration (pass-stats-cpu outer-ps) cpu)) - (pass-stats-gc-cpu-set! outer-ps (subtract-duration (pass-stats-gc-cpu outer-ps) gc-cpu)) - (pass-stats-bytes-set! outer-ps (- (pass-stats-bytes outer-ps) bytes))) - (pass-stats-cpu-set! ps (add-duration (pass-stats-cpu ps) cpu)) - (pass-stats-gc-cpu-set! ps (add-duration (pass-stats-gc-cpu ps) gc-cpu)) - (pass-stats-bytes-set! ps (+ (pass-stats-bytes ps) bytes))))))) - (thunk)))) - - (set-who! $pass-stats-fields (lambda () field-names)) - - (set! $pass-stats - (lambda () - (define (build-result namev psv) - (vector->list - (vector-map - (lambda (name ps) - (list name - (pass-stats-calls ps) - (pass-stats-cpu ps) - (pass-stats-gc-cpu ps) - (pass-stats-bytes ps))) - namev - psv))) - (with-tc-mutex - (if outer-ps - (let ([cpu (current-time 'time-thread)] - [gc-cpu (current-time 'time-collector-cpu)] - [bytes (+ (bytes-deallocated) (bytes-allocated))]) - (set-time-type! cpu 'time-duration) - (set-time-type! gc-cpu 'time-duration) - (pass-stats-cpu-set! outer-ps (add-duration (pass-stats-cpu outer-ps) cpu)) - (pass-stats-gc-cpu-set! outer-ps (add-duration (pass-stats-gc-cpu outer-ps) gc-cpu)) - (pass-stats-bytes-set! outer-ps (+ (pass-stats-bytes outer-ps) bytes)) - (let ([result (call-with-values (lambda () (hashtable-entries stats-ht)) build-result)]) - (pass-stats-cpu-set! outer-ps (subtract-duration (pass-stats-cpu outer-ps) cpu)) - (pass-stats-gc-cpu-set! outer-ps (subtract-duration (pass-stats-gc-cpu outer-ps) gc-cpu)) - (pass-stats-bytes-set! outer-ps (- (pass-stats-bytes outer-ps) bytes)) - result)) - (call-with-values (lambda () (hashtable-entries stats-ht)) build-result))))) - - (let () - (define who '$print-pass-stats) - (define field-name-strings (map symbol->string field-names)) - (define check-psls - (lambda (psl*) - (unless (list? psl*) ($oops who "~s is not a list" psl*)) - (for-each - (lambda (psl) - (define exact-integer? (lambda (x) (or (fixnum? x) (bignum? x)))) - (unless (and (fx= ($list-length psl who) 5) - (apply (lambda (name calls cpu gc-cpu bytes) - (and (exact-integer? calls) - (time? cpu) - (time? gc-cpu) - (exact-integer? bytes))) - psl)) - ($oops who "malformed pass-stats entry ~s" psl))) - psl*))) - (define val->string - (lambda (x) - (cond - [(time? x) - (let-values ([(sec nsec) - (let ([sec (time-second x)] [nsec (time-nanosecond x)]) - (if (and (< sec 0) (> nsec 0)) - (values (+ sec 1) (- 1000000000 nsec)) - (values sec nsec)))]) - (format "~d.~9,'0d" sec nsec))] - [else (format "~s" x)]))) - (define (print-pass-stats key psl*) - (define pslstring x-name) (symbol->string y-name))] - [(calls) (< x-calls y-calls)] - [else ($oops who "unrecognized sort key ~s" key)])) - y)) - x))) - ; run check when passed psl* to check psl*; run when passed - ; the value of ($pass-stats) to check our assumptions - (check-psls psl*) - (let ([psl* (append (sort pslstring psl)) psl*)]) - (let ([w* (fold-left (lambda (w* s*) - (map (lambda (s w) (fxmax (string-length s) w)) s* w*)) - (map string-length field-name-strings) - s**)]) - (define print-row - (lambda (s*) - (printf "~v<~a~;~> " (car w*) (car s*)) - (for-each (lambda (s w) (printf "~v:<~a~> " w s)) (cdr s*) (cdr w*)) - (newline))) - (print-row field-name-strings) - (print-row (map (lambda (w) (make-string w #\-)) w*)) - (for-each print-row s**))))) - (set! $print-pass-stats - (case-lambda - [() (print-pass-stats #f ($pass-stats))] - [(key) (print-pass-stats key ($pass-stats))] - [(key psl*) (print-pass-stats key psl*)])))) -) diff --git a/ta6ob/s/7.ta6ob b/ta6ob/s/7.ta6ob deleted file mode 100644 index 2c4636f..0000000 Binary files a/ta6ob/s/7.ta6ob and /dev/null differ diff --git a/ta6ob/s/Makefile b/ta6ob/s/Makefile deleted file mode 100644 index 2e1a793..0000000 --- a/ta6ob/s/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# Mf-ta6ob -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -m = ta6ob -archincludes = x86_64.ss - -include Mf-base diff --git a/ta6ob/s/Mf-base b/ta6ob/s/Mf-base deleted file mode 100644 index 730eeba..0000000 --- a/ta6ob/s/Mf-base +++ /dev/null @@ -1,596 +0,0 @@ -# Mf-base -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -MAKEFLAGS += --no-print-directory - -# the following flags control various compiler options. flags prefixed by an x -# separately control the options used while compiling a cross compiler. - -# o determines the optimize level -o = 3 - -# d is the debug level at which the system should be built -d = 0 - -# cl determines the commonization level -cl = (commonization-level) - -# i determines whether inspector-information is generated: f for false, t for true -i = f - -# cp0 determines the number of cp0 (source optimizer) iterations run -cp0 = 2 - -# fc determines whether fasl objects are compressed -fc = t - -# xf determines the compression format -xf = (compress-format) - -# xl determine the compression level -xl = (compress-level) - -# p (xp) determines whether source profiling is enabled: f for false, t for true. -p = f -xp = f - -# bp (xpb) determines whether binary profiling is enabled: f for false, t for true. -bp = f -xbp = f - -# c determines whether covin files are generated: f for false, t for true. -c = f - -# loadspd determines whether source-profile data is loaded: f for false, t for true -loadspd = f - -# dumpspd determines whether source-profile data is dumped: f for false, t for true -dumpspd = f - -# loadbpd determines whether binary-profile data is loaded: f for false, t for true -loadbpd = f - -# dumpbpd determines whether binary-profile data is dumped: f for false, t for true -dumpbpd = f - -# compile determines the entry point for compilng files -# another useful value for this is compile-with-asm, defined in debug.ss -compile = compile-file - -# pdhtml determines whether profile-dump-html is called at the end of a build -pdhtml = f - -# gac determines whether cost-center allocation counts are generated: f for false, t for true -gac = f - -# gic determines whether cost-center instruction counts are generated: f for false, t for true -gic = f - -# pps determines whether pass timings are printed -pps = f - -# Explicit ".exe" needed for WSL -ifeq ($(OS),Windows_NT) - ExeSuffix = .exe -else - ExeSuffix = -endif - -# The following control where files sit and typically don't need to be changed, except -# that Scheme and SCHEMEHEAPDIRS are set by Mf-cross to point to the host Scheme -# implementation -Scheme = ../bin/$m/scheme${ExeSuffix} -export SCHEMEHEAPDIRS=../boot/%m -export CHEZSCHEMELIBDIRS=. - -# Define the libdirs separator character -ifeq ($(OS),Windows_NT) - dirsep = ; -else - dirsep = : -endif - -ProfileDumpSource = source.pd -ProfileDumpBlock = block.pd -PetiteBoot = ../boot/$m/petite.boot -SchemeBoot = ../boot/$m/scheme.boot -Cheader = ../boot/$m/scheme.h -Cequates = ../boot/$m/equates.h -Revision = ../boot/$m/revision - -# The following controls the patch files loaded before compiling, typically used only -# to load a new compiler for cross compilation -patchfile = -patch = patch - -# putting cpnanopass.patch early for maximum make --jobs=2 benefit -patchobj = patch.patch cpnanopass.patch cprep.patch cpcheck.patch\ - cp0.patch cpvalid.patch cpcommonize.patch cpletrec.patch\ - reloc.patch\ - compile.patch fasl.patch syntax.patch env.patch\ - read.patch interpret.patch ftype.patch strip.patch\ - ubify.patch back.patch - -#ordering constraints: -#first: library, prims, mathprims, front, 5_? -#last: back -#newhash before read -#io before read -#event before 4 -#ftype after syntax -#layout and record before strnum (first define-record) -#date before 7 -#(there may be other constraints as well) - -basesrc =\ - library.ss prims.ss mathprims.ss record.ss 5_1.ss 5_2.ss 5_3.ss\ - strnum.ss bytevector.ss 5_4.ss 5_6.ss 5_7.ss\ - event.ss 4.ss front.ss foreign.ss 6.ss print.ss newhash.ss\ - format.ss date.ss 7.ss cafe.ss trace.ss engine.ss\ - interpret.ss cprep.ss cpcheck.ss cp0.ss cpvalid.ss cpcommonize.ss cpletrec.ss inspect.ss\ - enum.ss io.ss read.ss primvars.ss syntax.ss costctr.ss expeditor.ss\ - exceptions.ss pretty.ss env.ss\ - fasl.ss reloc.ss pdhtml.ss strip.ss ftype.ss back.ss - -baseobj = ${basesrc:%.ss=%.$m} - -compilersrc =\ - cpnanopass.ss compile.ss cback.ss - -compilerobj = ${compilersrc:%.ss=%.$m} - -src = ${basesrc} ${compilersrc} -obj = ${baseobj} ${compilerobj} -asm = $(basesrc:%.ss=%.asm) - -macroobj =\ - cmacros.so priminfo.so primvars.so env.so setup.so - -allsrc =\ - ${basesrc} ${compilersrc} cmacros.ss ${archincludes} setup.ss debug.ss priminfo.ss primdata.ss layout.ss\ - base-lang.ss expand-lang.ss primref.ss types.ss io-types.ss fasl-helpers.ss hashtable-types.ss\ - np-languages.ss - -# doit uses a different Scheme process to compile each target -doit: ${PetiteBoot} ${SchemeBoot} ${Cheader} ${Cequates} ${Revision} - -# all uses a single Scheme process to compile all targets. this is typically -# faster when most of the targets need to be recompiled. -all: bootall ${Cheader} ${Cequates} ${Revision} - -# allx runs all up to three times and checks to see if the new boot file is the -# same as the last, i.e., the system is properly bootstrapped. -allx: prettyclean saveboot - $(MAKE) all - if $(MAKE) checkboot > /dev/null 2>&1; then echo fine ; else\ - $(MAKE) prettyclean saveboot &&\ - $(MAKE) all &&\ - if $(MAKE) checkboot > /dev/null 2>&1; then echo fine ; else\ - $(MAKE) prettyclean saveboot &&\ - $(MAKE) all &&\ - $(MAKE) checkboot ;\ - fi\ - fi - $(MAKE) restoreboot -ifneq ($(OS),Windows_NT) - $(MAKE) resetbootlinks -endif - -# bootstrap runs allx if any sources have changed since the last bootstrap -bootstrap: ${allsrc} | ${Revision} - $(MAKE) allx - touch bootstrap - -# source eagerly creates links to most of the files that might be needed -source: ${allsrc} mkheader.ss script.all - -# profiled goes through the involved process of building a profile-optimized boot file -profiled: - $(MAKE) profileclean - $(MAKE) all p=t - $(MAKE) prettyclean - $(MAKE) io.$m dumpspd=t - $(MAKE) prettyclean - $(MAKE) all loadspd=t bp=t PetiteBoot=../boot/$m/xpetite.boot SchemeBoot=../boot/$m/xscheme.boot - $(MAKE) prettyclean - $(MAKE) io.$m loadspd=t dumpbpd=t Scheme="../bin/$m/scheme -b ../boot/$m/xpetite.boot -b ../boot/$m/xscheme.boot" - rm -f ../boot/$m/xpetite.boot ../boot/$m/xscheme.boot - $(MAKE) prettyclean - $(MAKE) all loadspd=t loadbpd=t - -# clean removes the products of the targets above -clean: profileclean - rm -f bootstrap - rm -f Make.out - -# the remaining targets are typically not useful except to support those above - -.SUFFIXES: -.SUFFIXES: .ss .$m .patch .so .asm - -.ss.$m: - echo '(reset-handler abort)'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(when #$p (compile-profile (quote source)))'\ - '(when #$(bp) (compile-profile (quote block)))'\ - '(when #$(loadspd) (profile-load-data "${ProfileDumpSource}"))'\ - '(when #$(loadbpd) (profile-load-data "${ProfileDumpBlock}"))'\ - '(generate-inspector-information #$i)'\ - '(generate-allocation-counts #${gac})'\ - '(generate-instruction-counts #${gic})'\ - '(generate-covin-files #$c)'\ - '(run-cp0 (lambda (cp0 x)'\ - ' (do ([i ${cp0} (fx- i 1)] [x x (cp0 x)])'\ - ' ((fx= i 0) x))))'\ - '(collect-trip-bytes (expt 2 24))'\ - '(collect-request-handler (lambda () (collect 0 1)))'\ - '(collect 1 2)'\ - '(delete-file "$*.covin")'\ - '(time (${compile} "$*.ss" "$*.$m" (quote $m)))'\ - '(when #${pdhtml} (profile-dump-html))'\ - '(when #${dumpspd} (profile-dump-data "${ProfileDumpSource}"))'\ - '(when #${dumpbpd} (profile-dump-data "${ProfileDumpBlock}"))'\ - | ${Scheme} -q ${macroobj} ${patchfile} - -.ss.asm: - echo '(reset-handler abort)'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(when #$p (compile-profile (quote source)))'\ - '(when #$(bp) (compile-profile (quote block)))'\ - '(when #$(loadspd) (profile-load-data "${ProfileDumpSource}"))'\ - '(when #$(loadbpd) (profile-load-data "${ProfileDumpBlock}"))'\ - '(generate-inspector-information #$i)'\ - '(generate-allocation-counts #${gac})'\ - '(generate-instruction-counts #${gic})'\ - '(generate-covin-files #$c)'\ - '(run-cp0 (lambda (cp0 x)'\ - ' (do ([i ${cp0} (fx- i 1)] [x x (cp0 x)])'\ - ' ((fx= i 0) x))))'\ - '(collect-trip-bytes (expt 2 24))'\ - '(collect-request-handler (lambda () (collect 0 1)))'\ - '(collect 1 2)'\ - '(print-gensym (quote pretty/suffix))'\ - '(delete-file "$*.covin")'\ - '(compile-with-asm "$*.ss" "$*.$m" (quote $m))'\ - '(when #${pdhtml} (profile-dump-html))'\ - '(when #${dumpspd} (profile-dump-data "${ProfileDumpSource}"))'\ - '(when #${dumpbpd} (profile-dump-data "${ProfileDumpBlock}"))'\ - | ${Scheme} -q ${macroobj} ${patchfile} - -.ss.so: - echo '(reset-handler abort)'\ - '(base-exception-handler (lambda (c) (fresh-line) (display-condition c) (newline) (reset)))'\ - '(keyboard-interrupt-handler (lambda () (display "interrupted---aborting\n") (reset)))'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(generate-inspector-information #$i)'\ - '(subset-mode (quote system))'\ - '(compile-file "$*.ss" "$*.so")'\ - | ${Scheme} -q cmacros.so priminfo.so - -.ss.patch: - echo '(reset-handler abort)'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(when #$(xp) (compile-profile (quote source)))'\ - '(when #$(xbp) (compile-profile (quote block)))'\ - '(generate-inspector-information #$i)'\ - '(run-cp0 (lambda (cp0 x)'\ - ' (do ([i ${cp0} (fx- i 1)] [x x (cp0 x)])'\ - ' ((fx= i 0) x))))'\ - '(collect-trip-bytes (expt 2 24))'\ - '(collect-request-handler (lambda () (collect 0 1)))'\ - '(collect 1 2)'\ - '(time (${compile} "$*.ss" "$*.patch" (quote $m)))'\ - | ${Scheme} -q ${macroobj} - -saveboot: - cp -p -f ${PetiteBoot} ../boot/$m/sbb - cp -p -f ${SchemeBoot} ../boot/$m/scb - -checkboot: - @echo '(reset-handler abort)'\ - '(base-exception-handler (lambda (c) (fresh-line) (display-condition c) (newline) (reset)))'\ - '(begin'\ - '(#%$$fasl-file-equal? "../boot/$m/sbb" "../boot/$m/petite.boot" #t)'\ - '(#%$$fasl-file-equal? "../boot/$m/scb" "../boot/$m/scheme.boot" #t)'\ - '(printf "bootfile comparison succeeded\n"))'\ - | ../bin/$m/scheme${ExeSuffix} -b ../boot/$m/sbb -q - -xcheckboot: ${macroobj} ${patchfile} - @echo '(reset-handler abort)'\ - '(base-exception-handler (lambda (c) (fresh-line) (display-condition c) (newline) (reset)))'\ - '(begin'\ - '(#%$$fasl-file-equal? "../boot/$m/sbb" "../boot/$m/petite.boot" #t)'\ - '(#%$$fasl-file-equal? "../boot/$m/scb" "../boot/$m/scheme.boot" #t)'\ - '(printf "bootfile comparison succeeded\n"))'\ - | ${Scheme} -q ${macroobj} ${patchfile} - -restoreboot: - -mv -f ../boot/$m/sbb ${PetiteBoot} - -mv -f ../boot/$m/scb ${SchemeBoot} - -resetbootlinks: - -@echo '(reset-handler abort)'\ - '(for-each'\ - '(lambda (fn)'\ - '(let ([fn (symbol->string fn)])'\ - '(unless (file-symbolic-link? fn)'\ - '(when (guard (c [else #f]) (#%$$fasl-file-equal? (format "../~a" fn) fn))'\ - '(system (format "ln -sf ../../~a ~a" fn fn))'\ - '(void)))))'\ - '(list (quote ${SchemeBoot}) (quote ${PetiteBoot})))'\ - | ${Scheme} -q - -${PetiteBoot}: ${macroobj} ${patchfile} ${baseobj} - echo '(reset-handler abort)'\ - '(generate-covin-files #$c)'\ - '(delete-file (string-append (path-root "${PetiteBoot}") ".covin"))'\ - '(apply #%$$make-boot-file "${PetiteBoot}" (quote $m) (quote ())'\ - ' (map symbol->string (quote (${baseobj}))))'\ - | ${Scheme} -q ${macroobj} ${patchfile} - -${SchemeBoot}: ${macroobj} ${patchfile} ${compilerobj} - echo '(reset-handler abort)'\ - '(generate-covin-files #$c)'\ - '(delete-file (string-append (path-root "${SchemeBoot}") ".covin"))'\ - '(apply #%$$make-boot-file "${SchemeBoot}" (quote $m) (quote ("petite"))'\ - ' (map symbol->string (quote (${compilerobj}))))'\ - | ${Scheme} -q ${macroobj} ${patchfile} - -cmacros.so: cmacros.ss machine.def layout.ss - echo '(reset-handler abort)'\ - '(base-exception-handler (lambda (c) (fresh-line) (display-condition c) (newline) (reset)))'\ - '(keyboard-interrupt-handler (lambda () (display "interrupted---aborting\n") (reset)))'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(generate-inspector-information #$i)'\ - '(subset-mode (quote system))'\ - '(compile-file "$*.ss" "$*.so")'\ - | ${Scheme} -q - -priminfo.so: priminfo.ss primdata.ss cmacros.so - echo '(reset-handler abort)'\ - '(base-exception-handler (lambda (c) (fresh-line) (display-condition c) (newline) (reset)))'\ - '(keyboard-interrupt-handler (lambda () (display "interrupted---aborting\n") (reset)))'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(generate-inspector-information #$i)'\ - '(subset-mode (quote system))'\ - '(compile-file "$*.ss" "$*.so")'\ - | ${Scheme} -q cmacros.so - -# supply primvars.so as well as cmacros.so -mkheader.so: mkheader.ss cmacros.so primvars.so env.so - echo '(reset-handler abort)'\ - '(base-exception-handler (lambda (c) (fresh-line) (display-condition c) (newline) (reset)))'\ - '(keyboard-interrupt-handler (lambda () (display "interrupted---aborting\n") (reset)))'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(generate-inspector-information #$i)'\ - '(subset-mode (quote system))'\ - '(compile-file "$*.ss" "$*.so")'\ - | ${Scheme} -q cmacros.so priminfo.so primvars.so env.so - -nanopass.so: $(shell echo ../nanopass/nanopass/*) ../nanopass/nanopass.ss - echo '(reset-handler abort)'\ - '(base-exception-handler (lambda (c) (fresh-line) (display-condition c) (newline) (reset)))'\ - '(keyboard-interrupt-handler (lambda () (display "interrupted---aborting\n") (reset)))'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(generate-inspector-information #$i)'\ - '(collect-trip-bytes (expt 2 24))'\ - '(collect-request-handler (lambda () (collect 0 1)))'\ - '(collect 1 2)'\ - '(compile-library "../nanopass/nanopass.ss" "nanopass.so")'\ - | ${Scheme} -q --libdirs "../nanopass${dirsep}${dirsep}." --compile-imported-libraries - -rootsrc = $(shell cd ../../s; echo *) -${rootsrc}: -ifeq ($(OS),Windows_NT) - cp -p ../../s/$@ $@ -else - ln -s ../../s/$@ $@ -endif - -script.all: Mf-base - -script.all makescript: - echo '(reset-handler abort)'\ - '(for-each load (command-line-arguments))'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(when #$p (compile-profile (quote source)))'\ - '(when #$(bp) (compile-profile (quote block)))'\ - '(when #$(loadspd) (profile-load-data "${ProfileDumpSource}"))'\ - '(when #$(loadbpd) (profile-load-data "${ProfileDumpBlock}"))'\ - '(generate-inspector-information #$i)'\ - '(generate-allocation-counts #${gac})'\ - '(generate-instruction-counts #${gic})'\ - '(#%$$enable-pass-timing #${pps})'\ - '(generate-covin-files #$c)'\ - '(run-cp0 (lambda (cp0 x)'\ - ' (do ([i ${cp0} (fx- i 1)] [x x (cp0 x)])'\ - ' ((fx= i 0) x))))'\ - '(collect-trip-bytes (expt 2 24))'\ - '(collect-request-handler (lambda () (collect 0 1)))'\ - '(for-each (lambda (x) (delete-file (string-append (path-root (symbol->string x)) ".covin"))) (quote (${obj})))'\ - '(time (for-each (lambda (x y)'\ - ' (collect 1 2)'\ - ' (${compile} (symbol->string x)'\ - ' (symbol->string y)'\ - ' (quote $m)))'\ - ' (quote (${src}))'\ - ' (quote (${obj}))))'\ - '(when #${pps} (#%$$print-pass-stats))'\ - '(delete-file (string-append (path-root "${PetiteBoot}") ".covin"))'\ - '(apply #%$$make-boot-file "${PetiteBoot}" (quote $m) (quote ())'\ - ' (map symbol->string (quote (${baseobj}))))'\ - '(delete-file (string-append (path-root "${SchemeBoot}") ".covin"))'\ - '(apply #%$$make-boot-file "${SchemeBoot}" (quote $m) (quote ("petite"))'\ - ' (map symbol->string (quote (${compilerobj}))))'\ - '(when #${pdhtml} (profile-dump-html))'\ - '(when #${dumpspd} (profile-dump-data "${ProfileDumpSource}"))'\ - '(when #${dumpbpd} (profile-dump-data "${ProfileDumpBlock}"))'\ - > script.all - -script-static.all: - echo '(reset-handler abort)'\ - '(for-each load (command-line-arguments))'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(when #$p (compile-profile (quote source)))'\ - '(when #$(bp) (compile-profile (quote block)))'\ - '(generate-inspector-information #$i)'\ - '(generate-allocation-counts #${gac})'\ - '(generate-instruction-counts #${gic})'\ - '(generate-covin-files #$c)'\ - '(run-cp0 (lambda (cp0 x)'\ - ' (do ([i ${cp0} (fx- i 1)] [x x (cp0 x)])'\ - ' ((fx= i 0) x))))'\ - '(for-each (lambda (x) (delete-file (string-append (path-root (symbol->string x)) ".covin"))) (quote (${obj})))'\ - '(compile-with-setup-closure-counts (quote (${closure-opt})) (quote (${src})) (quote (${obj})) (quote $m) #$r)'\ - '(delete-file (string-append (path-root "${PetiteBoot}") ".covin"))'\ - '(apply #%$$make-boot-file "${PetiteBoot}" (quote $m) (quote ())'\ - ' (map symbol->string (quote (${baseobj}))))'\ - '(delete-file (string-append (path-root "${SchemeBoot}") ".covin"))'\ - '(apply #%$$make-boot-file "${SchemeBoot}" (quote $m) (quote ("petite"))'\ - ' (map symbol->string (quote (${compilerobj}))))'\ - '(when #${pdhtml} (profile-dump-html))'\ - > script-static.all - -script-dynamic.all: - echo '(reset-handler abort)'\ - '(for-each load (command-line-arguments))'\ - '(optimize-level $o)'\ - '(debug-level $d)'\ - '(commonization-level $(cl))'\ - '(fasl-compressed #$(fc))'\ - '(compress-format $(xf))'\ - '(compress-level $(xl))'\ - '(when #$p (compile-profile (quote source)))'\ - '(when #$(bp) (compile-profile (quote block)))'\ - '(generate-inspector-information #$i)'\ - '(generate-allocation-counts #${gac})'\ - '(generate-instruction-counts #${gic})'\ - '(generate-covin-files #$c)'\ - '(run-cp0 (lambda (cp0 x)'\ - ' (do ([i ${cp0} (fx- i 1)] [x x (cp0 x)])'\ - ' ((fx= i 0) x))))'\ - '(for-each (lambda (x) (delete-file (string-append (path-root (symbol->string x)) ".covin"))) (quote (${obj})))'\ - '(compile-with-closure-counts (quote (${closure-opt})) (quote (${src})) (quote (${obj})) (quote $m) #$r)'\ - '(delete-file (string-append (path-root "${PetiteBoot}") ".covin"))'\ - '(apply #%$$make-boot-file "${PetiteBoot}" (quote $m) (quote ())'\ - ' (map symbol->string (quote (${baseobj}))))'\ - '(delete-file (string-append (path-root "${SchemeBoot}") ".covin"))'\ - '(apply #%$$make-boot-file "${SchemeBoot}" (quote $m) (quote ("petite"))'\ - ' (map symbol->string (quote (${compilerobj}))))'\ - '(when #${pdhtml} (profile-dump-html))'\ - > script-dynamic.all - -closure-counts: ${allsrc} ${patchfile} ${macroobj} nanopass.so base-lang.ss expand-lang.ss primref.ss types.ss io-types.ss fasl-helpers.ss hashtable-types.ss script-static.all script-dynamic.all - ${Scheme} -q ${macroobj} ${patchfile} --script script-static.all - $(MAKE) ${PetiteBoot} ${SchemeBoot} - ${Scheme} -q ${macroobj} ${patchfile} --script script-dynamic.all - $(MAKE) all - -bootall: ${allsrc} ${patchfile} ${macroobj} nanopass.so makescript - ${Scheme} -q ${macroobj} ${patchfile} --script script.all - -${patch}: ${patchobj} - rm -f ${patch} - cat ${patchobj} > ${patch} - -${asm} ${obj} mkheader.so: ${macroobj} nanopass.so base-lang.ss expand-lang.ss primref.ss types.ss io-types.ss fasl-helpers.ss hashtable-types.ss ${patchfile} -primvars.so setup.so mkheader.so env.so: cmacros.so priminfo.so primref.ss -setup.so: debug.ss - -${patchobj}: ${macroobj} nanopass.so base-lang.ss expand-lang.ss primref.ss types.ss io-types.ss fasl-helpers.ss hashtable-types.ss env.ss -cpnanopass.$m cpnanopass.patch: nanopass.so np-languages.ss ${archincludes} -5_4.$m: ../unicode/unicode-char-cases.ss ../unicode/unicode-charinfo.ss - -${Cheader}: mkheader.so ${macroobj} nanopass.so base-lang.ss expand-lang.ss primref.ss types.ss io-types.ss fasl-helpers.ss hashtable-types.ss - (if [ -r ${Cheader} ]; then mv -f ${Cheader} ${Cheader}.bak; fi) - echo '(reset-handler abort)'\ - '(mkscheme.h "${Cheader}" (quote $m))' |\ - ${Scheme} -q ${macroobj} mkheader.so - (if `cmp -s ${Cheader} ${Cheader}.bak`;\ - then mv -f ${Cheader}.bak ${Cheader};\ - else rm -f ${Cheader}.bak; fi) - -${Cequates}: mkheader.so ${macroobj} nanopass.so base-lang.ss expand-lang.ss primref.ss types.ss io-types.ss fasl-helpers.ss hashtable-types.ss - (if [ -r ${Cequates} ]; then mv -f ${Cequates} ${Cequates}.bak; fi) - echo '(reset-handler abort)'\ - '(mkequates.h "${Cequates}")' |\ - ${Scheme} -q ${macroobj} mkheader.so - (if `cmp -s ${Cequates} ${Cequates}.bak`;\ - then mv -f ${Cequates}.bak ${Cequates};\ - else rm -f ${Cequates}.bak; fi) - -.PHONY: ${Revision} -${Revision}: update-revision - @./update-revision > ${Revision} - -examples: - ( cd ../examples && ${MAKE} all Scheme="${Scheme} ../s/${patchfile}" ) - -prettyclean: - rm -f *.$m xpatch ${patch} *.patch *.so *.covin *.asm script.all header.tmp *.html - rm -rf nanopass - -profileclean: prettyclean - rm -f ${ProfileDumpSource} ${ProfileDumpBlock} diff --git a/ta6ob/s/Mf-cross b/ta6ob/s/Mf-cross deleted file mode 100644 index c466f7f..0000000 --- a/ta6ob/s/Mf-cross +++ /dev/null @@ -1,44 +0,0 @@ -# Mf-cross -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Usage: make -f Mf-cross m=host xm=target, e.g.: -# make -f Mf-cross m=i3le xm=i3osx -# to cross-compile to i3osx from i3le - -what = all examples -base = ../.. - -xdoit: xboot - -include Mf-${xm} - -Scheme=$(base)/bin/${m}/scheme -export SCHEMEHEAPDIRS=$(base)/boot/${m} -o = 2 -i = t -d = 3 - -xpatch = xpatch -xpatchobj = ${patchobj} - -xboot: ${xpatch} - $(MAKE) -f Mf-${xm} ${what} m=${xm} patchfile=${xpatch} Scheme="${Scheme}" SCHEMEHEAPDIRS=${SCHEMEHEAPDIRS} - -${xpatch}: ${xpatchobj} - cat ${xpatchobj} > ${xpatch} - -x$(xm).$(m): - $(MAKE) -f Mf-cross m=$(m) xm=$(xm) i=f o=3 d=0 xpatch - mv xpatch x$(xm).$(m) diff --git a/ta6ob/s/Mf-ta6ob b/ta6ob/s/Mf-ta6ob deleted file mode 100644 index 2e1a793..0000000 --- a/ta6ob/s/Mf-ta6ob +++ /dev/null @@ -1,19 +0,0 @@ -# Mf-ta6ob -# Copyright 1984-2017 Cisco Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -m = ta6ob -archincludes = x86_64.ss - -include Mf-base diff --git a/ta6ob/s/back.ss b/ta6ob/s/back.ss deleted file mode 100644 index a5b9fbf..0000000 --- a/ta6ob/s/back.ss +++ /dev/null @@ -1,214 +0,0 @@ -;;; back.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(begin -(define-who trace-output-port - ($make-thread-parameter - (console-output-port) - (lambda (x) - (unless (and (output-port? x) (textual-port? x)) - ($oops who "~s is not a textual output port" x)) - x))) - -(define-who trace-print - ($make-thread-parameter - pretty-print - (lambda (x) - (unless (procedure? x) - ($oops who "~s is not a procedure" x)) - x))) - -(define suppress-greeting (make-parameter #f (lambda (x) (and x #t)))) - -(define-who eval-syntax-expanders-when - ($make-thread-parameter '(compile load eval) - (lambda (x) - (unless (let check ([x x] [l '(compile load eval visit revisit)]) - (or (null? x) - (and (pair? x) - (memq (car x) l) - (check (cdr x) (remq (car x) l))))) - ($oops who "invalid eval-when list ~s" x)) - x))) - -(define-who collect-maximum-generation - (let ([$get-maximum-generation (foreign-procedure "(cs)maxgen" () fixnum)] - [$set-maximum-generation! (foreign-procedure "(cs)set_maxgen" (fixnum) void)]) - (case-lambda - [() ($get-maximum-generation)] - [(g) - (unless (and (fixnum? g) (fx>= g 0)) ($oops who "invalid generation ~s" g)) - (when (fx= g 0) ($oops who "new maximum generation must be at least 1")) - (let ([limit (fx- (constant static-generation) 1)]) - (when (fx> g limit) ($oops who "~s exceeds maximum supported value ~s" g limit))) - ($set-maximum-generation! g)]))) - -(define-who release-minimum-generation - (let ([$get-release-minimum-generation (foreign-procedure "(cs)minfreegen" () fixnum)] - [$set-release-minimum-generation! (foreign-procedure "(cs)set_minfreegen" (fixnum) void)]) - (case-lambda - [() ($get-release-minimum-generation)] - [(g) - (unless (and (fixnum? g) (fx>= g 0)) ($oops who "invalid generation ~s" g)) - (unless (fx<= g (collect-maximum-generation)) - ($oops who "new release minimum generation must not be be greater than collect-maximum-generation")) - ($set-release-minimum-generation! g)]))) - -(define-who enable-object-counts - (let ([$get-enable-object-counts (foreign-procedure "(cs)enable_object_counts" () boolean)] - [$set-enable-object-counts (foreign-procedure "(cs)set_enable_object_counts" (boolean) void)]) - (case-lambda - [() ($get-enable-object-counts)] - [(b) ($set-enable-object-counts b)]))) - -(define-who collect-trip-bytes - (make-parameter - (constant default-collect-trip-bytes) - (lambda (x) - (unless (and (fixnum? x) (fx< 0 x)) - ($oops who "~s is not a positive fixnum" x)) - ($set-collect-trip-bytes x) - x))) - -(define-who heap-reserve-ratio - (case-lambda - [() $heap-reserve-ratio] - [(x) (unless (number? x) - ($oops who "~s is not a number" x)) - (let ([y (inexact x)]) - (unless (and (flonum? y) (>= y 0)) - ($oops who "invalid heap reserve ratio ~s" x)) - (set! $heap-reserve-ratio y))])) - -(define-who $assembly-output - ($make-thread-parameter #f - (lambda (x) - (cond - [(or (not x) (and (output-port? x) (textual-port? x))) x] - [(eq? x #t) (current-output-port)] - [else ($oops who "~s is not a textual output port or #f" x)])))) - -(define-who expand-output - ($make-thread-parameter #f - (lambda (x) - (unless (or (not x) (and (output-port? x) (textual-port? x))) - ($oops who "~s is not a textual output port or #f" x)) - x))) - -(define-who expand/optimize-output - ($make-thread-parameter #f - (lambda (x) - (unless (or (not x) (and (output-port? x) (textual-port? x))) - ($oops who "~s is not a textual output port or #f" x)) - x))) - -(define generate-wpo-files - ($make-thread-parameter #f - (lambda (x) - (and x #t)))) - -(define-who generate-covin-files - ($make-thread-parameter #f - (lambda (x) - (and x #t)))) - -(define $enable-check-prelex-flags - ($make-thread-parameter #f - (lambda (x) - (and x #t)))) - -(define-who run-cp0 - ($make-thread-parameter - (default-run-cp0) - (lambda (x) - (unless (procedure? x) - ($oops who "~s is not a procedure" x)) - x))) - -(define fasl-compressed - ($make-thread-parameter #t (lambda (x) (and x #t)))) - -(define compile-file-message - ($make-thread-parameter #t (lambda (x) (and x #t)))) - -(define compile-imported-libraries - ($make-thread-parameter #f (lambda (x) (and x #t)))) - -(define-who compile-library-handler - ($make-thread-parameter - (lambda (ifn ofn) (compile-library ifn ofn)) - (lambda (x) - (unless (procedure? x) ($oops who "~s is not a procedure" x)) - x))) - -(define-who compile-program-handler - ($make-thread-parameter - (lambda (ifn ofn) (compile-program ifn ofn)) - (lambda (x) - (unless (procedure? x) ($oops who "~s is not a procedure" x)) - x))) - -(define-who compress-format - (case-lambda - [() - (let ([x ($tc-field 'compress-format ($tc))]) - (cond - [(eqv? x (constant COMPRESS-GZIP)) 'gzip] - [(eqv? x (constant COMPRESS-LZ4)) 'lz4] - [else ($oops who "unexpected $compress-format value ~s" x)]))] - [(x) - ($tc-field 'compress-format ($tc) - (case x - [(gzip) (constant COMPRESS-GZIP)] - [(lz4) (constant COMPRESS-LZ4)] - [else ($oops who "~s is not a supported format" x)]))])) - -(define-who compress-level - (case-lambda - [() - (let ([x ($tc-field 'compress-level ($tc))]) - (cond - [(eqv? x (constant COMPRESS-MIN)) 'minimum] - [(eqv? x (constant COMPRESS-LOW)) 'low] - [(eqv? x (constant COMPRESS-MEDIUM)) 'medium] - [(eqv? x (constant COMPRESS-HIGH)) 'high] - [(eqv? x (constant COMPRESS-MAX)) 'maximum] - [else ($oops who "unexpected $compress-level value ~s" x)]))] - [(x) - ($tc-field 'compress-level ($tc) - (case x - [(minimum) (constant COMPRESS-MIN)] - [(low) (constant COMPRESS-LOW)] - [(medium) (constant COMPRESS-MEDIUM)] - [(high) (constant COMPRESS-HIGH)] - [(maximum) (constant COMPRESS-MAX)] - [else ($oops who "~s is not a supported level" x)]))])) - -(define-who debug-level - ($make-thread-parameter - 1 - (lambda (x) - (unless (and (fixnum? x) (<= 0 x 3)) - ($oops who "invalid level ~s" x)) - x))) - -(define internal-defines-as-letrec* - ($make-thread-parameter #t (lambda (x) (and x #t)))) - -(define self-evaluating-vectors - ($make-thread-parameter #f (lambda (x) (and x #t)))) - -(set! $scheme-version (string->symbol ($format-scheme-version (constant scheme-version)))) -) diff --git a/ta6ob/s/back.ta6ob b/ta6ob/s/back.ta6ob deleted file mode 100644 index 36d3e96..0000000 Binary files a/ta6ob/s/back.ta6ob and /dev/null differ diff --git a/ta6ob/s/base-lang.ss b/ta6ob/s/base-lang.ss deleted file mode 100644 index abf2587..0000000 --- a/ta6ob/s/base-lang.ss +++ /dev/null @@ -1,260 +0,0 @@ -;;; base-lang.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(module (Lsrc Lsrc? Ltype Ltype? unparse-Ltype unparse-Lsrc count-Lsrc - lookup-primref primref? primref-name primref-level primref-flags primref-arity - sorry! make-preinfo preinfo? preinfo-lambda? preinfo-sexpr preinfo-sexpr-set! preinfo-src - make-preinfo-lambda preinfo-lambda-name preinfo-lambda-name-set! preinfo-lambda-flags preinfo-lambda-libspec - prelex? make-prelex prelex-name prelex-name-set! prelex-flags prelex-flags-set! - prelex-source prelex-operand prelex-operand-set! prelex-uname make-prelex* - target-fixnum? target-bignum?) - - (module (lookup-primref primref? primref-name primref-flags primref-arity primref-level) - (include "primref.ss") - - (define $lookup-primref - (lambda (level name) - (unless (symbol? name) - (sorry! 'lookup-primref "invalid primitive name ~s" name)) - (or ($sgetprop name - (case level - [(2) '*prim2*] - [(3) '*prim3*] - [else ($oops 'lookup-primref "invalid level ~s" level)]) - #f) - ($oops 'lookup-primref "unrecognized prim ~s" name)))) - - (define-syntax lookup-primref - (lambda (x) - (define exact-integer? - (lambda (x) - (and (integer? x) (exact? x)))) - (define constant-level&name - (lambda (level name) - (unless (and (exact-integer? level) (memv level '(2 3))) - (syntax-error x (format "invalid level ~s" level))) - (unless (symbol? name) - (syntax-error x (format "invalid name ~s" name))) - (let ([primref ($sgetprop name (if (eqv? level 2) '*prim2* '*prim3*) #f)]) - (unless primref (syntax-error x (format "unknown primitive ~s" name))) - #`'#,primref))) - (define constant-name - (lambda (?level name) - (unless (symbol? name) - (syntax-error x (format "invalid name ~s" name))) - (let ([primref2 ($sgetprop name '*prim2* #f)] - [primref3 ($sgetprop name '*prim3* #f)]) - (unless (and primref2 primref3) - (syntax-error x (format "unknown primitive ~s" name))) - #`(let ([level #,?level]) - (case level - [(2) '#,primref2] - [(3) '#,primref3] - [else (sorry! 'lookup-primref "invalid level ~s" level)]))))) - (syntax-case x (quote) - [(_ (quote level) (quote name)) - (constant-level&name (datum level) (datum name))] - [(_ level (quote name)) - (exact-integer? (datum level)) - (constant-level&name (datum level) (datum name))] - [(_ ?level (quote name)) - (constant-name #'?level (datum name))] - [(k ?level ?name) #'($lookup-primref ?level ?name)])))) - - (module (prelex? make-prelex - prelex-name prelex-name-set! - prelex-flags prelex-flags-set! - prelex-source - prelex-operand prelex-operand-set! - prelex-uname) - (define-record-type prelex - (nongenerative #{prelex grpmhtzqa9bflxfggfu6pp-0}) - (sealed #t) - (fields (mutable name) (mutable flags) source (mutable operand) (mutable $uname)) - (protocol - (lambda (new) - (lambda (name flags source operand) - (new name flags source operand #f))))) - (define prelex-uname - (lambda (id) - (or (prelex-$uname id) - (let ([uname (gensym (symbol->string (prelex-name id)))]) - (with-tc-mutex - (or (prelex-$uname id) - (begin (prelex-$uname-set! id uname) uname))))))) - (record-writer (record-type-descriptor prelex) - (lambda (x p wr) - (fprintf p "~s" (prelex-name x))))) - - (define make-prelex* - (case-lambda - [() (make-prelex (gensym) 0 #f #f)] - [(name) (make-prelex name 0 #f #f)])) - - ; TODO: use sorry! where appropriate - (define sorry! - (lambda (who str . arg*) - ($oops 'compiler-internal "~@[~a: ~]~?" who str arg*))) - - (define maybe-source-object? - (lambda (x) - (or (eq? x #f) (source-object? x)))) - - (define rcd? - (lambda (x) - (or (record-constructor-descriptor? x) #t))) ; rcd should be restricted to rcd or ctrcd - - (define exact-integer? - (lambda (x) - (and (integer? x) (exact? x)))) - - (meta-cond - [(= (constant fixnum-bits) (fixnum-width)) - (define target-fixnum? fixnum?) - (define target-bignum? bignum?)] - [(< (constant fixnum-bits) (fixnum-width)) - (define target-fixnum? - (lambda (x) - (and (fixnum? x) - (fx<= (constant most-negative-fixnum) x (constant most-positive-fixnum))))) - (define target-bignum? - (lambda (x) - (or (bignum? x) - (and (fixnum? x) - (not (fx<= (constant most-negative-fixnum) x (constant most-positive-fixnum)))))))] - [else - (define target-fixnum? - (lambda (x) - (or (fixnum? x) - (and (bignum? x) - (<= (constant most-negative-fixnum) x (constant most-positive-fixnum)))))) - (define target-bignum? - (lambda (x) - (and (bignum? x) - (not (<= (constant most-negative-fixnum) x (constant most-positive-fixnum))))))]) - - (define $prelex? - (lambda (x) - (prelex? x))) - - (define datum? - (lambda (x) - #t)) - - (define convention? - (lambda (x) - (symbol? x))) - - (define-record-type preinfo - (nongenerative #{preinfo e23pkvo5btgapnzomqgegm-2}) - (fields src (mutable sexpr)) - (protocol - (lambda (new) - (case-lambda - [() (new #f #f)] - [(src) (new src #f)] - [(src sexpr) (new src sexpr)])))) - - (define-record-type preinfo-lambda - (nongenerative #{preinfo-lambda e23pkvo5btgapnzomqgegm-4}) - (parent preinfo) - (sealed #t) - (fields libspec (mutable name) flags) - (protocol - (lambda (pargs->new) - (case-lambda - [() ((pargs->new) #f #f 0)] - [(src) ((pargs->new src) #f #f 0)] - [(src sexpr) ((pargs->new src sexpr) #f #f 0)] - [(src sexpr libspec) ((pargs->new src sexpr) libspec #f 0)] - [(src sexpr libspec name) ((pargs->new src sexpr) libspec name 0)] - [(src sexpr libspec name flags) ((pargs->new src sexpr) libspec name flags)])))) - - ; language of foreign types - (define-language Ltype - (nongenerative-id #{Ltype czp82kxwe75y4e18-1}) - (terminals - (exact-integer (bits)) - ($ftd (ftd))) - (Type (t) - (fp-integer bits) - (fp-unsigned bits) - (fp-void) - (fp-scheme-object) - (fp-u8*) - (fp-u16*) - (fp-u32*) - (fp-fixnum) - (fp-double-float) - (fp-single-float) - (fp-ftd ftd) - (fp-ftd& ftd))) - - (define arity? - (lambda (x) - (or (eq? x #f) - (for-all fixnum? x)))) - - (define maybe-string? (lambda (x) (or (eq? x #f) (string? x)))) - - ; source language used by the passes leading up to the compiler or interpreter - (define-language Lsrc - (nongenerative-id #{Lsrc czsa1fcfzdeh493n-3}) - (terminals - (preinfo (preinfo)) - ($prelex (x)) - (datum (d)) - (record-type-descriptor (rtd)) - (rcd (rcd)) - (source-object (src)) - (maybe-source-object (maybe-src)) - (Ltype (arg-type result-type)) => unparse-Ltype - (fixnum (interface index flags level)) - (arity (arity)) - (box (box)) - (convention (conv)) - (maybe-string (name)) - (symbol (sym type)) - (primref (pr))) - (Expr (e body rtd-expr) - pr - (moi) - (ref maybe-src x) => x - (quote d) - (if e0 e1 e2) - (seq e0 e1) - (set! maybe-src x e) => (set! x e) - (pariah) - (case-lambda preinfo cl ...) => (case-lambda cl ...) - (letrec ([x* e*] ...) body) - (letrec* ([x* e*] ...) body) - (call preinfo e0 e1 ...) => (e0 e1 ...) - (record-type rtd e) - (record-cd rcd rtd-expr e) - (immutable-list (e* ...) e) - (record rtd rtd-expr e* ...) - (record-ref rtd type index e) - (record-set! rtd type index e1 e2) - (cte-optimization-loc box e) - (foreign (conv* ...) name e (arg-type* ...) result-type) - (fcallable (conv* ...) e (arg-type* ...) result-type) - (profile src) => (profile) - ; used only in cpvalid - (cpvalid-defer e)) - (CaseLambdaClause (cl) - (clause (x* ...) interface body) => [(x* ...) interface body])) - - (define-language-node-counter count-Lsrc Lsrc) - ) diff --git a/ta6ob/s/bootstrap b/ta6ob/s/bootstrap deleted file mode 100644 index e69de29..0000000 diff --git a/ta6ob/s/bytevector.ss b/ta6ob/s/bytevector.ss deleted file mode 100644 index e348c82..0000000 --- a/ta6ob/s/bytevector.ss +++ /dev/null @@ -1,1516 +0,0 @@ -;;; bytevector.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(let () - (define-syntax signed-value-pred - (lambda (x) - (syntax-case x () - [(_ ?bits) - (let ([bits (syntax->datum #'?bits)]) - (unless (and (fixnum? bits) - (fx> bits 0) - (fx= (* (fxquotient bits 8) 8) bits)) - (syntax-error #'?bits "invalid bits")) - (cond - [(fx<= bits (constant fixnum-bits)) - (with-syntax ([limit- (- (expt 2 (- bits 1)))] - [limit+ (- (expt 2 (- bits 1)) 1)]) - #'(lambda (k) (and (fixnum? k) (fx<= limit- k limit+))))] - [(fx= bits (constant fixnum-bits)) #'fixnum?] - [else - (with-syntax ([limit- (- (expt 2 (- bits 1)))] - [limit+ (- (expt 2 (- bits 1)) 1)]) - #'(lambda (k) - (or (fixnum? k) - (and (bignum? k) (<= limit- k limit+)))))]))]))) - - (define-syntax unsigned-value-pred - (lambda (x) - (syntax-case x () - [(_ ?bits) - (let ([bits (syntax->datum #'?bits)]) - (unless (and (fixnum? bits) - (fx> bits 0) - (fx= (* (fxquotient bits 8) 8) bits)) - (syntax-error #'?bits "invalid bits")) - (cond - [(fx< bits (constant fixnum-bits)) - (with-syntax ([limit+ (expt 2 bits)]) - #'(lambda (k) (and (fixnum? k) ($fxu< k limit+))))] - [(fx= bits (constant fixnum-bits)) - #'(lambda (k) (and (fixnum? k) (fx>= k 0)))] - [else - (with-syntax ([limit+ (- (expt 2 bits) 1)]) - #'(lambda (k) - (if (fixnum? k) - (fx>= k 0) - (and (bignum? k) (<= 0 k limit+)))))]))]))) - - (define (not-a-bytevector who v) - ($oops who "~s is not a bytevector" v)) - - (define (not-a-mutable-bytevector who v) - ($oops who "~s is not a mutable bytevector" v)) - - (define (invalid-index who v i) - ($oops who "invalid index ~s for bytevector ~s" i v)) - - (define (invalid-fill-value who fill) - ($oops who "~s is not a valid fill value" fill)) - - (define (invalid-value who x) - ($oops who "invalid value ~s" x)) - - (define (size-multiple-error who n size) - ($oops who "bytevector length ~s is not a multiple of size ~s" - n size)) - - (define (unrecognized-endianness who eness) - ($oops who "unrecognized endianness ~s" eness)) - - (define (invalid-size who size) - ($oops who "invalid size ~s" size)) - - (define (invalid-size-or-index who size v i) - (if (and (fixnum? i) ($fxu< i (bytevector-length v))) - (if ($fxu< size (bytevector-length v)) - ($oops who "invalid index ~s for ~s-byte field of bytevector ~s" i size v) - ($oops who "invalid size ~s for bytevector ~s" size v)) - (invalid-index who v i))) - - (define (fill? x) (and (fixnum? x) (fx<= -128 x 255))) - - (define-syntax unaligned-ref-check - (syntax-rules () - [(_ who ?size v i) - (let ([size ?size]) - (unless (and (fixnum? i) - (fx>= i 0) - (fx< i (fx- (bytevector-length v) (fx- size 1)))) - (invalid-size-or-index who size v i)))])) - - (module ($bytevector-sint-little-ref $bytevector-uint-little-ref) - (define (load-little v i size a) - (cond - [(fx>= size 3) - (load-little v (fx- i 3) (fx- size 3) - (logor (ash a 24) - (fxlogor - (fxsll (bytevector-u8-ref v i) 16) - (fxsll (bytevector-u8-ref v (fx- i 1)) 8) - (bytevector-u8-ref v (fx- i 2)))))] - [(fx= size 0) a] - [(fx= size 1) (logor (ash a 8) (bytevector-u8-ref v i))] - [else (logor (ash a 16) - (fxlogor - (fxsll (bytevector-u8-ref v i) 8) - (bytevector-u8-ref v (fx- i 1))))])) - - (define ($bytevector-sint-little-ref v i size) - (let ([i (fx+ i size -1)]) - (load-little v (fx- i 1) (fx- size 1) (bytevector-s8-ref v i)))) - - (define ($bytevector-uint-little-ref v i size) - (let ([i (fx+ i size -1)]) - (load-little v (fx- i 1) (fx- size 1) (bytevector-u8-ref v i))))) - - (module ($bytevector-sint-big-ref $bytevector-uint-big-ref) - (define (load-big v i size a) - (cond - [(fx>= size 3) - (load-big v (fx+ i 3) (fx- size 3) - (logor (ash a 24) - (fxlogor - (fxsll (bytevector-u8-ref v i) 16) - (fxsll (bytevector-u8-ref v (fx+ i 1)) 8) - (bytevector-u8-ref v (fx+ i 2)))))] - [(fx= size 0) a] - [(fx= size 1) (logor (ash a 8) (bytevector-u8-ref v i))] - [else (logor (ash a 16) - (fxlogor - (fxsll (bytevector-u8-ref v i) 8) - (bytevector-u8-ref v (fx+ i 1))))])) - - (define ($bytevector-sint-big-ref v i size) - (load-big v (fx+ i 1) (fx- size 1) (bytevector-s8-ref v i))) - - (define ($bytevector-uint-big-ref v i size) - (load-big v (fx+ i 1) (fx- size 1) (bytevector-u8-ref v i)))) - - (define ($bytevector-int-little-set! v i k size) - (let store-little! ([i i] [k k] [size size]) - (cond - [(fx>= size 4) - (let ([k (logand k #xffffff)]) - (bytevector-u8-set! v i (fxlogand k #xff)) - (bytevector-u8-set! v (fx+ i 1) (fxlogand (fxsra k 8) #xff)) - (bytevector-u8-set! v (fx+ i 2) (fxsra k 16))) - (store-little! (fx+ i 3) (ash k -24) (fx- size 3))] - [(fx= size 1) ($bytevector-set! v i k)] - [(fx= size 2) - (bytevector-u8-set! v i (fxlogand k #xff)) - ($bytevector-set! v (fx+ i 1) (fxsra k 8))] - [else - (bytevector-u8-set! v i (fxlogand k #xff)) - (bytevector-u8-set! v (fx+ i 1) (fxlogand (fxsra k 8) #xff)) - ($bytevector-set! v (fx+ i 2) (fxsra k 16))]))) - - (define ($bytevector-int-big-set! v i k size) - (let store-big! ([i (fx+ i size -1)] [k k] [size size]) - (cond - [(fx>= size 4) - (let ([k (logand k #xffffff)]) - (bytevector-u8-set! v (fx- i 2) (fxsra k 16)) - (bytevector-u8-set! v (fx- i 1) (fxlogand (fxsra k 8) #xff)) - (bytevector-u8-set! v i (fxlogand k #xff))) - (store-big! (fx- i 3) (ash k -24) (fx- size 3))] - [(fx= size 1) ($bytevector-set! v i k)] - [(fx= size 2) - ($bytevector-set! v (fx- i 1) (fxsra k 8)) - (bytevector-u8-set! v i (fxlogand k #xff))] - [else - ($bytevector-set! v (fx- i 2) (fxsra k 16)) - (bytevector-u8-set! v (fx- i 1) (fxlogand (fxsra k 8) #xff)) - (bytevector-u8-set! v i (fxlogand k #xff))]))) - - (module ($bytevector-s16-ref $bytevector-u16-ref - $bytevector-s24-ref $bytevector-u24-ref - $bytevector-s32-ref $bytevector-u32-ref - $bytevector-s40-ref $bytevector-u40-ref - $bytevector-s48-ref $bytevector-u48-ref - $bytevector-s56-ref $bytevector-u56-ref - $bytevector-s64-ref $bytevector-u64-ref) - (meta-cond - [(fx> (constant fixnum-bits) 56) - (define logor56 fxlogor) - (define sll56 fxsll)] - [else - (define logor56 logor) - (define sll56 ash)]) - - (define (little-ref-s16 v i) - (fxlogor (fxsll (#3%bytevector-s8-ref v (fx+ i 1)) 8) - (#3%bytevector-u8-ref v i))) - (define (big-ref-s16 v i) - (fxlogor (fxsll (#3%bytevector-s8-ref v i) 8) - (#3%bytevector-u8-ref v (fx+ i 1)))) - (define (little-ref-u16 v i) - (fxlogor (fxsll (#3%bytevector-u8-ref v (fx+ i 1)) 8) - (#3%bytevector-u8-ref v i))) - (define (big-ref-u16 v i) - (fxlogor (fxsll (#3%bytevector-u8-ref v i) 8) - (#3%bytevector-u8-ref v (fx+ i 1)))) - (define (little-ref-s24 v i) - (fxlogor (fxsll (#3%bytevector-s8-ref v (fx+ i 2)) 16) - (little-ref-u16 v i))) - (define (big-ref-s24 v i) - (fxlogor (fxsll (#3%bytevector-s8-ref v i) 16) - (big-ref-u16 v (fx+ i 1)))) - (define (little-ref-u24 v i) - (fxlogor (fxsll (#3%bytevector-u8-ref v (fx+ i 2)) 16) - (little-ref-u16 v i))) - (define (big-ref-u24 v i) - (fxlogor (fxsll (#3%bytevector-u8-ref v i) 16) - (big-ref-u16 v (fx+ i 1)))) - (define (little-ref-s32 v i) - (logor56 (sll56 (little-ref-s16 v (fx+ i 2)) 16) - (little-ref-u16 v i))) - (define (big-ref-s32 v i) - (logor56 (sll56 (big-ref-s16 v i) 16) - (big-ref-u16 v (fx+ i 2)))) - (define (little-ref-u32 v i) - (logor56 (sll56 (little-ref-u16 v (fx+ i 2)) 16) - (little-ref-u16 v i))) - (define (big-ref-u32 v i) - (logor56 (sll56 (big-ref-u16 v i) 16) - (big-ref-u16 v (fx+ i 2)))) - (define (little-ref-s40 v i) - (logor56 (sll56(#3%bytevector-s8-ref v (fx+ i 4)) 32) - (little-ref-u32 v i))) - (define (big-ref-s40 v i) - (logor56 (sll56(#3%bytevector-s8-ref v i) 32) - (big-ref-u32 v (fx+ i 1)))) - (define (little-ref-u40 v i) - (logor56 (sll56(#3%bytevector-u8-ref v (fx+ i 4)) 32) - (little-ref-u32 v i))) - (define (big-ref-u40 v i) - (logor56 (sll56(#3%bytevector-u8-ref v i) 32) - (big-ref-u32 v (fx+ i 1)))) - (define (little-ref-s48 v i) - (logor56 (sll56(little-ref-s16 v (fx+ i 4)) 32) - (little-ref-u32 v i))) - (define (big-ref-s48 v i) - (logor56 (sll56(big-ref-s16 v i) 32) - (big-ref-u32 v (fx+ i 2)))) - (define (little-ref-u48 v i) - (logor56 (sll56(little-ref-u16 v (fx+ i 4)) 32) - (little-ref-u32 v i))) - (define (big-ref-u48 v i) - (logor56 (sll56(big-ref-u16 v i) 32) - (big-ref-u32 v (fx+ i 2)))) - (define (little-ref-s56 v i) - (logor56 (sll56(little-ref-s24 v (fx+ i 4)) 32) - (little-ref-u32 v i))) - (define (big-ref-s56 v i) - (logor56 (sll56(big-ref-s24 v i) 32) - (big-ref-u32 v (fx+ i 3)))) - (define (little-ref-u56 v i) - (logor56 (sll56(little-ref-u24 v (fx+ i 4)) 32) - (little-ref-u32 v i))) - (define (big-ref-u56 v i) - (logor56 (sll56(big-ref-u24 v i) 32) - (big-ref-u32 v (fx+ i 3)))) - (define (little-ref-s64 v i) - (logor (ash (little-ref-s32 v (fx+ i 4)) 32) - (little-ref-u32 v i))) - (define (big-ref-s64 v i) - (logor (ash (big-ref-s32 v i) 32) - (big-ref-u32 v (fx+ i 4)))) - (define (little-ref-u64 v i) - (logor (ash (little-ref-u32 v (fx+ i 4)) 32) - (little-ref-u32 v i))) - (define (big-ref-u64 v i) - (logor (ash (big-ref-u32 v i) 32) - (big-ref-u32 v (fx+ i 4)))) - - (define-syntax bytevector-*-ref - (lambda (x) - (define p2? - (lambda (n) - (let f ([i 1]) - (or (fx= i n) - (and (not (fx> i n)) (f (fxsll i 1))))))) - (syntax-case x () - [(kwd s/u bits) - (with-syntax ([prim-name (construct-name #'kwd "bytevector-" #'s/u #'bits "-ref")] - [native-name (construct-name #'kwd "bytevector-" #'s/u #'bits "-native-ref")] - [little-ref (construct-name #'kwd "little-ref-" #'s/u #'bits)] - [big-ref (construct-name #'kwd "big-ref-" #'s/u #'bits)]) - #`(lambda (v i eness who) - (unless (bytevector? v) (not-a-bytevector who v)) - (unaligned-ref-check who (fxquotient bits 8) v i) - (case eness - [(big) - #,(cond - [(constant unaligned-integers) #`(#3%prim-name v i 'big)] - [(and (eq? (constant native-endianness) 'big) (p2? (datum bits))) - #`(if (fx= (fxlogand i (fx- (fxquotient bits 8) 1)) 0) - (#3%native-name v i) - (big-ref v i))] - [else #`(big-ref v i)])] - [(little) - #,(cond - [(constant unaligned-integers) #`(#3%prim-name v i 'little)] - [(and (eq? (constant native-endianness) 'little) (p2? (datum bits))) - #`(if (fx= (fxlogand i (fx- (fxquotient bits 8) 1)) 0) - (#3%native-name v i) - (little-ref v i))] - [else #`(little-ref v i)])] - [else (unrecognized-endianness who eness)])))]))) - - (define $bytevector-s16-ref (bytevector-*-ref s 16)) - (define $bytevector-u16-ref (bytevector-*-ref u 16)) - (define $bytevector-s24-ref (bytevector-*-ref s 24)) - (define $bytevector-u24-ref (bytevector-*-ref u 24)) - (define $bytevector-s32-ref (bytevector-*-ref s 32)) - (define $bytevector-u32-ref (bytevector-*-ref u 32)) - (define $bytevector-s40-ref (bytevector-*-ref s 40)) - (define $bytevector-u40-ref (bytevector-*-ref u 40)) - (define $bytevector-s48-ref (bytevector-*-ref s 48)) - (define $bytevector-u48-ref (bytevector-*-ref u 48)) - (define $bytevector-s56-ref (bytevector-*-ref s 56)) - (define $bytevector-u56-ref (bytevector-*-ref u 56)) - (define $bytevector-s64-ref (bytevector-*-ref s 64)) - (define $bytevector-u64-ref (bytevector-*-ref u 64)) - ) - - (module ($bytevector-s16-set! $bytevector-u16-set! - $bytevector-s24-set! $bytevector-u24-set! - $bytevector-s32-set! $bytevector-u32-set! - $bytevector-s40-set! $bytevector-u40-set! - $bytevector-s48-set! $bytevector-u48-set! - $bytevector-s56-set! $bytevector-u56-set! - $bytevector-s64-set! $bytevector-u64-set!) - (meta-cond - [(fx> (constant fixnum-bits) 56) - (define logand56 fxlogand) - (define sra56 fxsra)] - [else - (define logand56 logand) - (define sra56 (lambda (x y) (ash x (fx- y))))]) - - (define (little-set-s16! v i k) - (#3%bytevector-u8-set! v i (fxlogand k #xff)) - (#3%bytevector-s8-set! v (fx+ i 1) (fxsra k 8))) - (define (big-set-s16! v i k) - (#3%bytevector-s8-set! v i (fxsra k 8)) - (#3%bytevector-u8-set! v (fx+ i 1) (fxlogand k #xff))) - (define (little-set-u16! v i k) - (#3%bytevector-u8-set! v i (fxlogand k #xff)) - (#3%bytevector-u8-set! v (fx+ i 1) (fxsra k 8))) - (define (big-set-u16! v i k) - (#3%bytevector-u8-set! v i (fxsra k 8)) - (#3%bytevector-u8-set! v (fx+ i 1) (fxlogand k #xff))) - (define (little-set-s24! v i k) - (little-set-u16! v i (fxlogand k #xffff)) - (#3%bytevector-s8-set! v (fx+ i 2) (fxsra k 16))) - (define (big-set-s24! v i k) - (#3%bytevector-s8-set! v i (fxsra k 16)) - (big-set-u16! v (fx+ i 1) (fxlogand k #xffff))) - (define (little-set-u24! v i k) - (little-set-u16! v i (fxlogand k #xffff)) - (#3%bytevector-u8-set! v (fx+ i 2) (fxsra k 16))) - (define (big-set-u24! v i k) - (#3%bytevector-u8-set! v i (fxsra k 16)) - (big-set-u16! v (fx+ i 1) (fxlogand k #xffff))) - (define (little-set-s32! v i k) - (little-set-u16! v i (logand56 k #xffff)) - (little-set-s16! v (fx+ i 2) (sra56 k 16))) - (define (big-set-s32! v i k) - (big-set-s16! v i (sra56 k 16)) - (big-set-u16! v (fx+ i 2) (logand56 k #xffff))) - (define (little-set-u32! v i k) - (little-set-u16! v i (logand56 k #xffff)) - (little-set-u16! v (fx+ i 2) (sra56 k 16))) - (define (big-set-u32! v i k) - (big-set-u16! v i (sra56 k 16)) - (big-set-u16! v (fx+ i 2) (logand56 k #xffff))) - (define (little-set-s40! v i k) - (little-set-u32! v i (logand56 k #xffffffff)) - (#3%bytevector-s8-set! v (fx+ i 4) (sra56 k 32))) - (define (big-set-s40! v i k) - (#3%bytevector-s8-set! v i (sra56 k 32)) - (big-set-u32! v (fx+ i 1) (logand56 k #xffffffff))) - (define (little-set-u40! v i k) - (little-set-u32! v i (logand56 k #xffffffff)) - (#3%bytevector-u8-set! v (fx+ i 4) (sra56 k 32))) - (define (big-set-u40! v i k) - (#3%bytevector-u8-set! v i (sra56 k 32)) - (big-set-u32! v (fx+ i 1) (logand56 k #xffffffff))) - (define (little-set-s48! v i k) - (little-set-u32! v i (logand56 k #xffffffff)) - (little-set-s16! v (fx+ i 4) (sra56 k 32))) - (define (big-set-s48! v i k) - (big-set-s16! v i (sra56 k 32)) - (big-set-u32! v (fx+ i 2) (logand56 k #xffffffff))) - (define (little-set-u48! v i k) - (little-set-u32! v i (logand56 k #xffffffff)) - (little-set-u16! v (fx+ i 4) (sra56 k 32))) - (define (big-set-u48! v i k) - (big-set-u16! v i (sra56 k 32)) - (big-set-u32! v (fx+ i 2) (logand56 k #xffffffff))) - (define (little-set-s56! v i k) - (little-set-u32! v i (logand56 k #xffffffff)) - (little-set-s24! v (fx+ i 4) (sra56 k 32))) - (define (big-set-s56! v i k) - (big-set-s24! v i (sra56 k 32)) - (big-set-u32! v (fx+ i 3) (logand56 k #xffffffff))) - (define (little-set-u56! v i k) - (little-set-u32! v i (logand56 k #xffffffff)) - (little-set-u24! v (fx+ i 4) (sra56 k 32))) - (define (big-set-u56! v i k) - (big-set-u24! v i (sra56 k 32)) - (big-set-u32! v (fx+ i 3) (logand56 k #xffffffff))) - (define (little-set-s64! v i k) - (little-set-u32! v i (logand k #xffffffff)) - (little-set-s32! v (fx+ i 4) (ash k -32))) - (define (big-set-s64! v i k) - (big-set-s32! v i (ash k -32)) - (big-set-u32! v (fx+ i 4) (logand k #xffffffff))) - (define (little-set-u64! v i k) - (little-set-u32! v i (logand k #xffffffff)) - (little-set-u32! v (fx+ i 4) (ash k -32))) - (define (big-set-u64! v i k) - (big-set-u32! v i (ash k -32)) - (big-set-u32! v (fx+ i 4) (logand k #xffffffff))) - - (define-syntax bytevector-*-set! - (lambda (x) - (define p2? - (lambda (n) - (let f ([i 1]) - (or (fx= i n) - (and (not (fx> i n)) (f (fxsll i 1))))))) - (syntax-case x () - [(kwd s/u bits) - (with-syntax ([prim-name (construct-name #'kwd "bytevector-" #'s/u #'bits "-set!")] - [native-name (construct-name #'kwd "bytevector-" #'s/u #'bits "-native-set!")] - [little-set! (construct-name #'kwd "little-set-" #'s/u #'bits "!")] - [big-set! (construct-name #'kwd "big-set-" #'s/u #'bits "!")] - [value-pred (if (free-identifier=? #'s/u #'s) - #'signed-value-pred - #'unsigned-value-pred)]) - #`(let ([value-okay? (value-pred bits)]) - (lambda (v i k eness who) - (unless (mutable-bytevector? v) (not-a-mutable-bytevector who v)) - (unaligned-ref-check who (fxquotient bits 8) v i) - (unless (value-okay? k) (invalid-value who k)) - (case eness - [(big) - #,(cond - [(and (constant unaligned-integers) (>= (constant ptr-bits) (datum bits))) - #`(#3%prim-name v i k 'big)] - [(and (eq? (constant native-endianness) 'big) (fx>= (constant ptr-bits) (datum bits)) (p2? (datum bits))) - #`(if (fx= (fxlogand i (fx- (fxquotient bits 8) 1)) 0) - (#3%native-name v i k) - (big-set! v i k))] - [else #`(big-set! v i k)])] - [(little) - #,(cond - [(and (constant unaligned-integers) (>= (constant ptr-bits) (datum bits))) - #`(#3%prim-name v i k 'little)] - [(and (eq? (constant native-endianness) 'little) (fx>= (constant ptr-bits) (datum bits)) (p2? (datum bits))) - #`(if (fx= (fxlogand i (fx- (fxquotient bits 8) 1)) 0) - (#3%native-name v i k) - (little-set! v i k))] - [else #`(little-set! v i k)])] - [else (unrecognized-endianness who eness)]))))]))) - - (define $bytevector-s16-set! (bytevector-*-set! s 16)) - (define $bytevector-u16-set! (bytevector-*-set! u 16)) - (define $bytevector-s24-set! (bytevector-*-set! s 24)) - (define $bytevector-u24-set! (bytevector-*-set! u 24)) - (define $bytevector-s32-set! (bytevector-*-set! s 32)) - (define $bytevector-u32-set! (bytevector-*-set! u 32)) - (define $bytevector-s40-set! (bytevector-*-set! s 40)) - (define $bytevector-u40-set! (bytevector-*-set! u 40)) - (define $bytevector-s48-set! (bytevector-*-set! s 48)) - (define $bytevector-u48-set! (bytevector-*-set! u 48)) - (define $bytevector-s56-set! (bytevector-*-set! s 56)) - (define $bytevector-u56-set! (bytevector-*-set! u 56)) - (define $bytevector-s64-set! (bytevector-*-set! s 64)) - (define $bytevector-u64-set! (bytevector-*-set! u 64)) - ) - - (set! native-endianness - (lambda () - (#2%native-endianness))) - - (set-who! make-bytevector - (case-lambda - [(n fill) - (unless (and (fixnum? n) (not ($fxu< (constant maximum-bytevector-length) n))) - ($oops who "~s is not a valid bytevector length" n)) - (unless (fill? fill) (invalid-fill-value who fill)) - (#3%make-bytevector n fill)] - [(n) - (unless (and (fixnum? n) (not ($fxu< (constant maximum-bytevector-length) n))) - ($oops who "~s is not a valid bytevector length" n)) - (#3%make-bytevector n)])) - - (set! bytevector? (lambda (x) (#2%bytevector? x))) - - (set! bytevector-length - (lambda (v) - (#2%bytevector-length v))) - - (set-who! $bytevector-set-immutable! - (lambda (v) - (unless (bytevector? v) - ($oops who "~s is not a bytevector" v)) - (#3%$bytevector-set-immutable! v))) - - (set-who! mutable-bytevector? - (lambda (v) - (#3%mutable-bytevector? v))) - - (set-who! immutable-bytevector? - (lambda (v) - (#3%immutable-bytevector? v))) - - (set! bytevector-s8-ref - (lambda (v i) - (#2%bytevector-s8-ref v i))) - - (set! bytevector-u8-ref - (lambda (v i) - (#2%bytevector-u8-ref v i))) - - (set! bytevector-s8-set! - (lambda (v i byte) - (#2%bytevector-s8-set! v i byte))) - - (set! bytevector-u8-set! - (lambda (v i octet) - (#2%bytevector-u8-set! v i octet))) - - (set-who! $bytevector-set! - (lambda (v i fill) - (if ($bytevector-set!-check? 8 v i) - (begin - (unless (fill? fill) (invalid-value who fill)) - (#3%$bytevector-set! v i fill)) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v))))) - - (set-who! bytevector-s16-native-ref - (lambda (v i) - (if ($bytevector-ref-check? 16 v i) - (#3%bytevector-s16-native-ref v i) - (if (bytevector? v) - (invalid-index who v i) - (not-a-bytevector who v))))) - - (set-who! bytevector-u16-native-ref - (lambda (v i) - (if ($bytevector-ref-check? 16 v i) - (#3%bytevector-u16-native-ref v i) - (if (bytevector? v) - (invalid-index who v i) - (not-a-bytevector who v))))) - - (set-who! bytevector-s16-native-set! - (let ([value-okay? (signed-value-pred 16)]) - (lambda (v i k) - (if ($bytevector-set!-check? 16 v i) - (begin - (unless (value-okay? k) (invalid-value who k)) - (#3%bytevector-s16-native-set! v i k)) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v)))))) - - (set-who! bytevector-u16-native-set! - (let ([value-okay? (unsigned-value-pred 16)]) - (lambda (v i k) - (if ($bytevector-set!-check? 16 v i) - (begin - (unless (value-okay? k) (invalid-value who k)) - (#3%bytevector-u16-native-set! v i k)) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v)))))) - - (set-who! bytevector-s32-native-ref - (lambda (v i) - (if ($bytevector-ref-check? 32 v i) - (#3%bytevector-s32-native-ref v i) - (if (bytevector? v) - (invalid-index who v i) - (not-a-bytevector who v))))) - - (set-who! bytevector-u32-native-ref - (lambda (v i) - (if ($bytevector-ref-check? 32 v i) - (#3%bytevector-u32-native-ref v i) - (if (bytevector? v) - (invalid-index who v i) - (not-a-bytevector who v))))) - - (set-who! bytevector-s32-native-set! - (let ([value-okay? (signed-value-pred 32)]) - (lambda (v i k) - (if ($bytevector-set!-check? 32 v i) - (begin - (unless (value-okay? k) (invalid-value who k)) - (#3%bytevector-s32-native-set! v i k)) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v)))))) - - (set-who! bytevector-u32-native-set! - (let ([value-okay? (unsigned-value-pred 32)]) - (lambda (v i k) - (if ($bytevector-set!-check? 32 v i) - (begin - (unless (value-okay? k) (invalid-value who k)) - (#3%bytevector-u32-native-set! v i k)) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v)))))) - - (set-who! bytevector-s64-native-ref - (lambda (v i) - (if ($bytevector-ref-check? 64 v i) - (constant-case ptr-bits - [(64) (#3%bytevector-s64-native-ref v i)] - [(32) - (constant-case native-endianness - [(big) - (logor (ash (#3%bytevector-s32-native-ref v i) 32) - (#3%bytevector-u32-native-ref v (fx+ i 4)))] - [(little) - (logor (ash (#3%bytevector-s32-native-ref v (fx+ i 4)) 32) - (#3%bytevector-u32-native-ref v i))])]) - (if (bytevector? v) - (invalid-index who v i) - (not-a-bytevector who v))))) - - (set-who! bytevector-u64-native-ref - (lambda (v i) - (if ($bytevector-ref-check? 64 v i) - (constant-case ptr-bits - [(64) (#3%bytevector-u64-native-ref v i)] - [(32) - (constant-case native-endianness - [(big) - (logor (ash (#3%bytevector-u32-native-ref v i) 32) - (#3%bytevector-u32-native-ref v (fx+ i 4)))] - [(little) - (logor (ash (#3%bytevector-u32-native-ref v (fx+ i 4)) 32) - (#3%bytevector-u32-native-ref v i))])]) - (if (bytevector? v) - (invalid-index who v i) - (not-a-bytevector who v))))) - - (set-who! bytevector-s64-native-set! - (let ([value-okay? (signed-value-pred 64)]) - (lambda (v i k) - (if ($bytevector-set!-check? 64 v i) - (begin - (unless (value-okay? k) (invalid-value who k)) - (constant-case ptr-bits - [(64) (#3%bytevector-s64-native-set! v i k)] - [(32) - (constant-case native-endianness - [(big) - (#3%bytevector-s32-native-set! v i (ash k -32)) - (#3%bytevector-u32-native-set! v (fx+ i 4) (logand k (- (expt 2 32) 1)))] - [(little) - (#3%bytevector-s32-native-set! v (fx+ i 4) (ash k -32)) - (#3%bytevector-u32-native-set! v i (logand k (- (expt 2 32) 1)))])])) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v)))))) - - (set-who! bytevector-u64-native-set! - (let ([value-okay? (unsigned-value-pred 64)]) - (lambda (v i k) - (if ($bytevector-set!-check? 64 v i) - (begin - (unless (value-okay? k) (invalid-value who k)) - (constant-case ptr-bits - [(64) (#3%bytevector-u64-native-set! v i k)] - [(32) - (constant-case native-endianness - [(big) - (#3%bytevector-u32-native-set! v i (ash k -32)) - (#3%bytevector-u32-native-set! v (fx+ i 4) (logand k (- (expt 2 32) 1)))] - [(little) - (#3%bytevector-u32-native-set! v (fx+ i 4) (ash k -32)) - (#3%bytevector-u32-native-set! v i (logand k (- (expt 2 32) 1)))])])) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v)))))) - - (set-who! bytevector-ieee-single-native-ref - (lambda (v i) - (if ($bytevector-ref-check? 32 v i) - (#3%bytevector-ieee-single-native-ref v i) - (if (bytevector? v) - (invalid-index who v i) - (not-a-bytevector who v))))) - - (set-who! bytevector-ieee-double-native-ref - (lambda (v i) - (if ($bytevector-ref-check? 64 v i) - (#3%bytevector-ieee-double-native-ref v i) - (if (bytevector? v) - (invalid-index who v i) - (not-a-bytevector who v))))) - - (set-who! bytevector-ieee-single-native-set! - (lambda (v i x) - (if ($bytevector-set!-check? 32 v i) - ; inline routine checks to make sure x is a real number - (#3%bytevector-ieee-single-native-set! v i x) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v))))) - - (set-who! bytevector-ieee-double-native-set! - (lambda (v i x) - (if ($bytevector-set!-check? 64 v i) - ; inline routine checks to make sure x is a real number - (#3%bytevector-ieee-double-native-set! v i x) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v))))) - - (set-who! bytevector-copy - (lambda (v) - (unless (bytevector? v) (not-a-bytevector who v)) - (let* ([n (bytevector-length v)] [v2 (make-bytevector n)]) - ($ptr-copy! v (constant bytevector-data-disp) v2 - (constant bytevector-data-disp) - (fxsrl - (fx+ n (fx- (constant ptr-bytes) 1)) - (constant log2-ptr-bytes))) - v2))) - - (set-who! bytevector-copy! - (lambda (v1 i1 v2 i2 k) - (unless (bytevector? v1) (not-a-bytevector who v1)) - (unless (mutable-bytevector? v2) (not-a-mutable-bytevector who v2)) - (let ([n1 (bytevector-length v1)] [n2 (bytevector-length v2)]) - (unless (and (fixnum? i1) (fx>= i1 0)) - ($oops who "invalid start value ~s" i1)) - (unless (and (fixnum? i2) (fx>= i2 0)) - ($oops who "invalid start value ~s" i2)) - (unless (and (fixnum? k) (fx>= k 0)) - ($oops who "invalid count ~s" k)) - (unless (fx<= k (fx- n1 i1)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" i1 k v1)) - (unless (fx<= k (fx- n2 i2)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" i2 k v2)) - ; whew! - (#3%bytevector-copy! v1 i1 v2 i2 k)))) - - (set-who! bytevector->immutable-bytevector - (lambda (v) - (cond - [(immutable-bytevector? v) v] - [(eqv? v '#vu8()) ($tc-field 'null-immutable-bytevector ($tc))] - [else - (unless (bytevector? v) ($oops who "~s is not a bytevector" v)) - (let ([v2 (bytevector-copy v)]) - ($bytevector-set-immutable! v2) - v2)]))) - - (set-who! bytevector-fill! - (lambda (v fill) - (unless (mutable-bytevector? v) (not-a-mutable-bytevector who v)) - (unless (fill? fill) (invalid-fill-value who fill)) - (#3%bytevector-fill! v fill))) - - (set-who! bytevector=? - (lambda (v1 v2) - (unless (bytevector? v1) (not-a-bytevector who v1)) - (unless (bytevector? v2) (not-a-bytevector who v2)) - (#3%bytevector=? v1 v2))) - - (set-who! $bytevector-ref-check? - (lambda (bits v i) - ; inlined handles only constant bits argument - (case bits - [(8) (#2%$bytevector-ref-check? 8 v i)] - [(16) (#2%$bytevector-ref-check? 16 v i)] - [(32) (#2%$bytevector-ref-check? 32 v i)] - [(64) (#2%$bytevector-ref-check? 64 v i)] - [else ($oops who "invalid bits argument ~s" bits)]))) - - (set-who! $bytevector-set!-check? - (lambda (bits v i) - ; inlined handles only constant bits argument - (case bits - [(8) (#2%$bytevector-set!-check? 8 v i)] - [(16) (#2%$bytevector-set!-check? 16 v i)] - [(32) (#2%$bytevector-set!-check? 32 v i)] - [(64) (#2%$bytevector-set!-check? 64 v i)] - [else ($oops who "invalid bits argument ~s" bits)]))) - - (set-who! bytevector-s16-ref - (lambda (v i eness) - ($bytevector-s16-ref v i eness who))) - - (set-who! bytevector-u16-ref - (lambda (v i eness) - ($bytevector-u16-ref v i eness who))) - - (set-who! bytevector-s24-ref - (lambda (v i eness) - ($bytevector-s24-ref v i eness who))) - - (set-who! bytevector-u24-ref - (lambda (v i eness) - ($bytevector-u24-ref v i eness who))) - - (set-who! bytevector-s32-ref - (lambda (v i eness) - ($bytevector-s32-ref v i eness who))) - - (set-who! bytevector-u32-ref - (lambda (v i eness) - ($bytevector-u32-ref v i eness who))) - - (set-who! bytevector-s40-ref - (lambda (v i eness) - ($bytevector-s40-ref v i eness who))) - - (set-who! bytevector-u40-ref - (lambda (v i eness) - ($bytevector-u40-ref v i eness who))) - - (set-who! bytevector-s48-ref - (lambda (v i eness) - ($bytevector-s48-ref v i eness who))) - - (set-who! bytevector-u48-ref - (lambda (v i eness) - ($bytevector-u48-ref v i eness who))) - - (set-who! bytevector-s56-ref - (lambda (v i eness) - ($bytevector-s56-ref v i eness who))) - - (set-who! bytevector-u56-ref - (lambda (v i eness) - ($bytevector-u56-ref v i eness who))) - - (set-who! bytevector-s64-ref - (lambda (v i eness) - ($bytevector-s64-ref v i eness who))) - - (set-who! bytevector-u64-ref - (lambda (v i eness) - ($bytevector-u64-ref v i eness who))) - - (set-who! bytevector-s16-set! - (lambda (v i k eness) - ($bytevector-s16-set! v i k eness who))) - - (set-who! bytevector-u16-set! - (lambda (v i k eness) - ($bytevector-u16-set! v i k eness who))) - - (set-who! bytevector-s24-set! - (lambda (v i k eness) - ($bytevector-s24-set! v i k eness who))) - - (set-who! bytevector-u24-set! - (lambda (v i k eness) - ($bytevector-u24-set! v i k eness who))) - - (set-who! bytevector-s32-set! - (lambda (v i k eness) - ($bytevector-s32-set! v i k eness who))) - - (set-who! bytevector-u32-set! - (lambda (v i k eness) - ($bytevector-u32-set! v i k eness who))) - - (set-who! bytevector-s40-set! - (lambda (v i k eness) - ($bytevector-s40-set! v i k eness who))) - - (set-who! bytevector-u40-set! - (lambda (v i k eness) - ($bytevector-u40-set! v i k eness who))) - - (set-who! bytevector-s48-set! - (lambda (v i k eness) - ($bytevector-s48-set! v i k eness who))) - - (set-who! bytevector-u48-set! - (lambda (v i k eness) - ($bytevector-u48-set! v i k eness who))) - - (set-who! bytevector-s56-set! - (lambda (v i k eness) - ($bytevector-s56-set! v i k eness who))) - - (set-who! bytevector-u56-set! - (lambda (v i k eness) - ($bytevector-u56-set! v i k eness who))) - - (set-who! bytevector-s64-set! - (lambda (v i k eness) - ($bytevector-s64-set! v i k eness who))) - - (set-who! bytevector-u64-set! - (lambda (v i k eness) - ($bytevector-u64-set! v i k eness who))) - - (set-who! bytevector-ieee-single-ref - (lambda (v i eness) - (define (swap-ref v i) - (bytevector-ieee-single-native-ref - (bytevector - (bytevector-u8-ref v (fx+ i 3)) - (bytevector-u8-ref v (fx+ i 2)) - (bytevector-u8-ref v (fx+ i 1)) - (bytevector-u8-ref v i)) - 0)) - (define (noswap-ref v i) - (bytevector-ieee-single-native-ref - (bytevector - (bytevector-u8-ref v i) - (bytevector-u8-ref v (fx+ i 1)) - (bytevector-u8-ref v (fx+ i 2)) - (bytevector-u8-ref v (fx+ i 3))) - 0)) - (unless (bytevector? v) (not-a-bytevector who v)) - (unaligned-ref-check who 4 v i) - (if (or (constant unaligned-floats) (fx= (fxlogand i 3) 0)) - (if (eq? eness (native-endianness)) - (#3%bytevector-ieee-single-native-ref v i) - (if (constant-case native-endianness - [(little) (eq? eness 'big)] - [(big) (eq? eness 'little)]) - (swap-ref v i) - (unrecognized-endianness who eness))) - (if (eq? eness (native-endianness)) - (noswap-ref v i) - (if (constant-case native-endianness - [(little) (eq? eness 'big)] - [(big) (eq? eness 'little)]) - (swap-ref v i) - (unrecognized-endianness who eness)))))) - - (set-who! bytevector-ieee-double-ref - (lambda (v i eness) - (define (swap-ref v i) - (bytevector-ieee-double-native-ref - (bytevector - (bytevector-u8-ref v (fx+ i 7)) - (bytevector-u8-ref v (fx+ i 6)) - (bytevector-u8-ref v (fx+ i 5)) - (bytevector-u8-ref v (fx+ i 4)) - (bytevector-u8-ref v (fx+ i 3)) - (bytevector-u8-ref v (fx+ i 2)) - (bytevector-u8-ref v (fx+ i 1)) - (bytevector-u8-ref v i)) - 0)) - (define (noswap-ref v i) - (bytevector-ieee-double-native-ref - (bytevector - (bytevector-u8-ref v i) - (bytevector-u8-ref v (fx+ i 1)) - (bytevector-u8-ref v (fx+ i 2)) - (bytevector-u8-ref v (fx+ i 3)) - (bytevector-u8-ref v (fx+ i 4)) - (bytevector-u8-ref v (fx+ i 5)) - (bytevector-u8-ref v (fx+ i 6)) - (bytevector-u8-ref v (fx+ i 7))) - 0)) - (unless (bytevector? v) (not-a-bytevector who v)) - (unaligned-ref-check who 8 v i) - (if (or (constant unaligned-floats) (fx= (fxlogand i 7) 0)) - (if (eq? eness (native-endianness)) - (#3%bytevector-ieee-double-native-ref v i) - (if (constant-case native-endianness - [(little) (eq? eness 'big)] - [(big) (eq? eness 'little)]) - (swap-ref v i) - (unrecognized-endianness who eness))) - (if (eq? eness (native-endianness)) - (noswap-ref v i) - (if (constant-case native-endianness - [(little) (eq? eness 'big)] - [(big) (eq? eness 'little)]) - (swap-ref v i) - (unrecognized-endianness who eness)))))) - - (set-who! bytevector-ieee-single-set! - (lambda (v i x eness) - (define (swap-set! v i x) - (let ([v2 (make-bytevector 4)]) - (bytevector-ieee-single-native-set! v2 0 x) - (bytevector-u8-set! v i (bytevector-u8-ref v2 3)) - (bytevector-u8-set! v (fx+ i 1) (bytevector-u8-ref v2 2)) - (bytevector-u8-set! v (fx+ i 2) (bytevector-u8-ref v2 1)) - (bytevector-u8-set! v (fx+ i 3) (bytevector-u8-ref v2 0)))) - (define (noswap-set! v i x) - (let ([v2 (make-bytevector 4)]) - (bytevector-ieee-single-native-set! v2 0 x) - (bytevector-u8-set! v i (bytevector-u8-ref v2 0)) - (bytevector-u8-set! v (fx+ i 1) (bytevector-u8-ref v2 1)) - (bytevector-u8-set! v (fx+ i 2) (bytevector-u8-ref v2 2)) - (bytevector-u8-set! v (fx+ i 3) (bytevector-u8-ref v2 3)))) - (unless (mutable-bytevector? v) (not-a-mutable-bytevector who v)) - (unaligned-ref-check who 4 v i) - (let ([x ($real->flonum x who)]) - (if (or (constant unaligned-floats) (fx= (fxlogand i 3) 0)) - (if (eq? eness (native-endianness)) - (#3%bytevector-ieee-single-native-set! v i x) - (if (constant-case native-endianness - [(little) (eq? eness 'big)] - [(big) (eq? eness 'little)]) - (swap-set! v i x) - (unrecognized-endianness who eness))) - (if (eq? eness (native-endianness)) - (noswap-set! v i x) - (if (constant-case native-endianness - [(little) (eq? eness 'big)] - [(big) (eq? eness 'little)]) - (swap-set! v i x) - (unrecognized-endianness who eness))))))) - - (set-who! bytevector-ieee-double-set! - (lambda (v i x eness) - (define (swap-set! v i x) - (let ([v2 (make-bytevector 8)]) - (bytevector-ieee-double-native-set! v2 0 x) - (bytevector-u8-set! v i (bytevector-u8-ref v2 7)) - (bytevector-u8-set! v (fx+ i 1) (bytevector-u8-ref v2 6)) - (bytevector-u8-set! v (fx+ i 2) (bytevector-u8-ref v2 5)) - (bytevector-u8-set! v (fx+ i 3) (bytevector-u8-ref v2 4)) - (bytevector-u8-set! v (fx+ i 4) (bytevector-u8-ref v2 3)) - (bytevector-u8-set! v (fx+ i 5) (bytevector-u8-ref v2 2)) - (bytevector-u8-set! v (fx+ i 6) (bytevector-u8-ref v2 1)) - (bytevector-u8-set! v (fx+ i 7) (bytevector-u8-ref v2 0)))) - (define (noswap-set! v i x) - (let ([v2 (make-bytevector 8)]) - (bytevector-ieee-double-native-set! v2 0 x) - (bytevector-u8-set! v i (bytevector-u8-ref v2 0)) - (bytevector-u8-set! v (fx+ i 1) (bytevector-u8-ref v2 1)) - (bytevector-u8-set! v (fx+ i 2) (bytevector-u8-ref v2 2)) - (bytevector-u8-set! v (fx+ i 3) (bytevector-u8-ref v2 3)) - (bytevector-u8-set! v (fx+ i 4) (bytevector-u8-ref v2 4)) - (bytevector-u8-set! v (fx+ i 5) (bytevector-u8-ref v2 5)) - (bytevector-u8-set! v (fx+ i 6) (bytevector-u8-ref v2 6)) - (bytevector-u8-set! v (fx+ i 7) (bytevector-u8-ref v2 7)))) - (unless (mutable-bytevector? v) (not-a-mutable-bytevector who v)) - (unaligned-ref-check who 8 v i) - (let ([x ($real->flonum x who)]) - (if (or (constant unaligned-floats) (fx= (fxlogand i 7) 0)) - (if (eq? eness (native-endianness)) - (#3%bytevector-ieee-double-native-set! v i x) - (if (constant-case native-endianness - [(little) (eq? eness 'big)] - [(big) (eq? eness 'little)]) - (swap-set! v i x) - (unrecognized-endianness who eness))) - (if (eq? eness (native-endianness)) - (noswap-set! v i x) - (if (constant-case native-endianness - [(little) (eq? eness 'big)] - [(big) (eq? eness 'little)]) - (swap-set! v i x) - (unrecognized-endianness who eness))))))) - - (let () - (define ($bytevector-s8-ref v i eness who) - (if ($bytevector-ref-check? 8 v i) - (begin - (unless (memq eness '(little big)) (unrecognized-endianness who eness)) - (#3%bytevector-s8-ref v i)) - (if (bytevector? v) - (invalid-index who v i) - (not-a-bytevector who v)))) - - (define ($bytevector-u8-ref v i eness who) - (if ($bytevector-ref-check? 8 v i) - (begin - (unless (memq eness '(little big)) (unrecognized-endianness who eness)) - (#3%bytevector-u8-ref v i)) - (if (bytevector? v) - (invalid-index who v i) - (not-a-bytevector who v)))) - - (set-who! bytevector-sint-ref - (lambda (v i eness size) - (case size - [(1) ($bytevector-s8-ref v i eness who)] - [(2) ($bytevector-s16-ref v i eness who)] - [(4) ($bytevector-s32-ref v i eness who)] - [(8) ($bytevector-s64-ref v i eness who)] - [else - (unless (bytevector? v) (not-a-bytevector who v)) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (unaligned-ref-check who size v i) - (case eness - [(big) ($bytevector-sint-big-ref v i size)] - [(little) ($bytevector-sint-little-ref v i size)] - [else (unrecognized-endianness who eness)])]))) - - (set-who! bytevector-uint-ref - (lambda (v i eness size) - (case size - [(1) ($bytevector-u8-ref v i eness who)] - [(2) ($bytevector-u16-ref v i eness who)] - [(4) ($bytevector-u32-ref v i eness who)] - [(8) ($bytevector-u64-ref v i eness who)] - [else - (unless (bytevector? v) (not-a-bytevector who v)) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (unaligned-ref-check who size v i) - (case eness - [(big) ($bytevector-uint-big-ref v i size)] - [(little) ($bytevector-uint-little-ref v i size)] - [else (unrecognized-endianness who eness)])])))) - - (let () - (define $bytevector-s8-set! - (let ([value-okay? (signed-value-pred 8)]) - (lambda (v i k eness who) - (if ($bytevector-set!-check? 8 v i) - (begin - (unless (value-okay? k) (invalid-value who k)) - (unless (memq eness '(little big)) (unrecognized-endianness who eness)) - (#3%bytevector-s8-set! v i k)) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v)))))) - - (define $bytevector-u8-set! - (let ([value-okay? (unsigned-value-pred 8)]) - (lambda (v i k eness who) - (if ($bytevector-set!-check? 8 v i) - (begin - (unless (value-okay? k) (invalid-value who k)) - (unless (memq eness '(little big)) (unrecognized-endianness who eness)) - (#3%bytevector-u8-set! v i k)) - (if (mutable-bytevector? v) - (invalid-index who v i) - (not-a-mutable-bytevector who v)))))) - - (set-who! bytevector-sint-set! - (lambda (v i k eness size) - (case size - [(1) ($bytevector-s8-set! v i k eness who)] - [(2) ($bytevector-s16-set! v i k eness who)] - [(4) ($bytevector-s32-set! v i k eness who)] - [(8) ($bytevector-s64-set! v i k eness who)] - [else - (unless (mutable-bytevector? v) (not-a-mutable-bytevector who v)) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (unaligned-ref-check who size v i) - (unless (and (or (fixnum? k) (bignum? k)) - (let ([k (ash k (fx- 1 (fx* size 8)))]) - (or (fx= k 0) (fx= k -1)))) - (invalid-value who k)) - (case eness - [(big) ($bytevector-int-big-set! v i k size)] - [(little) ($bytevector-int-little-set! v i k size)] - [else (unrecognized-endianness who eness)])]))) - - (set-who! bytevector-uint-set! - (lambda (v i k eness size) - (case size - [(1) ($bytevector-u8-set! v i k eness who)] - [(2) ($bytevector-u16-set! v i k eness who)] - [(4) ($bytevector-u32-set! v i k eness who)] - [(8) ($bytevector-u64-set! v i k eness who)] - [else - (unless (mutable-bytevector? v) (not-a-mutable-bytevector who v)) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (unaligned-ref-check who size v i) - (unless (and (or (fixnum? k) (bignum? k)) - (fx= (ash k (fx- (fx* size 8))) 0)) - (invalid-value who k)) - (case eness - [(big) ($bytevector-int-big-set! v i k size)] - [(little) ($bytevector-int-little-set! v i k size)] - [else (unrecognized-endianness who eness)])])))) - - (let () - (define-syntax bv->list - (syntax-rules () - [(_ bytes ref) - (lambda (v who) - (unless (bytevector? v) (not-a-bytevector who v)) - (let ([n (bytevector-length v)]) - (unless (fx= (fxlogand n (fx- bytes 1)) 0) - (size-multiple-error who n bytes)) - (let loop ([i (fx- n bytes)] [ls '()]) - (if (fx> i 0) - (loop - (fx- i (fx* bytes 2)) - (list* (ref v (fx- i bytes)) (ref v i) ls)) - (if (fx= i 0) (cons (ref v 0) ls) ls)))))])) - - (define $bytevector->s8-list (bv->list 1 bytevector-s8-ref)) - (define $bytevector->u8-list (bv->list 1 bytevector-u8-ref)) - (define $bytevector->s16-native-list (bv->list 2 bytevector-s16-native-ref)) - (define $bytevector->u16-native-list (bv->list 2 bytevector-u16-native-ref)) - (define $bytevector->s32-native-list (bv->list 4 bytevector-s32-native-ref)) - (define $bytevector->u32-native-list (bv->list 4 bytevector-u32-native-ref)) - (define $bytevector->s64-native-list (bv->list 8 bytevector-s64-native-ref)) - (define $bytevector->u64-native-list (bv->list 8 bytevector-u64-native-ref)) - - (set-who! bytevector->s8-list - (lambda (v) - ($bytevector->s8-list v who))) - - (set-who! bytevector->u8-list - (lambda (v) - ($bytevector->u8-list v who))) - - (set-who! bytevector->sint-list - (lambda (v eness size) - (define (big->list v size) - (unless (bytevector? v) (not-a-bytevector who v)) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (let ([n (bytevector-length v)]) - (unless (fx= (fxremainder n size) 0) (size-multiple-error who n size)) - (let f ([i 0]) - (if (fx= i n) - '() - (cons ($bytevector-sint-big-ref v i size) - (f (fx+ i size))))))) - (define (little->list v size) - (unless (bytevector? v) (not-a-bytevector who v)) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (let ([n (bytevector-length v)]) - (unless (fx= (fxremainder n size) 0) (size-multiple-error who n size)) - (let f ([i 0]) - (if (fx= i n) - '() - (cons ($bytevector-sint-little-ref v i size) - (f (fx+ i size))))))) - (if (eq? eness (native-endianness)) - (case size - [(1) ($bytevector->s8-list v who)] - [(2) ($bytevector->s16-native-list v who)] - [(4) ($bytevector->s32-native-list v who)] - [(8) ($bytevector->s64-native-list v who)] - [else - (constant-case native-endianness - [(little) (little->list v size)] - [(big) (big->list v size)])]) - (constant-case native-endianness - [(little) - (if (eq? eness 'big) - (big->list v size) - (unrecognized-endianness who eness))] - [(big) - (if (eq? eness 'little) - (little->list v size) - (unrecognized-endianness who eness))])))) - - (set-who! bytevector->uint-list - (lambda (v eness size) - (define (big->list v size) - (unless (bytevector? v) (not-a-bytevector who v)) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (let ([n (bytevector-length v)]) - (unless (fx= (fxremainder n size) 0) (size-multiple-error who n size)) - (let f ([i 0]) - (if (fx= i n) - '() - (cons ($bytevector-uint-big-ref v i size) - (f (fx+ i size))))))) - (define (little->list v size) - (unless (bytevector? v) (not-a-bytevector who v)) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (let ([n (bytevector-length v)]) - (unless (fx= (fxremainder n size) 0) (size-multiple-error who n size)) - (let f ([i 0]) - (if (fx= i n) - '() - (cons ($bytevector-uint-little-ref v i size) - (f (fx+ i size))))))) - (if (eq? eness (native-endianness)) - (case size - [(1) ($bytevector->u8-list v who)] - [(2) ($bytevector->u16-native-list v who)] - [(4) ($bytevector->u32-native-list v who)] - [(8) ($bytevector->u64-native-list v who)] - [else - (constant-case native-endianness - [(little) (little->list v size)] - [(big) (big->list v size)])]) - (constant-case native-endianness - [(little) - (if (eq? eness 'big) - (big->list v size) - (unrecognized-endianness who eness))] - [(big) - (if (eq? eness 'little) - (little->list v size) - (unrecognized-endianness who eness))])))) - ) - - (let () - (define-syntax list->bv - (syntax-rules () - [(_ bytes set! vokay?) - (let ([value-okay? vokay?]) - (lambda (ls who) - (let* ([n ($list-length ls who)] - [v (make-bytevector (fx* n bytes))]) - (let loop ([ls ls] [i 0]) - (unless (null? ls) - (let ([k (car ls)]) - (unless (value-okay? k) (invalid-value who k)) - (set! v i k)) - (let ([ls (cdr ls)]) - (unless (null? ls) - (let ([k (car ls)]) - (unless (value-okay? k) (invalid-value who k)) - (set! v (fx+ i bytes) k)) - (loop (cdr ls) (fx+ i (fx* bytes 2))))))) - v)))])) - - (define $s8-list->bytevector (list->bv 1 bytevector-s8-set! (signed-value-pred 8))) - (define $u8-list->bytevector (list->bv 1 bytevector-u8-set! (unsigned-value-pred 8))) - (define $s16-native-list->bytevector (list->bv 2 bytevector-s16-native-set! (signed-value-pred 16))) - (define $u16-native-list->bytevector (list->bv 2 bytevector-u16-native-set! (unsigned-value-pred 16))) - (define $s32-native-list->bytevector (list->bv 4 bytevector-s32-native-set! (signed-value-pred 32))) - (define $u32-native-list->bytevector (list->bv 4 bytevector-u32-native-set! (unsigned-value-pred 32))) - (define $s64-native-list->bytevector (list->bv 8 bytevector-s64-native-set! (signed-value-pred 64))) - (define $u64-native-list->bytevector (list->bv 8 bytevector-u64-native-set! (unsigned-value-pred 64))) - - (set-who! s8-list->bytevector - (lambda (ls) - ($s8-list->bytevector ls who))) - - (set-who! u8-list->bytevector - (lambda (ls) - ($u8-list->bytevector ls who))) - - (set-who! sint-list->bytevector - (lambda (ls eness size) - (define (list->big v size) - (let ([n ($list-length ls who)]) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (let ([v (make-bytevector (fx* n size))]) - (let f ([ls ls] [i 0]) - (unless (null? ls) - (let ([k (car ls)]) - (unless (and (or (fixnum? k) (bignum? k)) - (let ([k (ash k (fx- 1 (fx* size 8)))]) - (or (fx= k 0) (fx= k -1)))) - (invalid-value who k)) - ($bytevector-int-big-set! v i k size)) - (f (cdr ls) (fx+ i size)))) - v))) - (define (list->little v size) - (let ([n ($list-length ls who)]) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (let ([v (make-bytevector (fx* n size))]) - (let f ([ls ls] [i 0]) - (unless (null? ls) - (let ([k (car ls)]) - (unless (and (or (fixnum? k) (bignum? k)) - (let ([k (ash k (fx- 1 (fx* size 8)))]) - (or (fx= k 0) (fx= k -1)))) - (invalid-value who k)) - ($bytevector-int-little-set! v i k size)) - (f (cdr ls) (fx+ i size)))) - v))) - (if (eq? eness (native-endianness)) - (case size - [(1) ($s8-list->bytevector ls who)] - [(2) ($s16-native-list->bytevector ls who)] - [(4) ($s32-native-list->bytevector ls who)] - [(8) ($s64-native-list->bytevector ls who)] - [else - (constant-case native-endianness - [(little) (list->little ls size)] - [(big) (list->big ls size)])]) - (constant-case native-endianness - [(little) - (if (eq? eness 'big) - (list->big ls size) - (unrecognized-endianness who eness))] - [(big) - (if (eq? eness 'little) - (list->little ls size) - (unrecognized-endianness who eness))])))) - - (set-who! uint-list->bytevector - (lambda (ls eness size) - (define (list->big v size) - (let ([n ($list-length ls who)]) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (let ([v (make-bytevector (fx* n size))]) - (let f ([ls ls] [i 0]) - (unless (null? ls) - (let ([k (car ls)]) - (unless (and (or (fixnum? k) (bignum? k)) - (fx= (ash k (fx- (fx* size 8))) 0)) - (invalid-value who k)) - ($bytevector-int-big-set! v i k size)) - (f (cdr ls) (fx+ i size)))) - v))) - (define (list->little v size) - (let ([n ($list-length ls who)]) - (unless (and (fixnum? size) (fx> size 0)) (invalid-size who size)) - (let ([v (make-bytevector (fx* n size))]) - (let f ([ls ls] [i 0]) - (unless (null? ls) - (let ([k (car ls)]) - (unless (and (or (fixnum? k) (bignum? k)) - (fx= (ash k (fx- (fx* size 8))) 0)) - (invalid-value who k)) - ($bytevector-int-little-set! v i k size)) - (f (cdr ls) (fx+ i size)))) - v))) - (if (eq? eness (native-endianness)) - (case size - [(1) ($u8-list->bytevector ls who)] - [(2) ($u16-native-list->bytevector ls who)] - [(4) ($u32-native-list->bytevector ls who)] - [(8) ($u64-native-list->bytevector ls who)] - [else - (constant-case native-endianness - [(little) (list->little ls size)] - [(big) (list->big ls size)])]) - (constant-case native-endianness - [(little) - (if (eq? eness 'big) - (list->big ls size) - (unrecognized-endianness who eness))] - [(big) - (if (eq? eness 'little) - (list->little ls size) - (unrecognized-endianness who eness))])))) - ) - - (let () - ;; Store uncompressed size as u64, using low bits to indicate compression format: - (define uncompressed-length-length (ftype-sizeof integer-64)) - ;; Always big-endian, so that compressed data is portable. - (define uncompressed-length-endianness (endianness big)) - - (define fp-bytevector-compress-size - (foreign-procedure "(cs)bytevector_compress_size" (iptr int) uptr)) - (define fp-bytevector-compress - (foreign-procedure "(cs)bytevector_compress" (scheme-object iptr iptr scheme-object iptr iptr int) scheme-object)) - (define fp-bytevector-uncompress - (foreign-procedure "(cs)bytevector_uncompress" (scheme-object iptr iptr scheme-object iptr iptr int) scheme-object)) - - (let () - (define (compress who bv fmt offset) - (let* ([dest-max-len (fp-bytevector-compress-size (bytevector-length bv) fmt)] - [dest-alloc-len (min (+ dest-max-len offset) (constant maximum-bytevector-length))] - [dest-bv (make-bytevector dest-alloc-len)]) - (let ([r (fp-bytevector-compress dest-bv offset (fx- dest-alloc-len offset) bv 0 (bytevector-length bv) fmt)]) - (if (string? r) - ($oops who r bv) - (bytevector-truncate! dest-bv (fx+ r offset)))))) - - (set-who! $bytevector-compress - (lambda (bv fmt) - (compress who bv fmt 0))) - - (set-who! bytevector-compress - (lambda (bv) - (unless (bytevector? bv) (not-a-bytevector who bv)) - (let* ([fmt ($tc-field 'compress-format ($tc))] - [dest-bv (compress who bv fmt uncompressed-length-length)]) - (let ([tag (bitwise-ior - (bitwise-arithmetic-shift-left (bytevector-length bv) (constant COMPRESS-FORMAT-BITS)) - fmt)]) - ($bytevector-u64-set! dest-bv 0 tag uncompressed-length-endianness who) - dest-bv))))) - - (let () - (define (uncompress who bv dest-length fmt offset) - (unless (and (fixnum? dest-length) ($fxu< dest-length (constant maximum-bytevector-length))) - ($oops who "bytevector ~s claims invalid uncompressed size ~s" bv dest-length)) - (let ([dest-bv (make-bytevector dest-length)]) - (let ([r (fp-bytevector-uncompress dest-bv 0 dest-length bv offset (fx- (bytevector-length bv) offset) fmt)]) - (cond - [(string? r) ($oops who r bv)] - [(fx= r dest-length) dest-bv] - [else ($oops who "uncompressed size ~s for ~s is smaller than expected size ~s" r bv dest-length)])))) - - (set-who! $bytevector-uncompress - (lambda (bv dest-length fmt) - (uncompress who bv dest-length fmt 0))) - - (set-who! bytevector-uncompress - (lambda (bv) - (unless (bytevector? bv) (not-a-bytevector who bv)) - (unless (>= (bytevector-length bv) uncompressed-length-length) ($oops who "invalid data in source bytevector ~s" bv)) - (let* ([tag ($bytevector-u64-ref bv 0 uncompressed-length-endianness who)] - [fmt (logand tag (fx- (fxsll 1 (constant COMPRESS-FORMAT-BITS)) 1))] - [dest-length (bitwise-arithmetic-shift-right tag (constant COMPRESS-FORMAT-BITS))]) - (uncompress who bv dest-length fmt uncompressed-length-length)))))) -) diff --git a/ta6ob/s/bytevector.ta6ob b/ta6ob/s/bytevector.ta6ob deleted file mode 100644 index 4665d4e..0000000 Binary files a/ta6ob/s/bytevector.ta6ob and /dev/null differ diff --git a/ta6ob/s/cafe.ss b/ta6ob/s/cafe.ss deleted file mode 100644 index e5d2f24..0000000 --- a/ta6ob/s/cafe.ss +++ /dev/null @@ -1,217 +0,0 @@ -;;; cafe.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(begin -(define default-prompt-and-read - (lambda (n) - (unless (and (integer? n) (>= n 0)) - ($oops 'default-prompt-and-read - "~s is not a nonnegative integer" - n)) - (let ([prompt (waiter-prompt-string)]) - (unless (string=? prompt "") - (do ([n n (- n 1)]) - ((= n 0) - (write-char #\space (console-output-port)) - (flush-output-port (console-output-port))) - (display prompt (console-output-port)))) - (let ([x (read (console-input-port))]) - (when (and (eof-object? x) (not (string=? prompt ""))) - (newline (console-output-port)) - (flush-output-port (console-output-port))) - x)))) - -(define waiter-prompt-and-read - ($make-thread-parameter - default-prompt-and-read - (lambda (p) - (unless (procedure? p) - ($oops 'waiter-prompt-and-read "~s is not a procedure" p)) - p))) - -(define waiter-write - ($make-thread-parameter - (lambda (x) - (unless (eq? x (void)) - (pretty-print x (console-output-port))) - (flush-output-port (console-output-port))) - (lambda (p) - (unless (procedure? p) - ($oops 'waiter-write "~s is not a procedure" p)) - p))) - -(define waiter-prompt-string - ($make-thread-parameter - ">" - (lambda (s) - (unless (string? s) - ($oops 'waiter-prompt-string "~s is not a string" s)) - s))) - -(define new-cafe) - -(let () -(define-threaded waiter-expr) -(define-threaded waiter-stat1) -(define-threaded waiter-stat2) -(define-threaded waiter-total-stats) - -(define sstats-sum - (lambda (a b) - (define sstats-time-add - (lambda (f a b) - (add-duration (f a) (f b)))) - (make-sstats - (sstats-time-add sstats-cpu a b) - (sstats-time-add sstats-real a b) - (+ (sstats-bytes a) (sstats-bytes b)) - (+ (sstats-gc-count a) (sstats-gc-count b)) - (sstats-time-add sstats-gc-cpu a b) - (sstats-time-add sstats-gc-real a b) - (+ (sstats-gc-bytes a) (sstats-gc-bytes b))))) - -(define waiter - (lambda (cafe eval) - (let ([x ((waiter-prompt-and-read) cafe)]) - (when (eof-object? x) (exit)) - (fluid-let ([waiter-total-stats (make-sstats - (make-time 'time-duration 0 0) - (make-time 'time-duration 0 0) - 0 - 0 - (make-time 'time-duration 0 0) - (make-time 'time-duration 0 0) - 0)] - [waiter-expr x] - [waiter-stat1 (void)] - [waiter-stat2 (void)]) - (dynamic-wind #t - (lambda () - (set! waiter-stat1 (statistics)) - (set! waiter-stat2 (statistics))) - (lambda () - (parameterize ([$interrupt waiter-interrupt]) - (top-level eval x))) - (lambda () - (let ([s (statistics)]) - (set! waiter-total-stats - (sstats-sum (sstats-difference - (sstats-difference s waiter-stat2) - (sstats-difference waiter-stat2 - waiter-stat1)) - waiter-total-stats))))))) - (waiter cafe eval))) - -; This marks the "top-level" continuation for the debugger -(define top-level - (lambda (eval x) - (call/cc ; grab continuation & start a new stack segment - (rec new-cafe - (lambda (k) - ($current-stack-link $null-continuation) ; toss what's below - (call-with-values - (lambda () (eval x)) - (lambda args (for-each (waiter-write) args))) - (k)))))) - -(define waiter-interrupt - (lambda () - (call/cc - (lambda (k) - (parameterize ([$interrupt void]) - (let ([s (statistics)]) - (set! waiter-total-stats - (sstats-sum (sstats-difference - (sstats-difference s waiter-stat2) - (sstats-difference waiter-stat2 - waiter-stat1)) - waiter-total-stats))) - (clear-input-port (console-input-port)) - (let ([waiter (call/cc - (lambda (k) - (rec f (lambda () (k f)))))]) - (fprintf (console-output-port) "break> ") - (flush-output-port (console-output-port)) - (case (let ([x (parameterize ([$interrupt waiter] - [reset-handler waiter]) - (read (console-input-port)))]) - (if (eof-object? x) - (begin (newline (console-output-port)) - (flush-output-port (console-output-port)) - 'exit) - x)) - [(exit e) - (void)] - [(statistics s) - (parameterize ([print-level 2] [print-length 2]) - (fprintf (console-output-port) - "(time ~s)~%" - waiter-expr)) - (sstats-print waiter-total-stats (console-output-port)) - (flush-output-port (console-output-port)) - (waiter)] - [(reset r quit q) - (reset)] - [(abort a) - (abort)] - [(new-cafe n) - (new-cafe) - (waiter)] - [(inspect i) - (inspect k) - (waiter)] - [(?) - (fprintf (console-output-port) " -Type e to exit interrupt handler and continue - r or q to reset scheme - a to abort scheme - n to enter new cafe - i to inspect current continuation - s to display statistics - -") - (flush-output-port (console-output-port)) - (waiter)] - [else - (fprintf (console-output-port) - "Invalid command. Type ? for options.~%") - (flush-output-port (console-output-port)) - (waiter)])) - (set! waiter-stat1 (statistics)) - (set! waiter-stat2 (statistics))))))) - -(set! $cafe ($make-thread-parameter 0)) - -(set! new-cafe - (let () - (rec new-cafe - (case-lambda - [() (new-cafe eval)] - [(eval) - (unless (procedure? eval) - ($oops 'new-cafe "~s is not a procedure" eval)) - (call/cc - (lambda (k1) - (parameterize ([exit-handler k1] [reset-handler (reset-handler)]) - (let ((k2 k1)) - (reset-handler (lambda () (k2))) - (call/cc (lambda (k) (set! k2 k))) - (parameterize ([$cafe (+ ($cafe) 1)] [$interrupt reset]) - (with-exception-handler - (lambda (c) ((base-exception-handler) c)) - (lambda () - (waiter ($cafe) eval))))))))])))) -) -) diff --git a/ta6ob/s/cafe.ta6ob b/ta6ob/s/cafe.ta6ob deleted file mode 100644 index 1a1b216..0000000 Binary files a/ta6ob/s/cafe.ta6ob and /dev/null differ diff --git a/ta6ob/s/cback.ss b/ta6ob/s/cback.ss deleted file mode 100644 index cedc90a..0000000 --- a/ta6ob/s/cback.ss +++ /dev/null @@ -1,19 +0,0 @@ -;;; cback.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(begin -(current-eval compile) -(define $compiler-is-loaded? #t) -) diff --git a/ta6ob/s/cback.ta6ob b/ta6ob/s/cback.ta6ob deleted file mode 100644 index c5d09ed..0000000 Binary files a/ta6ob/s/cback.ta6ob and /dev/null differ diff --git a/ta6ob/s/cmacros.so b/ta6ob/s/cmacros.so deleted file mode 100644 index a1af3c7..0000000 Binary files a/ta6ob/s/cmacros.so and /dev/null differ diff --git a/ta6ob/s/cmacros.ss b/ta6ob/s/cmacros.ss deleted file mode 100644 index e2f4a9b..0000000 --- a/ta6ob/s/cmacros.ss +++ /dev/null @@ -1,2677 +0,0 @@ -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(define-syntax disable-unbound-warning - (syntax-rules () - ((_ name ...) - (eval-when (compile load eval) - ($sputprop 'name 'no-unbound-warning #t) ...)))) - -(disable-unbound-warning - lookup-constant - flag->mask - construct-name - tc-field-list -) - -(define-syntax define-constant - (lambda (x) - (syntax-case x () - ((_ ctype x y) - (and (identifier? #'ctype) (identifier? #'x)) - #'(eval-when (compile load eval) - (putprop 'x '*constant-ctype* 'ctype) - (putprop 'x '*constant* y))) - ((_ x y) - (identifier? #'x) - #'(eval-when (compile load eval) - (putprop 'x '*constant* y)))))) - -(eval-when (compile load eval) -(define lookup-constant - (let ([flag (box #f)]) - (lambda (x) - (unless (symbol? x) - ($oops 'lookup-constant "~s is not a symbol" x)) - (let ([v (getprop x '*constant* flag)]) - (when (eq? v flag) - ($oops 'lookup-constant "undefined constant ~s" x)) - v)))) -) - -(define-syntax constant - (lambda (x) - (syntax-case x () - ((_ x) - (identifier? #'x) - #`'#,(datum->syntax #'x - (lookup-constant (datum x))))))) - -(define-syntax constant-case - (syntax-rules (else) - [(_ const [(k ...) e1 e2 ...] ... [else ee1 ee2 ...]) - (meta-cond - [(member (constant const) '(k ...)) e1 e2 ...] - ... - [else ee1 ee2 ...])] - [(_ const [(k ...) e1 e2 ...] ...) - (meta-cond - [(member (constant const) '(k ...)) e1 e2 ...] - ... - [else (syntax-error #'const - (format "unhandled value ~s" (constant const)))])])) - -(eval-when (compile load eval) -(define construct-name - (lambda (template-identifier . args) - (datum->syntax - template-identifier - (string->symbol - (apply string-append - (map (lambda (x) (format "~a" (syntax->datum x))) - args)))))) -) - -(define-syntax macro-define-structure - (lambda (x) - (define constant? - (lambda (x) - (or (let ((x (syntax->datum x))) - (or (boolean? x) (string? x) (char? x) (number? x))) - (syntax-case x (quote) - ((quote obj) #t) - (else #f))))) - (syntax-case x () - ((_ (name id1 ...)) - (andmap identifier? #'(name id1 ...)) - #'(macro-define-structure (name id1 ...) ())) - ((_ (name id1 ...) ((id2 init) ...)) - (and (andmap identifier? #'(name id1 ... id2 ...)) - (andmap constant? #'(init ...))) - (with-syntax - ((constructor (construct-name #'name "make-" #'name)) - (predicate (construct-name #'name #'name "?")) - ((index-name ...) - (map (lambda (x) (construct-name x #'name "-" x "-index")) - #'(id1 ... id2 ...))) - ((access ...) - (map (lambda (x) (construct-name x #'name "-" x)) - #'(id1 ... id2 ...))) - ((assign ...) - (map (lambda (x) (construct-name x "set-" #'name "-" x "!")) - #'(id1 ... id2 ...))) - (structure-length (fx+ (length #'(id1 ... id2 ...)) 1)) - ((index ...) - (let f ((i 1) (ids #'(id1 ... id2 ...))) - (if (null? ids) - '() - (cons i (f (fx+ i 1) (cdr ids))))))) - #'(begin - (define-syntax constructor - (syntax-rules () - ((_ id1 ...) - (#%vector 'name id1 ... init ...)))) - (define-syntax predicate - (syntax-rules () - ((_ x) - (let ((t x)) - (and (#%vector? x) - (#3%fx= (#3%vector-length x) structure-length) - (#%eq? (#3%vector-ref x 0) 'name)))))) - (define-constant index-name index) - ... - (define-syntax access - (syntax-rules () - ((_ x) (#%vector-ref x index)))) - ... - (define-syntax assign - (syntax-rules () - ((_ x update) (#%vector-set! x index update)))) - ...)))))) - -(define-syntax type-case - (syntax-rules (else) - [(_ expr - [(pred1 pred2 ...) e1 e2 ...] ... - [else ee1 ee2 ...]) - (let ([t expr]) - (cond - [(or (pred1 t) (pred2 t) ...) e1 e2 ...] - ... - [else ee1 ee2 ...]))])) - -;;; machine-case and float-type-case call eval to pick up the -;;; system value of $target-machine under the assumption that -;;; we'll be in system mode when we expand the macro - -(define-syntax machine-case - (lambda (x) - (let ((target-machine (eval '($target-machine)))) - (let loop ((x (syntax-case x () ((_ m ...) #'(m ...))))) - (syntax-case x (else) - ((((a1 a2 ...) e ...) m1 m2 ...) - (let ((machines (datum (a1 a2 ...)))) - (if (memq target-machine machines) - (if (null? #'(e ...)) - (begin - (printf "Warning: empty machine-case clause for ~s~%" - machines) - #'($oops 'assembler - "empty machine-case clause for ~s" - '(a1 a2 ...))) - #'(begin e ...)) - (loop (cdr x))))) - (((else e1 e2 ...)) #'(begin e1 e2 ...))))))) - -(define-syntax float-type-case - (lambda (x) - (syntax-case x (ieee else) - ((_ ((ieee tag ...) e1 e2 ...) m ...) - #t ; all currently supported machines are ieee - #'(begin e1 e2 ...)) - ((_ ((tag1 tag2 ...) e1 e2 ...) m ...) - #'(float-type-case ((tag2 ...) e1 e2 ...) m ...)) - ((_ (() e1 e2 ...) m ...) - #'(float-type-case m ...)) - ((_ (else e1 e2 ...)) - #'(begin e1 e2 ...))))) -(define-syntax ieee - (lambda (x) - (syntax-error x "misplaced aux keyword"))) - -;; layout of our flags field: -;; bit 0: needs head space? -;; bit 1 - 9: upper 9 bits of index (lower bit is the needs head space index -;; bit 10 - 12: interface -;; bit 13: closure? -;; bit 14: error? -;; bit 15: has-headroom-version? -(macro-define-structure (libspec name flags)) - -(define-constant libspec-does-not-expect-headroom-index 0) -(define-constant libspec-index-offset 0) -(define-constant libspec-index-size 10) -(define-constant libspec-index-base-offset 1) -(define-constant libspec-index-base-size 9) -(define-constant libspec-interface-offset 10) -(define-constant libspec-interface-size 3) -(define-constant libspec-closure-index 13) -(define-constant libspec-error-index 14) -(define-constant libspec-has-does-not-expect-headroom-version-index 15) -(define-constant libspec-fake-index 16) - -(define-syntax make-libspec-flags - (lambda (x) - (syntax-case x () - [(_ index-base does-not-expect-headroom? closure? interface error? has-does-not-expect-headroom-version?) - #'(begin - (unless (fx>= (- (expt 2 (constant libspec-index-base-size)) 1) index-base 0) - ($oops 'make-libspec-flags "libspec base index exceeds ~s-bit bound: ~s" - (constant libspec-index-base-size) index-base)) - (unless (fx>= (- (expt 2 (constant libspec-interface-size)) 1) interface 0) - ($oops 'make-libspec-flags "libspec interface exceeds ~s-bit bound: ~s" - (constant libspec-interface-size) interface)) - (when (and does-not-expect-headroom? (not has-does-not-expect-headroom-version?)) - ($oops 'make-libspec-flags - "creating invalid version of libspec that does not expect headroom")) - (fxlogor - (if does-not-expect-headroom? - (fxsll 1 (constant libspec-does-not-expect-headroom-index)) - 0) - (fxsll index-base (constant libspec-index-base-offset)) - (fxsll interface (constant libspec-interface-offset)) - (if closure? (fxsll 1 (constant libspec-closure-index)) 0) - (if error? (fxsll 1 (constant libspec-error-index)) 0) - (if has-does-not-expect-headroom-version? - (fxsll 1 (constant libspec-has-does-not-expect-headroom-version-index)) - 0)))]))) - -(define-syntax libspec-does-not-expect-headroom? - (syntax-rules () - [(_ ?libspec) - (fxbit-set? (libspec-flags ?libspec) (constant libspec-does-not-expect-headroom-index))])) - -(define-syntax libspec-index - (syntax-rules () - [(_ ?libspec) - (fxbit-field (libspec-flags ?libspec) - (constant libspec-index-offset) - (fx+ (constant libspec-index-size) (constant libspec-index-offset)))])) - -(define-syntax libspec-interface - (syntax-rules () - [(_ ?libspec) - (fxbit-field (libspec-flags ?libspec) - (constant libspec-interface-offset) - (fx+ (constant libspec-interface-size) (constant libspec-interface-offset)))])) - -(define-syntax libspec-closure? - (syntax-rules () - [(_ ?libspec) - (fxbit-set? (libspec-flags ?libspec) (constant libspec-closure-index))])) - -(define-syntax libspec-error? - (syntax-rules () - [(_ ?libspec) - (fxbit-set? (libspec-flags ?libspec) (constant libspec-error-index))])) - -(define-syntax libspec-has-does-not-expect-headroom-version? - (syntax-rules () - [(_ ?libspec) - (fxbit-set? (libspec-flags ?libspec) (constant libspec-has-does-not-expect-headroom-version-index))])) - -(define-syntax libspec->does-not-expect-headroom-libspec - (syntax-rules () - [(_ ?libspec) - (let ([libspec ?libspec]) - (unless (libspec-has-does-not-expect-headroom-version? libspec) - ($oops #f "generating invalid libspec for ~s that does not expect headroom" - (libspec-name libspec))) - (make-libspec (libspec-name libspec) - (fxlogor (libspec-flags libspec) - (fxsll 1 (constant libspec-does-not-expect-headroom-index)))))])) - -(define-syntax libspec->headroom-libspec - (syntax-rules () - [(_ ?libspec) - (let ([libspec ?libspec]) - (make-libspec (libspec-name libspec) - (fxlogand (libspec-flags libspec) - (fxlognot (fxsll 1 (constant libspec-does-not-expect-headroom-index))))))])) - -(define-syntax return-values - (syntax-rules () - ((_ args ...) (values args ...)))) - -(define-syntax with-values - (syntax-rules () - ((_ producer proc) - (call-with-values (lambda () producer) proc)))) - -(define-syntax meta-assert - (lambda (x) - (syntax-case x () - [(_ e) - #`(let-syntax ([t (if e (lambda () #'(void)) #,(#%$make-source-oops #f "failed meta-assertion" #'e))]) - (void))]))) - -(define-syntax features - (lambda (x) - (syntax-case x () - [(k foo ...) - (with-implicit (k feature-list when-feature unless-feature if-feature) - #'(begin - (define-syntax feature-list - (syntax-rules () - [(_) '(foo ...)])) - (define-syntax when-feature - (syntax-rules (foo ...) - [(_ foo e1 e2 (... ...)) (begin e1 e2 (... ...))] ... - [(_ bar e1 e2 (... ...)) (void)])) - (define-syntax unless-feature - (syntax-rules (foo ...) - [(_ foo e1 e2 (... ...)) (void)] ... - [(_ bar e1 e2 (... ...)) (begin e1 e2 (... ...))])) - (define-syntax if-feature - (syntax-rules (foo ...) - [(_ foo e1 e2) e1] ... - [(_ bar e1 e2) e2]))))]))) - -(define-constant scheme-version #x00090509) - -(define-syntax define-machine-types - (lambda (x) - (syntax-case x () - [(_ name ...) - (with-syntax ([(value ...) (enumerate (datum (name ...)))] - [(cname ...) - (map (lambda (name) - (construct-name name "machine-type-" name)) - #'(name ...))]) - #'(begin - (define-constant cname value) ... - (define-constant machine-type-alist '((value . name) ...)) - (define-constant machine-type-limit (+ (max value ...) 1))))]))) - -(define-machine-types - any - i3le ti3le - i3nt ti3nt - i3fb ti3fb - i3ob ti3ob - i3osx ti3osx - a6le ta6le - a6osx ta6osx - a6ob ta6ob - a6s2 ta6s2 - i3s2 ti3s2 - a6fb ta6fb - i3nb ti3nb - a6nb ta6nb - a6nt ta6nt - i3qnx ti3qnx - arm32le tarm32le - ppc32le tppc32le -) - -(include "machine.def") - -(define-constant machine-type-name (cdr (assv (constant machine-type) (constant machine-type-alist)))) - -(define-syntax log2 - (syntax-rules () - [(_ n) (integer-length (- n 1))])) - -; a string-char is a 32-bit equivalent of a ptr char: identical to a -; ptr char on 32-bit machines and the low-order half of a ptr char on -; 64-bit machines. -(define-constant string-char-bits 32) -(define-constant string-char-bytes 4) -(define-constant string-char-offset (log2 (constant string-char-bytes))) - -(define-constant ptr-bytes (/ (constant ptr-bits) 8)) ; size in bytes -(define-constant log2-ptr-bytes (log2 (constant ptr-bytes))) - -;;; ordinary types must be no more than 8 bits long -(define-constant ordinary-type-bits 8) ; smallest addressable unit - -; (typemod = type modulus) -; The typemod defines the range of primary types and is also the -; offset that we subtract off of the actual addresses before adding -; in the primary type tag to obtain a ptr. -; -; The typemod imposes a lower bound on our choice of alignment -; since the low n bits of aligned addresses must be zero so that -; we can steal those bits for type tags. -; -; Leaving the typemod at 8 for 64-bit ports, means that we "waste" -; a bit of primary type space. If we ever attempt to reclaim this -; bit, we must remember that flonums are actually represented by two -; primary type codes, ie. 1xxx and 0xxx, see also the comment under -; byte-alignment. -(define-constant typemod 8) -(define-constant primary-type-bits (log2 (constant typemod))) - -; We must have room for forward marker and forward pointer, hence two ptrs. -; We sometimes violate this for flonums since we "extract" the real -; and imag part by returning pointers into the inexactnum structure. -; This is safe since we never forward flonums. -(define-constant byte-alignment - (max (constant typemod) (* 2 (constant ptr-bytes)))) - -;;; fasl codes---see fasl.c for documentation of representation - -(define-constant fasl-type-header 0) -(define-constant fasl-type-box 1) -(define-constant fasl-type-symbol 2) -(define-constant fasl-type-ratnum 3) -(define-constant fasl-type-vector 4) -(define-constant fasl-type-inexactnum 5) -(define-constant fasl-type-closure 6) -(define-constant fasl-type-pair 7) -(define-constant fasl-type-flonum 8) -(define-constant fasl-type-string 9) -(define-constant fasl-type-large-integer 10) -(define-constant fasl-type-code 11) -(define-constant fasl-type-immediate 12) -(define-constant fasl-type-entry 13) -(define-constant fasl-type-library 14) -(define-constant fasl-type-library-code 15) -(define-constant fasl-type-graph 16) -(define-constant fasl-type-graph-def 17) -(define-constant fasl-type-graph-ref 18) -(define-constant fasl-type-gensym 19) -(define-constant fasl-type-exactnum 20) -; 21 -; 22 -(define-constant fasl-type-record 23) -(define-constant fasl-type-rtd 24) -(define-constant fasl-type-small-integer 25) -(define-constant fasl-type-base-rtd 26) -(define-constant fasl-type-fxvector 27) -(define-constant fasl-type-ephemeron 28) -(define-constant fasl-type-bytevector 29) -(define-constant fasl-type-weak-pair 30) -(define-constant fasl-type-eq-hashtable 31) -(define-constant fasl-type-symbol-hashtable 32) -; 33 -(define-constant fasl-type-visit 34) -(define-constant fasl-type-revisit 35) -(define-constant fasl-type-visit-revisit 36) - -(define-constant fasl-type-immutable-vector 37) -(define-constant fasl-type-immutable-string 38) -(define-constant fasl-type-immutable-fxvector 39) -(define-constant fasl-type-immutable-bytevector 40) -(define-constant fasl-type-immutable-box 41) - -(define-constant fasl-type-uncompressed 42) -(define-constant fasl-type-gzip 43) -(define-constant fasl-type-lz4 44) - -(define-constant fasl-fld-ptr 0) -(define-constant fasl-fld-u8 1) -(define-constant fasl-fld-i16 2) -(define-constant fasl-fld-i24 3) -(define-constant fasl-fld-i32 4) -(define-constant fasl-fld-i40 5) -(define-constant fasl-fld-i48 6) -(define-constant fasl-fld-i56 7) -(define-constant fasl-fld-i64 8) -(define-constant fasl-fld-single 9) -(define-constant fasl-fld-double 10) - -(define-constant fasl-header - (bytevector (constant fasl-type-header) 0 0 0 - (char->integer #\c) (char->integer #\h) (char->integer #\e) (char->integer #\z))) - -(define-syntax define-enumerated-constants - (lambda (x) - (syntax-case x () - [(_ reloc-name ...) - (with-syntax ([(i ...) (enumerate #'(reloc-name ...))]) - #'(begin - (define-constant reloc-name i) - ...))]))) - -(define-syntax define-reloc-constants - (lambda (x) - (syntax-case x () - [(_ (all x ...) (arch y ...) ...) - #`(constant-case architecture - [(arch) (define-enumerated-constants x ... y ...)] - ...)]))) - -(define-reloc-constants - (all reloc-abs) - (x86 reloc-rel) - (sparc reloc-sparcabs reloc-sparcrel) - (sparc64 reloc-sparc64abs reloc-sparc64rel) - (ppc reloc-ppccall reloc-ppcload) - (x86_64 reloc-x86_64-call reloc-x86_64-jump) - (arm32 reloc-arm32-abs reloc-arm32-call reloc-arm32-jump) - (ppc32 reloc-ppc32-abs reloc-ppc32-call reloc-ppc32-jump)) - -(constant-case ptr-bits - [(64) - (define-constant reloc-extended-format #x1) - (define-constant reloc-type-offset 1) - (define-constant reloc-type-mask #x7) - (define-constant reloc-code-offset-offset 4) - (define-constant reloc-code-offset-mask #x3ffffff) - (define-constant reloc-item-offset-offset 30) - (define-constant reloc-item-offset-mask #x3ffffff)] - [(32) - (define-constant reloc-extended-format #x1) - (define-constant reloc-type-offset 1) - (define-constant reloc-type-mask #x7) - (define-constant reloc-code-offset-offset 4) - (define-constant reloc-code-offset-mask #x3ff) - (define-constant reloc-item-offset-offset 14) - (define-constant reloc-item-offset-mask #x3ffff)]) - -(macro-define-structure (reloc type item-offset code-offset long?)) - -(define-constant SERROR #x0000) -(define-constant STRVNCATE #x0001) ; V for U to avoid msvc errno.h conflict -(define-constant SREPLACE #x0002) -(define-constant SAPPEND #x0003) -(define-constant SDEFAULT #x0004) - -(define-constant OPEN-ERROR-OTHER 0) -(define-constant OPEN-ERROR-PROTECTION 1) -(define-constant OPEN-ERROR-EXISTS 2) -(define-constant OPEN-ERROR-EXISTSNOT 3) - -(define-constant SEOF -1) - -(define-constant COMPRESS-GZIP 0) -(define-constant COMPRESS-LZ4 1) -(define-constant COMPRESS-FORMAT-BITS 3) - -(define-constant COMPRESS-MIN 0) -(define-constant COMPRESS-LOW 1) -(define-constant COMPRESS-MEDIUM 2) -(define-constant COMPRESS-HIGH 3) -(define-constant COMPRESS-MAX 4) - -(define-constant SICONV-DUNNO 0) -(define-constant SICONV-INVALID 1) -(define-constant SICONV-INCOMPLETE 2) -(define-constant SICONV-NOROOM 3) - -;;; port flag masks are always single bits - -(define-constant port-flag-input #x01) -(define-constant port-flag-output #x02) -(define-constant port-flag-binary #x04) -(define-constant port-flag-closed #x08) -(define-constant port-flag-file #x10) -(define-constant port-flag-compressed #x20) -(define-constant port-flag-exclusive #x40) -(define-constant port-flag-bol #x80) -(define-constant port-flag-eof #x100) -(define-constant port-flag-block-buffered #x200) -(define-constant port-flag-line-buffered #x400) -(define-constant port-flag-input-mode #x800) -(define-constant port-flag-char-positions #x1000) -(define-constant port-flag-r6rs #x2000) -(define-constant port-flag-fold-case #x4000) -(define-constant port-flag-no-fold-case #x8000) - -(define-constant port-flags-offset (constant ordinary-type-bits)) - -;;; allcaps versions are pre-shifted by port-flags-offset -(define-constant PORT-FLAG-INPUT (ash (constant port-flag-input) (constant port-flags-offset))) -(define-constant PORT-FLAG-OUTPUT (ash (constant port-flag-output) (constant port-flags-offset))) -(define-constant PORT-FLAG-BINARY (ash (constant port-flag-binary) (constant port-flags-offset))) -(define-constant PORT-FLAG-CLOSED (ash (constant port-flag-closed) (constant port-flags-offset))) -(define-constant PORT-FLAG-FILE (ash (constant port-flag-file) (constant port-flags-offset))) -(define-constant PORT-FLAG-COMPRESSED (ash (constant port-flag-compressed) (constant port-flags-offset))) -(define-constant PORT-FLAG-EXCLUSIVE (ash (constant port-flag-exclusive) (constant port-flags-offset))) -(define-constant PORT-FLAG-BOL (ash (constant port-flag-bol) (constant port-flags-offset))) -(define-constant PORT-FLAG-EOF (ash (constant port-flag-eof) (constant port-flags-offset))) -(define-constant PORT-FLAG-BLOCK-BUFFERED (ash (constant port-flag-block-buffered) (constant port-flags-offset))) -(define-constant PORT-FLAG-LINE-BUFFERED (ash (constant port-flag-line-buffered) (constant port-flags-offset))) -(define-constant PORT-FLAG-INPUT-MODE (ash (constant port-flag-input-mode) (constant port-flags-offset))) -(define-constant PORT-FLAG-CHAR-POSITIONS (ash (constant port-flag-char-positions) (constant port-flags-offset))) -(define-constant PORT-FLAG-R6RS (ash (constant port-flag-r6rs) (constant port-flags-offset))) -(define-constant PORT-FLAG-FOLD-CASE (ash (constant port-flag-fold-case) (constant port-flags-offset))) -(define-constant PORT-FLAG-NO-FOLD-CASE (ash (constant port-flag-no-fold-case) (constant port-flags-offset))) - -;;; c-error codes -(define-constant ERROR_OTHER 0) -(define-constant ERROR_CALL_UNBOUND 1) -(define-constant ERROR_CALL_NONPROCEDURE_SYMBOL 2) -(define-constant ERROR_CALL_NONPROCEDURE 3) -(define-constant ERROR_CALL_ARGUMENT_COUNT 4) -(define-constant ERROR_RESET 5) -(define-constant ERROR_NONCONTINUABLE_INTERRUPT 6) -(define-constant ERROR_VALUES 7) -(define-constant ERROR_MVLET 8) - -;;; allocation spaces -(define-constant space-locked #x20) ; lock flag -(define-constant space-old #x40) ; oldspace flag - -(define-syntax define-alloc-spaces - (lambda (x) - (syntax-case x (real swept unswept unreal) - [(_ (real - (swept - (swept-name swept-cname swept-cchar swept-value) - ... - (last-swept-name last-swept-cname last-swept-cchar last-swept-value)) - (unswept - (unswept-name unswept-cname unswept-cchar unswept-value) - ... - (last-unswept-name last-unswept-cname last-unswept-cchar last-unswept-value))) - (unreal - (unreal-name unreal-cname unreal-cchar unreal-value) - ... - (last-unreal-name last-unreal-cname last-unreal-cchar last-unreal-value))) - (with-syntax ([(real-name ...) #'(swept-name ... last-swept-name unswept-name ... last-unswept-name)] - [(real-cname ...) #'(swept-cname ... last-swept-cname unswept-cname ... last-unswept-cname)] - [(real-cchar ...) #'(swept-cchar ... last-swept-cchar unswept-cchar ... last-unswept-cchar)] - [(real-value ...) #'(swept-value ... last-swept-value unswept-value ... last-unswept-value)]) - (with-syntax ([(name ...) #'(real-name ... unreal-name ... last-unreal-name)] - [(cname ...) #'(real-cname ... unreal-cname ... last-unreal-cname)] - [(cchar ...) #'(real-cchar ... unreal-cchar ... last-unreal-cchar)] - [(value ...) #'(real-value ... unreal-value ... last-unreal-value)]) - (with-syntax ([(space-name ...) (map (lambda (n) (construct-name n "space-" n)) #'(name ...))]) - (unless (< (syntax->datum #'last-unreal-value) (constant space-locked)) - ($oops 'define-alloc-spaces "conflict with space-locked")) - (unless (< (syntax->datum #'last-unreal-value) (constant space-old)) - ($oops 'define-alloc-spaces "conflict with space-old")) - #'(begin - (define-constant space-name value) ... - (define-constant real-space-alist '((real-name . real-value) ...)) - (define-constant space-cname-list '(cname ...)) - (define-constant space-char-list '(cchar ...)) - (define-constant max-sweep-space last-swept-value) - (define-constant max-real-space last-unswept-value) - (define-constant max-space last-unreal-value)))))]))) - -(define-alloc-spaces - (real - (swept - (new "new" #\n 0) ; all generation 0 objects allocated here - (impure "impure" #\i 1) ; most mutable objects allocated here (all ptrs) - (symbol "symbol" #\x 2) ; - (port "port" #\q 3) ; - (weakpair "weakpr" #\w 4) ; - (ephemeron "emph" #\e 5) ; - (pure "pure" #\p 6) ; swept immutable objects allocated here (all ptrs) - (continuation "cont" #\k 7) ; - (code "code" #\c 8) ; - (pure-typed-object "p-tobj" #\r 9) ; - (impure-record "ip-rec" #\s 10)) ; - (unswept - (data "data" #\d 11))) ; unswept objects allocated here - (unreal - (empty "empty" #\e 12))) ; available segments - -;;; enumeration of types for which gc tracks object counts -;;; also update gc.c - -(define-constant countof-pair 0) -(define-constant countof-symbol 1) -(define-constant countof-flonum 2) -(define-constant countof-closure 3) -(define-constant countof-continuation 4) -(define-constant countof-bignum 5) -(define-constant countof-ratnum 6) -(define-constant countof-inexactnum 7) -(define-constant countof-exactnum 8) -(define-constant countof-box 9) -(define-constant countof-port 10) -(define-constant countof-code 11) -(define-constant countof-thread 12) -(define-constant countof-tlc 13) -(define-constant countof-rtd-counts 14) -(define-constant countof-stack 15) -(define-constant countof-relocation-table 16) -(define-constant countof-weakpair 17) -(define-constant countof-vector 18) -(define-constant countof-string 19) -(define-constant countof-fxvector 20) -(define-constant countof-bytevector 21) -(define-constant countof-locked 22) -(define-constant countof-guardian 23) -(define-constant countof-oblist 24) -(define-constant countof-ephemeron 25) -(define-constant countof-types 26) - -;;; type-fixnum is assumed to be all zeros by at least by vector, fxvector, -;;; and bytevector index checks -(define-constant type-fixnum 0) ; #b100/#b000 32-bit, #b000 64-bit -(define-constant type-pair #b001) -(define-constant type-flonum #b010) -(define-constant type-symbol #b011) -; #b100 occupied by fixnums on 32-bit machines, unused on 64-bit machines -(define-constant type-closure #b101) -(define-constant type-immediate #b110) -(define-constant type-typed-object #b111) - -;;; note: for type-char, leave at least fixnum-offset zeros at top of -;;; type byte to simplify char->integer conversion -(define-constant type-boolean #b00000110) -(define-constant ptr sfalse #b00000110) -(define-constant ptr strue #b00001110) -(define-constant type-char #b00010110) -(define-constant ptr sunbound #b00011110) -(define-constant ptr snil #b00100110) -(define-constant ptr forward-marker #b00101110) -(define-constant ptr seof #b00110110) -(define-constant ptr svoid #b00111110) -(define-constant ptr black-hole #b01000110) -(define-constant ptr sbwp #b01001110) -(define-constant ptr ftype-guardian-rep #b01010110) - -;;; on 32-bit machines, vectors get two primary tag bits, including -;;; one for the immutable flag, and so do bytevectors, so their maximum -;;; lengths are equal to the most-positive fixnum on 32-bit machines. -;;; strings and fxvectors get only one primary tag bit each and have -;;; to use a different bit for the immutable flag, so their maximum -;;; lengths are equal to 1/2 of the most-positive fixnum on 32-bit -;;; machines. taking sizes of vector, bytevector, string, and fxvector -;;; elements into account, a vector can occupy up to 1/2 of virtual -;;; memory, a string or fxvector up to 1/4, and a bytevector up to 1/8. - -;;; on 64-bit machines, vectors get only one of the primary tag bits, -;;; bytevectors still get two (but don't need two), and strings and -;;; fxvectors still get one. all have maximum lengths equal to the -;;; most-positive fixnum. - -;;; vector type/length field must look like a fixnum. an immutable bit sits just above the fixnum tag, with the length above that. -(define-constant type-vector (constant type-fixnum)) -; #b000 occupied by vectors on 32- and 64-bit machines -(define-constant type-bytevector #b01) -(define-constant type-string #b010) -(define-constant type-fxvector #b011) -; #b100 occupied by vectors on 32-bit machines, unused on 64-bit machines -; #b101 occupied by type-immutable-bytevector -(define-constant type-other-number #b0110) ; bit 3 reset for numbers -(define-constant type-bignum #b00110) ; bit 4 reset for bignums -(define-constant type-positive-bignum #b000110) -(define-constant type-negative-bignum #b100110) -(define-constant type-ratnum #b00010110) ; bit 4 set for non-bignum numbers -(define-constant type-inexactnum #b00110110) -(define-constant type-exactnum #b01010110) -(define-constant type-box #b0001110) ; bit 3 set for non-numbers -(define-constant type-immutable-box #b10001110) ; low 7 bits match `type-box` -(define-constant type-port #b00011110) -; #b00101110 (forward_marker) must not be used -(define-constant type-code #b00111110) -(define-constant type-thread #b01001110) -(define-constant type-tlc #b01011110) -(define-constant type-rtd-counts #b01101110) -(define-constant type-record #b111) - -(define-constant code-flag-system #b0001) -(define-constant code-flag-continuation #b0010) -(define-constant code-flag-template #b0100) -(define-constant code-flag-guardian #b1000) - -(define-constant fixnum-bits - (case (constant ptr-bits) - [(64) 61] - [(32) 30] - [else ($oops 'fixnum-bits "expected reasonable native bit width (eg. 32 or 64)")])) -(define-constant iptr most-positive-fixnum - (- (expt 2 (- (constant fixnum-bits) 1)) 1)) -(define-constant iptr most-negative-fixnum - (- (expt 2 (- (constant fixnum-bits) 1)))) - -(define-constant fixnum-offset (- (constant ptr-bits) (constant fixnum-bits))) - -; string length field (high bits) + immutability is stored with type -(define-constant string-length-offset 4) -(define-constant string-immutable-flag - (expt 2 (- (constant string-length-offset) 1))) -(define-constant iptr maximum-string-length - (min (- (expt 2 (fx- (constant ptr-bits) (constant string-length-offset))) 1) - (constant most-positive-fixnum))) - -(define-constant bignum-sign-offset 5) -(define-constant bignum-length-offset 6) -(define-constant iptr maximum-bignum-length - (min (- (expt 2 (fx- (constant ptr-bits) (constant bignum-length-offset))) 1) - (constant most-positive-fixnum))) -(define-constant bigit-bits 32) -(define-constant bigit-bytes (/ (constant bigit-bits) 8)) - -; vector length field (high bits) + immutability is stored with type -(define-constant vector-length-offset (fx+ 1 (constant fixnum-offset))) -(define-constant vector-immutable-flag - (expt 2 (- (constant vector-length-offset) 1))) -(define-constant iptr maximum-vector-length - (min (- (expt 2 (fx- (constant ptr-bits) (constant vector-length-offset))) 1) - (constant most-positive-fixnum))) - -; fxvector length field (high bits) + immutability is stored with type -(define-constant fxvector-length-offset 4) -(define-constant fxvector-immutable-flag - (expt 2 (- (constant fxvector-length-offset) 1))) -(define-constant iptr maximum-fxvector-length - (min (- (expt 2 (fx- (constant ptr-bits) (constant fxvector-length-offset))) 1) - (constant most-positive-fixnum))) - -; bytevector length field (high bits) + immutability is stored with type -(define-constant bytevector-length-offset 3) -(define-constant bytevector-immutable-flag - (expt 2 (- (constant bytevector-length-offset) 1))) -(define-constant iptr maximum-bytevector-length - (min (- (expt 2 (fx- (constant ptr-bits) (constant bytevector-length-offset))) 1) - (constant most-positive-fixnum))) - -(define-constant code-flags-offset (constant ordinary-type-bits)) - -(define-constant char-data-offset 8) - -(define-constant type-binary-port - (fxlogor (ash (constant port-flag-binary) (constant port-flags-offset)) - (constant type-port))) -(define-constant type-textual-port (constant type-port)) -(define-constant type-input-port - (fxlogor (ash (constant port-flag-input) (constant port-flags-offset)) - (constant type-port))) -(define-constant type-binary-input-port - (fxlogor (ash (constant port-flag-binary) (constant port-flags-offset)) - (constant type-input-port))) -(define-constant type-textual-input-port (constant type-input-port)) -(define-constant type-output-port - (fxlogor (ash (constant port-flag-output) (constant port-flags-offset)) - (constant type-port))) -(define-constant type-binary-output-port - (fxlogor (ash (constant port-flag-binary) (constant port-flags-offset)) - (constant type-output-port))) -(define-constant type-textual-output-port (constant type-output-port)) -(define-constant type-io-port - (fxlogor (constant type-input-port) - (constant type-output-port))) -(define-constant type-system-code - (fxlogor (constant type-code) - (fxsll (constant code-flag-system) - (constant code-flags-offset)))) -(define-constant type-continuation-code - (fxlogor (constant type-code) - (fxsll (constant code-flag-continuation) - (constant code-flags-offset)))) -(define-constant type-guardian-code - (fxlogor (constant type-code) - (fxsll (constant code-flag-guardian) - (constant code-flags-offset)))) - -;; type checks are generally performed by applying the mask to the object -;; then comparing against the type code. a mask equal to -;; (constant byte-constant-mask) implies that the object being -;; type-checked must have zeros in all but the low byte if it is to pass -;; the check so that anything between a byte and full word comparison -;; can be used. - -(define-constant byte-constant-mask (- (ash 1 (constant ptr-bits)) 1)) - -(define-constant mask-fixnum (- (ash 1 (constant fixnum-offset)) 1)) - -;;; octets are fixnums in the range 0..255 -(define-constant mask-octet (lognot (ash #xff (constant fixnum-offset)))) -(define-constant type-octet (constant type-fixnum)) - -(define-constant mask-pair #b111) -(define-constant mask-flonum #b111) -(define-constant mask-symbol #b111) -(define-constant mask-closure #b111) -(define-constant mask-immediate #b111) -(define-constant mask-typed-object #b111) - -(define-constant mask-boolean #b11110111) -(define-constant mask-char #xFF) -(define-constant mask-false (constant byte-constant-mask)) -(define-constant mask-eof (constant byte-constant-mask)) -(define-constant mask-unbound (constant byte-constant-mask)) -(define-constant mask-nil (constant byte-constant-mask)) -(define-constant mask-bwp (constant byte-constant-mask)) - -;;; vector type/length field must look like a fixnum. an immutable bit sits just above the fixnum tag, with the length above that. -(define-constant mask-vector (constant mask-fixnum)) -(define-constant mask-bytevector #b11) -(define-constant mask-string #b111) -(define-constant mask-fxvector #b111) -(define-constant mask-other-number #b1111) -(define-constant mask-bignum #b11111) -(define-constant mask-bignum-sign #b100000) -(define-constant mask-signed-bignum - (fxlogor - (constant mask-bignum) - (constant mask-bignum-sign))) -(define-constant mask-ratnum (constant byte-constant-mask)) -(define-constant mask-inexactnum (constant byte-constant-mask)) -(define-constant mask-exactnum (constant byte-constant-mask)) -(define-constant mask-rtd-counts (constant byte-constant-mask)) -(define-constant mask-record #b111) -(define-constant mask-port #xFF) -(define-constant mask-binary-port - (fxlogor (fxsll (constant port-flag-binary) (constant port-flags-offset)) - (constant mask-port))) -(define-constant mask-textual-port (constant mask-binary-port)) -(define-constant mask-input-port - (fxlogor (fxsll (constant port-flag-input) (constant port-flags-offset)) - (fx- (fxsll 1 (constant port-flags-offset)) 1))) -(define-constant mask-binary-input-port - (fxlogor (fxsll (constant port-flag-binary) (constant port-flags-offset)) - (constant mask-input-port))) -(define-constant mask-textual-input-port (constant mask-binary-input-port)) -(define-constant mask-output-port - (fxlogor (fxsll (constant port-flag-output) (constant port-flags-offset)) - (fx- (fxsll 1 (constant port-flags-offset)) 1))) -(define-constant mask-binary-output-port - (fxlogor (fxsll (constant port-flag-binary) (constant port-flags-offset)) - (constant mask-output-port))) -(define-constant mask-textual-output-port (constant mask-binary-output-port)) -(define-constant mask-box #x7F) -(define-constant mask-code #xFF) -(define-constant mask-system-code - (fxlogor (fxsll (constant code-flag-system) (constant code-flags-offset)) - (fx- (fxsll 1 (constant code-flags-offset)) 1))) -(define-constant mask-continuation-code - (fxlogor (fxsll (constant code-flag-continuation) (constant code-flags-offset)) - (fx- (fxsll 1 (constant code-flags-offset)) 1))) -(define-constant mask-guardian-code - (fxlogor (fxsll (constant code-flag-guardian) (constant code-flags-offset)) - (fx- (fxsll 1 (constant code-flags-offset)) 1))) -(define-constant mask-thread (constant byte-constant-mask)) -(define-constant mask-tlc (constant byte-constant-mask)) - -(define-constant type-mutable-vector (constant type-vector)) -(define-constant type-immutable-vector - (fxlogor (constant type-vector) (constant vector-immutable-flag))) -(define-constant mask-mutable-vector - (fxlogor (constant mask-vector) (constant vector-immutable-flag))) - -(define-constant type-mutable-string (constant type-string)) -(define-constant type-immutable-string - (fxlogor (constant type-string) (constant string-immutable-flag))) -(define-constant mask-mutable-string - (fxlogor (constant mask-string) (constant string-immutable-flag))) - -(define-constant type-mutable-fxvector (constant type-fxvector)) -(define-constant type-immutable-fxvector - (fxlogor (constant type-fxvector) (constant fxvector-immutable-flag))) -(define-constant mask-mutable-fxvector - (fxlogor (constant mask-fxvector) (constant fxvector-immutable-flag))) - -(define-constant type-mutable-bytevector (constant type-bytevector)) -(define-constant type-immutable-bytevector - (fxlogor (constant type-bytevector) (constant bytevector-immutable-flag))) -(define-constant mask-mutable-bytevector - (fxlogor (constant mask-bytevector) (constant bytevector-immutable-flag))) - -(define-constant type-mutable-box (constant type-box)) -(define-constant mask-mutable-box (constant byte-constant-mask)) - -(define-constant fixnum-factor (expt 2 (constant fixnum-offset))) -(define-constant vector-length-factor (expt 2 (constant vector-length-offset))) -(define-constant string-length-factor (expt 2 (constant string-length-offset))) -(define-constant bignum-length-factor (expt 2 (constant bignum-length-offset))) -(define-constant fxvector-length-factor (expt 2 (constant fxvector-length-offset))) -(define-constant bytevector-length-factor (expt 2 (constant bytevector-length-offset))) -(define-constant char-factor (expt 2 (constant char-data-offset))) - -;;; record-datatype must be defined before we include layout.ss -;;; (maybe should move into that file??) -;;; We allow Scheme inputs for both signed and unsigned integers to range from -;;; -2^(b-1)..2^b-1, e.g., for 32-bit, -2^31..2^32-1. -(macro-define-structure (fld name mutable? type byte)) - -(eval-when (compile load eval) -(define-syntax foreign-datatypes - (identifier-syntax - '((scheme-object (constant ptr-bytes) (lambda (x) #t)) - (double-float 8 flonum?) - (single-float 4 flonum?) - (integer-8 1 $integer-8?) - (unsigned-8 1 $integer-8?) - (integer-16 2 $integer-16?) - (unsigned-16 2 $integer-16?) - (integer-24 3 $integer-24?) - (unsigned-24 3 $integer-24?) - (integer-32 4 $integer-32?) - (unsigned-32 4 $integer-32?) - (integer-40 5 $integer-40?) - (unsigned-40 5 $integer-40?) - (integer-48 6 $integer-48?) - (unsigned-48 6 $integer-48?) - (integer-56 7 $integer-56?) - (unsigned-56 7 $integer-56?) - (integer-64 8 $integer-64?) - (unsigned-64 8 $integer-64?) - (fixnum (constant ptr-bytes) fixnum?) - (char 1 $foreign-char?) - (wchar (fxsrl (constant wchar-bits) 3) $foreign-wchar?) - (boolean (fxsrl (constant int-bits) 3) (lambda (x) #t))))) -) - -(define-syntax record-datatype - (with-syntax ((((type bytes pred) ...) - (datum->syntax #'* foreign-datatypes))) - (lambda (x) - (syntax-case x (list cases) - [(_ list) #''(type ...)] - [(_ cases ty handler else-expr) - #'(case ty - [(type) (handler type bytes pred)] - ... - [else else-expr])])))) - -(define-syntax c-alloc-align - (syntax-rules () - ((_ n) - (fxlogand (fx+ n (fx- (constant byte-alignment) 1)) - (fxlognot (fx- (constant byte-alignment) 1)))))) - -(eval-when (compile load eval) -(define-syntax filter-foreign-type - ; for $object-ref, foreign-ref, etc. - ; foreign-procedure and foreign-callable have their own - ; filter-type in syntax.ss - (with-syntax ([alist (datum->syntax #'* - `((ptr . scheme-object) - (iptr . - ,(constant-case ptr-bits - [(32) 'integer-32] - [(64) 'integer-64])) - (uptr . - ,(constant-case ptr-bits - [(32) 'unsigned-32] - [(64) 'unsigned-64])) - (void* . - ,(constant-case ptr-bits - [(32) 'unsigned-32] - [(64) 'unsigned-64])) - (int . - ,(constant-case int-bits - [(32) 'integer-32] - [(64) 'integer-64])) - (unsigned . - ,(constant-case int-bits - [(32) 'unsigned-32] - [(64) 'unsigned-64])) - (unsigned-int . - ,(constant-case int-bits - [(32) 'unsigned-32] - [(64) 'unsigned-64])) - (short . - ,(constant-case short-bits - [(16) 'integer-16] - [(32) 'integer-32])) - (unsigned-short . - ,(constant-case short-bits - [(16) 'unsigned-16] - [(32) 'unsigned-32])) - (long . - ,(constant-case long-bits - [(32) 'integer-32] - [(64) 'integer-64])) - (unsigned-long . - ,(constant-case long-bits - [(32) 'unsigned-32] - [(64) 'unsigned-64])) - (long-long . - ,(constant-case long-long-bits - [(64) 'integer-64])) - (unsigned-long-long . - ,(constant-case long-long-bits - [(64) 'unsigned-64])) - (wchar_t . wchar) - (size_t . - ,(constant-case size_t-bits - [(32) 'unsigned-32] - [(64) 'unsigned-64])) - (ssize_t . - ,(constant-case size_t-bits - [(32) 'integer-32] - [(64) 'integer-64])) - (ptrdiff_t . - ,(constant-case ptrdiff_t-bits - [(32) 'integer-32] - [(64) 'integer-64])) - (float . single-float) - (double . double-float)))]) - (syntax-rules () - [(_ ?x) - (let ([x ?x]) - (cond - [(assq x 'alist) => cdr] - [else x]))]))) -(define-syntax filter-scheme-type - ; for define-primitive-structure-disps - (with-syntax ([alist (datum->syntax #'* - `((byte . signed-8) - (octet . unsigned-8) - (I32 . integer-32) - (U32 . unsigned-32) - (I64 . integer-64) - (U64 . unsigned-64) - (bigit . - ,(constant-case bigit-bits - [(16) 'unsigned-16] - [(32) 'unsigned-32])) - (string-char . - ,(constant-case string-char-bits - [(32) 'unsigned-32]))))]) - (syntax-rules () - [(_ ?x) - (let ([x ?x]) - (cond - [(assq x 'alist) => cdr] - [else x]))]))) -) - -(define-syntax define-primitive-structure-disps - (lambda (x) - (include "layout.ss") - (define make-name-field-disp - (lambda (name field-name) - (construct-name name name "-" field-name "-disp"))) - (define split - (lambda (ls) - (let f ([x (car ls)] [ls (cdr ls)]) - (if (null? ls) - (list '() x) - (let ([rest (f (car ls) (cdr ls))]) - (list (cons x (car rest)) (cadr rest))))))) - (define get-fld-byte - (lambda (fn flds) - (let loop ([flds flds]) - (let ([fld (car flds)]) - (if (eq? (fld-name fld) fn) - (fld-byte fld) - (loop (cdr flds))))))) - (define parse-field - (lambda (field) - (syntax-case field (constant) - [(field-type field-name) - (list #'field-type #'field-name #f)] - [(field-type field-name n) - (integer? (datum n)) - (list #'field-type #'field-name (datum n))] - [(field-type field-name (constant sym)) - (list #'field-type #'field-name - (lookup-constant (datum sym)))]))) - (syntax-case x () - [(_ name type (field1 field2 ...)) - (andmap identifier? #'(name type)) - (with-syntax ([((field-type field-name field-length) ...) - (map parse-field #'(field1 field2 ...))]) - (with-values (compute-field-offsets 'define-primitive-structure-disps - (- (constant typemod) (lookup-constant (datum type))) - (map (lambda (type name len) - (list (filter-scheme-type type) - name - (or len 1))) - (datum (field-type ...)) - (datum (field-name ...)) - #'(field-length ...))) - (lambda (pm mpm flds size) - (let ([var? (eq? (car (last-pair #'(field-length ...))) 0)]) - (with-syntax ([(name-field-disp ...) - (map (lambda (fn) - (make-name-field-disp #'name fn)) - (datum (field-name ...)))] - [(field-disp ...) - (map (lambda (fn) (get-fld-byte fn flds)) - (datum (field-name ...)))] - [size (if var? size (c-alloc-align size))] - [size-name - (construct-name - #'name - (if var? "header-size-" "size-") - #'name)]) - #'(begin - (putprop - 'name - '*fields* - (map list - '(field-name ...) - '(field-type ...) - '(field-disp ...) - '(field-length ...))) - (define-constant size-name size) - (define-constant name-field-disp field-disp) - ...))))))]))) - -(define-primitive-structure-disps typed-object type-typed-object - ([iptr type])) - -(define-primitive-structure-disps pair type-pair - ([ptr car] - [ptr cdr])) - -(define-constant pair-shift (log2 (constant size-pair))) - -(define-primitive-structure-disps box type-typed-object - ([iptr type] - [ptr ref])) - -(define-primitive-structure-disps ephemeron type-pair - ([ptr car] - [ptr cdr] - [ptr next] ; `next` is needed by the GC to keep track of pending ephemerons - [ptr trigger-next])) ; `trigger-next` is similar, but for segment-specific lists - -(define-primitive-structure-disps tlc type-typed-object - ([iptr type] - [ptr keyval] - [ptr ht] - [ptr next])) - -(define-primitive-structure-disps symbol type-symbol - ([ptr value] - [ptr pvalue] - [ptr plist] - [ptr name] - [ptr splist] - [ptr hash])) - -(define-primitive-structure-disps ratnum type-typed-object - ([iptr type] - [ptr numerator] - [ptr denominator])) - -(define-primitive-structure-disps vector type-typed-object - ([iptr type] - [ptr data 0])) - -(define-primitive-structure-disps fxvector type-typed-object - ([iptr type] - [ptr data 0])) - -(constant-case ptr-bits - [(32) - (define-primitive-structure-disps bytevector type-typed-object - ([iptr type] - [ptr pad] ; pad needed to maintain double-word alignment for data - [octet data 0]))] - [(64) - (define-primitive-structure-disps bytevector type-typed-object - ([iptr type] - [octet data 0]))]) - -; WARNING: implementation of real-part and imag-part assumes that -; flonums are subobjects of inexactnums. -(define-primitive-structure-disps flonum type-flonum - ([double data])) - -; on 32-bit systems, the iptr pad will have no effect above and -; beyond the normal padding. on 64-bit systems, the pad -; guarantees that the forwarding address will not overwrite -; real-part, which may share storage with a flonum that has -; not yet been forwarded. -(define-primitive-structure-disps inexactnum type-typed-object - ([iptr type] - [iptr pad] - [double real] - [double imag])) - -(define-primitive-structure-disps exactnum type-typed-object - ([iptr type] - [ptr real] - [ptr imag])) - -(define-primitive-structure-disps closure type-closure - ([ptr code] - [ptr data 0])) - -(define-primitive-structure-disps port type-typed-object - ([iptr type] - [ptr handler] - [iptr ocount] - [iptr icount] - [ptr olast] - [ptr obuffer] - [ptr ilast] - [ptr ibuffer] - [ptr info] - [ptr name])) - -(define-primitive-structure-disps string type-typed-object - ([iptr type] - [string-char data 0])) - -(define-primitive-structure-disps bignum type-typed-object - ([iptr type] - [bigit data 0])) - -(define-primitive-structure-disps code type-typed-object - ([iptr type] - [iptr length] - [ptr reloc] - [ptr name] - [ptr arity-mask] - [iptr closure-length] - [ptr info] - [ptr pinfo*] - [octet data 0])) - -(define-primitive-structure-disps reloc-table typemod - ([iptr size] - [ptr code] - [uptr data 0])) - -(define-primitive-structure-disps continuation type-closure - ([ptr code] - [ptr stack] - [iptr stack-length] - [iptr stack-clength] - [ptr link] - [ptr return-address] - [ptr winders])) - -(define-primitive-structure-disps record type-typed-object - ([ptr type] - [ptr data 0])) - -(define-primitive-structure-disps thread type-typed-object - ([ptr type] [uptr tc])) - -(define-constant virtual-register-count 16) - -;;; make sure gc sweeps all ptrs -(define-primitive-structure-disps tc typemod - ([void* arg-regs (constant asm-arg-reg-max)] - [void* ac0] - [void* ac1] - [void* sfp] - [void* cp] - [void* esp] - [void* ap] - [void* eap] - [void* ret] - [void* trap] - [void* xp] - [void* yp] - [void* ts] - [void* td] - [void* real_eap] - [ptr virtual-registers (constant virtual-register-count)] - [ptr guardian-entries] - [ptr cchain] - [ptr code-ranges-to-flush] - [U32 random-seed] - [I32 active] - [void* scheme-stack] - [ptr stack-cache] - [ptr stack-link] - [iptr scheme-stack-size] - [ptr winders] - [ptr U] - [ptr V] - [ptr W] - [ptr X] - [ptr Y] - [ptr something-pending] - [ptr timer-ticks] - [ptr disable-count] - [ptr signal-interrupt-pending] - [ptr signal-interrupt-queue] - [ptr keyboard-interrupt-pending] - [ptr threadno] - [ptr current-input] - [ptr current-output] - [ptr current-error] - [ptr block-counter] - [ptr sfd] - [ptr current-mso] - [ptr target-machine] - [ptr fxlength-bv] - [ptr fxfirst-bit-set-bv] - [ptr null-immutable-vector] - [ptr null-immutable-fxvector] - [ptr null-immutable-bytevector] - [ptr null-immutable-string] - [ptr meta-level] - [ptr compile-profile] - [ptr generate-inspector-information] - [ptr generate-procedure-source-information] - [ptr generate-profile-forms] - [ptr optimize-level] - [ptr subset-mode] - [ptr suppress-primitive-inlining] - [ptr default-record-equal-procedure] - [ptr default-record-hash-procedure] - [ptr compress-format] - [ptr compress-level] - [void* lz4-out-buffer] - [U64 instr-counter] - [U64 alloc-counter] - [ptr parameters] - [ptr DSTBV] - [ptr SRCBV])) - -(define tc-field-list - (let f ([ls (oblist)] [params '()]) - (if (null? ls) - params - (f (cdr ls) - (let* ([sym (car ls)] - [str (symbol->string sym)] - [n (string-length str)]) - (if (and (> n 8) - (string=? (substring str 0 3) "tc-") - (string=? (substring str (- n 5) n) "-disp") - (getprop sym '*constant* #f)) - (cons (string->symbol (substring str 3 (- n 5))) params) - params)))))) - -(define-constant unactivate-mode-noop 0) -(define-constant unactivate-mode-deactivate 1) -(define-constant unactivate-mode-destroy 2) - -(define-primitive-structure-disps rtd-counts type-typed-object - ([iptr type] - [U64 timestamp] - [uptr data 256])) - -(define-primitive-structure-disps record-type type-typed-object - ([ptr type] - [ptr parent] - [ptr size] - [ptr pm] - [ptr mpm] - [ptr name] - [ptr flds] - [ptr flags] - [ptr uid] - [ptr counts])) - -(define-constant rtd-generative #b0001) -(define-constant rtd-opaque #b0010) -(define-constant rtd-sealed #b0100) - -; we do this as a macro here since we want the freshest version possible -; in syntax.ss when we use it as a patch, whereas we want the old -; version in non-patched record.ss, so he can operate on host-system -; record types. -(define-syntax make-record-call-args - (identifier-syntax - (lambda (flds size e*) - (let f ((flds flds) (b (constant record-data-disp)) (e* e*)) - (if (null? flds) - (if (< b (+ size (constant record-type-disp))) - (cons 0 (f flds (+ b (constant ptr-bytes)) e*)) - '()) - (let ((fld (car flds))) - (cond - [(< b (fld-byte fld)) - (cons 0 (f flds (+ b (constant ptr-bytes)) e*))] - [(> b (fld-byte fld)) - (f (cdr flds) b (cdr e*))] - [else ; (= b (fld-byte fld)) - (cons (if (eq? (filter-foreign-type (fld-type fld)) 'scheme-object) (car e*) 0) - (f (cdr flds) - (+ b (constant ptr-bytes)) - (cdr e*)))]))))))) - -(define-primitive-structure-disps guardian-entry typemod - ([ptr obj] - [ptr rep] - [ptr tconc] - [ptr next])) - -;;; forwarding addresses are recorded with a single forward-marker -;;; bit pattern (a special Scheme object) followed by the forwarding -;;; address, a ptr to the forwarded object. -(define-primitive-structure-disps forward typemod - ([ptr marker] - [ptr address])) - -(define-primitive-structure-disps cached-stack typemod - ([iptr size] - [ptr link])) - -(define-primitive-structure-disps rp-header typemod - ([ptr livemask] - [uptr toplink] - [iptr frame-size] - [uptr mv-return-address])) -(define-constant return-address-mv-return-address-disp - (- (constant rp-header-mv-return-address-disp) (constant size-rp-header))) -(define-constant return-address-frame-size-disp - (- (constant rp-header-frame-size-disp) (constant size-rp-header))) -(define-constant return-address-toplink-disp - (- (constant rp-header-toplink-disp) (constant size-rp-header))) -(define-constant return-address-livemask-disp - (- (constant rp-header-livemask-disp) (constant size-rp-header))) - -(define-syntax bigit-type - (lambda (x) - (with-syntax ([type (datum->syntax #'* (filter-scheme-type 'bigit))]) - #''type))) - -(define-syntax string-char-type - (lambda (x) - (with-syntax ([type (datum->syntax #'* (filter-scheme-type 'string-char))]) - #''type))) - -(define-constant annotation-debug #b0001) -(define-constant annotation-profile #b0010) -(define-constant annotation-all #b0011) - -(eval-when (compile load eval) -(define flag->mask - (lambda (m e) - (cond - [(fixnum? m) m] - [(and (symbol? m) (assq m e)) => cdr] - [(and (list? m) (eq? (car m) 'or)) - (let f ((ls (cdr m))) - (if (null? ls) - 0 - (fxlogor (flag->mask (car ls) e) (f (cdr ls)))))] - [(and (list? m) (eq? (car m) 'sll) (= (length m) 3)) - (fxsll (flag->mask (cadr m) e) (lookup-constant (caddr m)))] - [else ($oops 'flag->mask "invalid mask ~s" m)]))) -) - -(define-syntax define-flags - (lambda (exp) - (define mask-environment - (lambda (flags masks) - (let f ((flags flags) (masks masks) (e '())) - (if (null? flags) - e - (let ((mask (flag->mask (car masks) e))) - (f (cdr flags) (cdr masks) - (cons `(,(car flags) . ,mask) e))))))) - (syntax-case exp () - ((_k name (flag mask) ...) - (with-syntax ((env (datum->syntax #'_k - (mask-environment - (datum (flag ...)) - (datum (mask ...)))))) - #'(define-syntax name - (lambda (x) - (syntax-case x () - ((_k f (... ...)) - (datum->syntax #'_k - (flag->mask `(or ,@(datum (f (... ...)))) 'env))))))))))) - -(define-syntax any-set? - (syntax-rules () - ((_ mask x) - (not (fx= (fxlogand mask x) 0))))) - -(define-syntax all-set? - (syntax-rules () - ((_ mask x) - (let ((m mask)) (fx= (fxlogand m x) m))))) - -(define-syntax set-flags - (syntax-rules () - ((_ mask x) - (fxlogor mask x)))) - -(define-syntax reset-flags - (syntax-rules () - ((_ mask x) - (fxlogand (fxlognot mask) x)))) - -;;; prim-mask notes: -;;; - pure prim can (but need not) return same (by eqv?) value for same -;;; (by eqv?) args and causes no side effects -;;; - pure is not set when primitive can cause an effect, observe an effect, -;;; or allocate a mutable object. So set-car!, car, cons, equal?, and -;;; list? are not pure, while pair?, +, <, and char->integer are pure. -;;; - an mifoldable primitive can be folded in a machine-independent way -;;; when it gets constant arguments. we don't fold primitives that depend -;;; on machine characteristics, like most-positive-fixnum. (but we do -;;; have cp0 handlers for almost all of them that do the right thing.) -;;; - mifoldable does not imply pure. can fold car when it gets a constant -;;; (and thus immutable) argument, but it is not pure. -;;; - pure does not imply mifoldable, since a pure primitive might not be -;;; machine-independent. -(define-flags prim-mask - (system #b00000000000000000000001) - (primitive #b00000000000000000000010) - (keyword #b00000000000000000000100) - (r5rs #b00000000000000000001000) - (ieee #b00000000000000000010000) - (proc #b00000000000000000100000) - (discard #b00000000000000001000000) - (unrestricted #b00000000000000010000000) - (true #b00000000000000100000000) - (mifoldable #b00000000000001000000000) - (cp02 #b00000000000010000000000) - (cp03 #b00000000000100000000000) - (system-keyword #b00000000001000000000000) - (r6rs #b00000000010000000000000) - (pure (or #b00000000100000000000000 discard)) - (library-uid #b00000001000000000000000) - (boolean-valued #b00000010000000000000000) - (abort-op #b00000100000000000000000) - (unsafe #b00001000000000000000000) - (arith-op (or proc pure true)) - (alloc (or proc discard true)) - ; would be nice to check that these and only these actually have cp0 partial folders - (partial-folder (or cp02 cp03)) -) - -(define-flags cp0-info-mask - (pure-known #b0000000001) - (pure #b0000000010) - (ivory-known #b0000000100) - (ivory #b0000001000) - (simple-known #b0000010000) - (simple #b0000100000) - (boolean-valued-known #b0001000000) - (boolean-valued #b0010000000) -) - -(define-syntax define-flag-field - (lambda (exp) - (syntax-case exp () - ((k struct field (flag mask) ...) - (let () - (define getter-name - (lambda (f) - (construct-name #'k #'struct "-" f))) - (define setter-name - (lambda (f) - (construct-name #'k "set-" #'struct "-" f "!"))) - (with-syntax ((field-ref (getter-name #'field)) - (field-set! (construct-name #'k #'struct "-" #'field "-set!")) - ((flag-ref ...) (map getter-name #'(flag ...))) - ((flag-set! ...) (map setter-name #'(flag ...))) - (f->m (construct-name #'k #'struct "-" #'field - "-mask"))) - #'(begin - (define-flags f->m (flag mask) ...) - (define-syntax flag-ref - (lambda (x) - (syntax-case x () - ((kk x) (with-implicit (kk field-ref) - #'(any-set? (f->m flag) (field-ref x))))))) - ... - (define-syntax flag-set! - (lambda (x) - (syntax-case x () - ((kk x bool) - (with-implicit (kk field-ref field-set!) - #'(let ((t x)) - (field-set! t - (if bool - (set-flags (f->m flag) (field-ref t)) - (reset-flags (f->m flag) (field-ref t)))))))))) - ...))))))) - -;;; compile-time-environment structures - -(define-constant prelex-is-flags-offset 8) -(define-constant prelex-was-flags-offset 16) -(define-constant prelex-sticky-mask #b11111111) -(define-constant prelex-is-mask #b1111111100000000) - -(define-flag-field prelex flags - ; sticky flags: - (immutable-value #b0000000000000001) - ; is flags: - (assigned #b0000000100000000) - (referenced #b0000001000000000) - (seen #b0000010000000000) - (multiply-referenced #b0000100000000000) - ; was flags: - (was-assigned (sll assigned prelex-was-flags-offset)) - (was-referenced (sll referenced prelex-was-flags-offset)) - (was-multiply-referenced (sll multiply-referenced prelex-was-flags-offset)) - ; aggregate flags: - (seen/referenced (or seen referenced)) - (seen/assigned (or seen assigned)) - (referenced/assigned (or referenced assigned)) -) - -(macro-define-structure ($c-func) - ([code-record #f] ; (code func free ...) - [code-object #f] ; actual code object created by c-mkcode - [closure-record #f] ; (closure . func), if constant - [closure #f])) ; actual closure created by c-mkcode, if constant - -(define-syntax negated-flonum? - (syntax-rules () - ((_ x) (fx= ($flonum-sign x) 1)))) - -(define-syntax $nan? - (syntax-rules () - ((_ e) - (let ((x e)) - (float-type-case - [(ieee) (not (fl= x x))]))))) - -(define-syntax infinity? - (syntax-rules () - ((_ e) - (let ([x e]) - (float-type-case - [(ieee) (and (exceptional-flonum? x) (not ($nan? x)))]))))) - -(define-syntax exceptional-flonum? - (syntax-rules () - ((_ x) - (float-type-case - [(ieee) (fx= ($flonum-exponent x) #x7ff)])))) - -(define-syntax on-reset - (syntax-rules () - ((_ oops e1 e2 ...) - ($reset-protect (lambda () e1 e2 ...) (lambda () oops))))) - -(define-syntax $make-thread-parameter - (if-feature pthreads - (identifier-syntax make-thread-parameter) - (identifier-syntax make-parameter))) - -(define-syntax define-threaded - (if-feature pthreads - (syntax-rules () - [(_ var) (define-threaded var 'var)] - [(_ var expr) - (begin - (define tmp ($make-thread-parameter expr)) - (define-syntax var - (identifier-syntax - (id (tmp)) - ((set! id val) (tmp val)))))]) - (identifier-syntax define))) - -(define-syntax define-syntactic-monad - (lambda (x) - (syntax-case x () - ((_ name formal ...) - (andmap identifier? #'(name formal ...)) - #'(define-syntax name - (lambda (x) - (syntax-case x (lambda define) - ((key lambda more-formals . body) - (with-implicit (key formal ...) - #'(lambda (formal ... . more-formals) . body))) - ((key define (proc-name . more-formals) . body) - (with-implicit (key formal ...) - #'(define proc-name (lambda (formal ... . more-formals) . body)))) - ((key proc ((x e) (... ...)) arg (... ...)) - (andmap identifier? #'(x (... ...))) - (with-implicit (key formal ...) - (for-each - (lambda (x) - (unless (let mem ((ls #'(formal ...))) - (and (not (null? ls)) - (or (free-identifier=? x (car ls)) - (mem (cdr ls))))) - (syntax-error x (format "undeclared ~s monad binding" 'name)))) - #'(x (... ...))) - #'(let ((x e) (... ...)) - (proc formal ... arg (... ...))))) - ((key proc) #'(key proc ()))))))))) - -(define-syntax make-binding - (syntax-rules () - ((_ type value) (cons type value)))) -(define-syntax binding-type (syntax-rules () ((_ b) (car b)))) -(define-syntax binding-value (syntax-rules () ((_ b) (cdr b)))) -(define-syntax set-binding-type! - (syntax-rules () - ((_ b v) (set-car! b v)))) -(define-syntax set-binding-value! - (syntax-rules () - ((_ b v) (set-cdr! b v)))) -(define-syntax binding? - (syntax-rules () - ((_ x) (let ((t x)) (and (pair? t) (symbol? (car t))))))) - -;;; heap/stack management constants - -(define-constant collect-interrupt-index 1) -(define-constant timer-interrupt-index 2) -(define-constant keyboard-interrupt-index 3) -(define-constant signal-interrupt-index 4) -(define-constant maximum-interrupt-index 4) - -(define-constant ignore-event-flag 0) - -(define-constant default-timer-ticks 1000) -(define-constant default-collect-trip-bytes - (expt 2 (+ 20 (constant log2-ptr-bytes)))) -(define-constant default-heap-reserve-ratio 1.0) -(define-constant static-generation 255) -(define-constant default-max-nonstatic-generation 4) - -(constant-case address-bits - [(32) - (constant-case segment-table-levels - [(1) (define-constant segment-t1-bits 19)] ; table size: .5M words = 2M bytes - [(2) (define-constant segment-t2-bits 9) ; outer-table size: .5k words = 2k bytes - (define-constant segment-t1-bits 10)]) ; inner-table size: 1k words = 4k bytes - (define-constant segment-offset-bits 13) ; segment size: 8k bytes (2k ptrs) - (define-constant card-offset-bits 8)] ; card size: 256 bytes (64 ptrs) - [(64) - (constant-case segment-table-levels - [(2) (define-constant segment-t2-bits 25) ; outer-table size: 32M words = 268M bytes - (define-constant segment-t1-bits 25)] ; inner-table size: 32M words = 268M bytes - [(3) (define-constant segment-t3-bits 17) ; outer-table size: 128k words = 1M bytes - (define-constant segment-t2-bits 17) ; middle-table size: 128k words = 1M bytes - (define-constant segment-t1-bits 16)]) ; inner-table size: 64k words = 512k bytes - (define-constant segment-offset-bits 14) ; segment size: 16k bytes (2k ptrs) - (define-constant card-offset-bits 9)]) ; card size: 512 bytes (64 ptrs) - -(define-constant bytes-per-segment (ash 1 (constant segment-offset-bits))) -(define-constant segment-card-offset-bits (- (constant segment-offset-bits) (constant card-offset-bits))) -;;; cards-per-segment must be a multiple of ptr-bits, since gc sometimes -;;; processes dirty bytes in iptr-sized pieces -(define-constant cards-per-segment (ash 1 (constant segment-card-offset-bits))) -(define-constant bytes-per-card (ash 1 (constant card-offset-bits))) - -;;; minimum-segment-request is the minimum number of segments -;;; requested from the O/S when Scheme runs out of memory. -(define-constant minimum-segment-request 128) - -;;; alloc_waste_maximum determines the maximum amount wasted if a large -;;; object request or remembered-set scan request is made from Scheme -;;; (through S_get_more_room or S_scan_remembered_set). if more than -;;; alloc_maximum_waste bytes remain between ap and eap, ap is left -;;; unchanged. -(define-constant alloc-waste-maximum (ash (constant bytes-per-segment) -3)) - -;;; default-stack-size determines the length in bytes of the runtime stack -;;; used for execution of scheme programs. Since the stack is extended -;;; automatically by copying part of the stack into a continuation, -;;; it is not necessary to make the number very large, except for -;;; efficiency. Since the cost of invoking continuations is bounded by -;;; default-stack-size, it should not be made excessively large. -;;; stack-slop determines how much of the stack is available for routines -;;; that use a bounded amount of stack space, and thus don't need to -;;; check for stack overflow. - -;; Make default stack size a multiple of the segment size, but leave room for -;; two ptrs at the end (a forward marker and a pointer to the next segment of -;; this type --- used by garbage collector). -(define-constant default-stack-size - (- (* 4 (constant bytes-per-segment)) (* 2 (constant ptr-bytes)))) -(define-constant stack-slop (ceiling (/ (constant default-stack-size) 64))) -(define-constant stack-frame-limit (fxsrl (constant stack-slop) 1)) -;; one-shot-headroom must include stack-slop so min factor below is 2 -(define-constant one-shot-headroom (fx* (constant stack-slop) 3)) -;; shot-1-shot-flag is inserted into continuation length field to mark -;; a one-shot continuation shot. it must look like a negative byte -;; offset -(define-constant unscaled-shot-1-shot-flag -1) -(define-constant scaled-shot-1-shot-flag - (* (constant unscaled-shot-1-shot-flag) (constant ptr-bytes))) - -;;; underflow limit determines how much we're willing to copy on -;;; stack underflow/continuation invocation -(define-constant underflow-limit (* (constant ptr-bytes) 16)) - -;;; check assumptions -(let ([x (fxsrl (constant type-char) - (fx- (constant char-data-offset) - (constant fixnum-offset)))]) - (unless (fx= (fxlogand x (constant mask-fixnum)) (constant type-fixnum)) - ($oops 'cmacros.ss - "expected type-char/fixnum relationship does not hold"))) - -(define-syntax with-tc-mutex - (if-feature pthreads - (syntax-rules () - [(_ e1 e2 ...) - (dynamic-wind - (lambda () (disable-interrupts) (mutex-acquire $tc-mutex)) - (lambda () e1 e2 ...) - (lambda () (mutex-release $tc-mutex) (enable-interrupts)))]) - (identifier-syntax critical-section))) - -(define-constant hashtable-default-size 8) - -(define-constant eq-hashtable-subtype-normal 0) -(define-constant eq-hashtable-subtype-weak 1) -(define-constant eq-hashtable-subtype-ephemeron 2) - -; keep in sync with make-date -(define-constant dtvec-nsec 0) -(define-constant dtvec-sec 1) -(define-constant dtvec-min 2) -(define-constant dtvec-hour 3) -(define-constant dtvec-mday 4) -(define-constant dtvec-mon 5) -(define-constant dtvec-year 6) -(define-constant dtvec-wday 7) -(define-constant dtvec-yday 8) -(define-constant dtvec-isdst 9) -(define-constant dtvec-tzoff 10) -(define-constant dtvec-tzname 11) -(define-constant dtvec-size 12) - -(define-constant time-process 0) -(define-constant time-thread 1) -(define-constant time-duration 2) -(define-constant time-monotonic 3) -(define-constant time-utc 4) -(define-constant time-collector-cpu 5) -(define-constant time-collector-real 6) - -(define-syntax make-winder - (syntax-rules () - [(_ critical? in out) (vector critical? in out)])) -(define-syntax winder-critical? (syntax-rules () [(_ w) (vector-ref w 0)])) -(define-syntax winder-in (syntax-rules () [(_ w) (vector-ref w 1)])) -(define-syntax winder-out (syntax-rules () [(_ w) (vector-ref w 2)])) - -(define-syntax winder? - (syntax-rules () - [(_ ?w) - (let ([w ?w]) - (and (vector? w) - (fx= (vector-length w) 3) - (boolean? (winder-critical? w)) - (procedure? (winder-in w)) - (procedure? (winder-out w))))])) - -(define-syntax default-run-cp0 - (lambda (x) - (syntax-case x () - [(k) (datum->syntax #'k '(lambda (cp0 x) (cp0 (cp0 x))))]))) - -;;; A state-case expression must take the following form: -;;; (state-case var eof-clause clause ... else-clause) -;;; eof-clause and else-clause must take the form -;;; (eof exp1 exp2 ...) -;;; (else exp1 exp2 ...) -;;; and the remaining clauses must take the form -;;; (char-set exp1 exp2 ...) -;;; The value of var must be an eof object or a character. -;;; state-case selects the first clause matching the value of var and -;;; evaluates the expressions exp1 exp2 ... of that clause. If the -;;; value of var is an eof-object, eof-clause is selected. Otherwise, -;;; the clauses clause ... are considered from left to right. If the -;;; value of var is in the set of characters defined by the char-set of -;;; a given clause, the clause is selected. If no other clause is -;;; selected, else-clause is selected. - -;;; char-set may be -;;; * a single character, e.g., #\a, or -;;; * a list of subkeys, each of which is -;;; - a single character, or -;;; - a character range, e.g., (#\a - #\z) -;;; For example, (#\$ (#\a - #\z) (#\A - #\Z)) specifies the set -;;; containing $ and the uppercase and lowercase letters. -(define-syntax state-case - (lambda (x) - (define state-case-test - (lambda (cvar k) - (with-syntax ((cvar cvar)) - (syntax-case k (-) - (char - (char? (datum char)) - #'(char=? cvar char)) - ((char1 - char2) - (and (char? (datum char1)) (char? (datum char2))) - #'(char<=? char1 cvar char2)) - (predicate - (identifier? #'predicate) - #'(predicate cvar)))))) - (define state-case-help - (lambda (cvar clauses) - (syntax-case clauses (else) - (((else exp1 exp2 ...)) - #'(begin exp1 exp2 ...)) - ((((k ...) exp1 exp2 ...) . more) - (with-syntax (((test ...) - (map (lambda (k) (state-case-test cvar k)) - #'(k ...))) - (rest (state-case-help cvar #'more))) - #'(if (or test ...) (begin exp1 exp2 ...) rest))) - (((k exp1 exp2 ...) . more) - (with-syntax ((test (state-case-test cvar #'k)) - (rest (state-case-help cvar #'more))) - #'(if test (begin exp1 exp2 ...) rest)))))) - (syntax-case x (eof) - ((_ cvar (eof exp1 exp2 ...) more ...) - (identifier? #'cvar) - (with-syntax ((rest (state-case-help #'cvar #'(more ...)))) - #'(if (eof-object? cvar) - (begin exp1 exp2 ...) - rest)))))) - -;; the following (old) version of state-case creates a set of vectors sc1, ... -;; corresponding to each state-case in the file and records the frequency -;; with which each clause (numbered from 0) matches. this is how the reader -;; is "tuned". -; (let ([n 0]) -; (extend-syntax (state-case) -; [(state-case exp more ...) -; (with ([cvar (gensym)] -; [statvar (string->symbol (format "sc~a" (set! n (1+ n))))] -; [size (length '(more ...))]) -; (let ([cvar exp]) -; (unless (top-level-bound? 'statvar) -; (printf "creating ~s~%" 'statvar) -; (set! statvar (make-vector size 0))) -; (state-case-help statvar 0 cvar more ...)))])) -; -; (extend-syntax (state-case-help else) -; [(state-case-help svar i cvar) (rd-character-error cvar)] -; [(state-case-help svar i cvar [else exp1 exp2 ...]) -; (if (char<=? #\nul cvar #\rubout) -; (begin (vector-set! svar i (1+ (vector-ref svar i))) exp1 exp2 ...) -; (rd-character-error cvar))] -; [(state-case-help svar i cvar [(k1 ...) exp1 exp2 ...] more ...) -; (if (or (state-case-test cvar k1) ...) -; (begin (vector-set! svar i (1+ (vector-ref svar i))) exp1 exp2 ...) -; (with ([i (1+ 'i)]) -; (state-case-help svar i cvar more ...)))] -; [(state-case-help svar i cvar [k1 exp1 exp2 ...] more ...) -; (if (state-case-test cvar k1) -; (begin (vector-set! svar i (1+ (vector-ref svar i))) exp1 exp2 ...) -; (with ([i (1+ 'i)]) -; (state-case-help svar i cvar more ...)))]) - -(define-syntax message-lambda - (lambda (x) - (define (group i* clause*) - (let* ([n (fx+ (apply fxmax -1 i*) 1)] [v (make-vector n '())]) - (for-each - (lambda (i clause) - (vector-set! v i (cons clause (vector-ref v i)))) - i* clause*) - (let f ([i 0]) - (if (fx= i n) - '() - (let ([ls (vector-ref v i)]) - (if (null? ls) - (f (fx+ i 1)) - (cons (reverse ls) (f (fx+ i 1))))))))) - (syntax-case x () - [(_ ?err [(k arg ...) b1 b2 ...] ...) - (let ([clause** (group (map length #'((arg ...) ...)) - #'([(k arg ...) b1 b2 ...] ...))]) - #`(let ([err ?err]) - (case-lambda - #,@(map (lambda (clause*) - (with-syntax ([([(k arg ...) b1 b2 ...] ...) clause*] - [(t0 t1 ...) - (with-syntax ([([(k arg ...) . body] . rest) clause*]) - (generate-temporaries #'(k arg ...)))]) - #'[(t0 t1 ...) - (case t0 - [(k) (let ([arg t1] ...) b1 b2 ...)] - ... - [else (err t0 t1 ...)])])) - clause**) - [(msg . args) (apply err msg args)])))]))) - -(define-syntax set-who! - (lambda (x) - (syntax-case x () - [(k #(prefix id) e) - (and (identifier? #'prefix) (identifier? #'id)) - (with-implicit (k who) - (with-syntax ([ext-id (construct-name #'id #'prefix #'id)]) - #'(set! ext-id (let ([who 'id]) (rec id e)))))] - [(k id e) - (identifier? #'id) - (with-implicit (k who) - #'(set! id (let ([who 'id]) e)))]))) - -(define-syntax define-who - (lambda (x) - (syntax-case x () - [(k (id . args) b1 b2 ...) - #'(k id (lambda args b1 b2 ...))] - [(k #(prefix id) e) - (and (identifier? #'prefix) (identifier? #'id)) - (with-implicit (k who) - (with-syntax ([ext-id (construct-name #'id #'prefix #'id)]) - #'(define ext-id (let ([who 'id]) (rec id e)))))] - [(k id e) - (identifier? #'id) - (with-implicit (k who) - #'(define id (let ([who 'id]) e)))]))) - -(define-syntax trace-define-who - (lambda (x) - (syntax-case x () - [(k (id . args) b1 b2 ...) - #'(k id (lambda args b1 b2 ...))] - [(k id e) - (identifier? #'id) - (with-implicit (k who) - #'(trace-define id (let ([who 'id]) e)))]))) - -(define-syntax safe-assert - (lambda (x) - (syntax-case x () - [(_ e1 e2 ...) - (if (fx= (debug-level) 0) - #'(void) - #'(begin (assert e1) (assert e2) ...))]))) - -(define-syntax self-evaluating? - (syntax-rules () - [(_ ?x) - (let ([x ?x]) - (or (number? x) - (boolean? x) - (char? x) - (string? x) - (bytevector? x) - (fxvector? x) - (memq x '(#!eof #!bwp #!base-rtd))))])) - -;;; datatype support -(define-syntax define-datatype - (lambda (x) - (define iota - (case-lambda - [(n) (iota 0 n)] - [(i n) (if (= n 0) '() (cons i (iota (+ i 1) (- n 1))))])) - (define construct-name - (lambda (template-identifier . args) - (datum->syntax - template-identifier - (string->symbol - (apply string-append - (map (lambda (x) - (if (string? x) - x - (symbol->string (syntax->datum x)))) - args)))))) - (syntax-case x () - [(_ dtname (vname field ...) ...) - (identifier? #'dtname) - #'(define-datatype (dtname) (vname field ...) ...)] - [(_ (dtname dtfield-spec ...) (vname field ...) ...) - (and (andmap identifier? #'(vname ...)) (andmap identifier? #'(field ... ...))) - (let () - (define split-name - (lambda (x) - (let ([sym (syntax->datum x)]) - (if (gensym? sym) - (cons (datum->syntax x (string->symbol (symbol->string sym))) x) - (cons x (datum->syntax x (gensym (symbol->string sym)))))))) - (with-syntax ([(dtname . dtuid) (split-name #'dtname)] - [((vname . vuid) ...) (map split-name #'(vname ...))] - [(dtfield ...) - (map (lambda (spec) - (syntax-case spec (immutable mutable) - [(immutable name) (identifier? #'name) #'name] - [(mutable name) (identifier? #'name) #'name] - [_ (syntax-error spec "invalid datatype field specifier")])) - #'(dtfield-spec ...))]) - (with-syntax ([dtname? (construct-name #'dtname #'dtname "?")] - [dtname-case (construct-name #'dtname #'dtname "-case")] - [dtname-variant (construct-name #'dtname #'dtname "-variant")] - [(dtname-dtfield ...) - (map (lambda (field) - (construct-name #'dtname #'dtname "-" field)) - #'(dtfield ...))] - [(dtname-dtfield-set! ...) - (fold-right - (lambda (dtf ls) - (syntax-case dtf (mutable immutable) - [(immutable name) ls] - [(mutable name) (cons (construct-name #'dtname #'dtname "-" #'name "-set!") ls)])) - '() - #'(dtfield-spec ...))] - [((vname-field ...) ...) - (map (lambda (vname fields) - (map (lambda (field) - (construct-name #'dtname - vname "-" field)) - fields)) - #'(vname ...) - #'((field ...) ...))] - [(raw-make-vname ...) - (map (lambda (x) - (construct-name #'dtname - "make-" x)) - #'(vname ...))] - [(make-vname ...) - (map (lambda (x) - (construct-name #'dtname - #'dtname "-" x)) - #'(vname ...))] - ; wash away gensyms for dtname-case - [(pretty-vname ...) - (map (lambda (vname) - (construct-name vname vname)) - #'(vname ...))] - [(i ...) (iota (length #'(vname ...)))] - [((fvar ...) ...) (map generate-temporaries #'((field ...) ...))]) - #'(module (dtname? (dtname-case dtname-variant vname-field ... ...) dtname-dtfield ... dtname-dtfield-set! ... make-vname ...) - (define-record-type dtname - (nongenerative dtuid) - (fields (immutable variant) dtfield-spec ...)) - (module (make-vname vname-field ...) - (define-record-type (vname make-vname vname?) - (nongenerative vuid) - (parent dtname) - (fields (immutable field) ...) - (protocol - (lambda (make-new) - (lambda (dtfield ... field ...) - ((make-new i dtfield ...) field ...)))))) - ... - (define-syntax dtname-case - (lambda (x) - (define make-clause - (lambda (x) - (syntax-case x (pretty-vname ...) - [(pretty-vname (fvar ...) e1 e2 (... ...)) - #'((i) (let ([fvar (vname-field t)] ...) - e1 e2 (... ...)))] - ...))) - (syntax-case x (else) - [(__ e0 - (v (fld (... ...)) e1 e2 (... ...)) - (... ...) - (else e3 e4 (... ...))) - ; could discard else clause if all variants are mentioned - (with-syntax ([(clause (... ...)) - (map make-clause - #'((v (fld (... ...)) e1 e2 (... ...)) - (... ...)))]) - #'(let ([t e0]) - (case (dtname-variant t) - clause - (... ...) - (else e3 e4 (... ...)))))] - [(__ e0 - (v (fld (... ...)) e1 e2 (... ...)) - (... ...)) - (let f ([ls1 (list #'pretty-vname ...)]) - (or (null? ls1) - (and (let g ([ls2 #'(v (... ...))]) - (if (null? ls2) - (syntax-error x - (format "unhandled `~s' variant in" - (syntax->datum (car ls1)))) - (or (literal-identifier=? (car ls1) (car ls2)) - (g (cdr ls2))))) - (f (cdr ls1))))) - (with-syntax ([(clause (... ...)) - (map make-clause - #'((v (fld (... ...)) e1 e2 (... ...)) - (... ...)))]) - #'(let ([t e0]) - (case (dtname-variant t) - clause - (... ...))))])))))))]))) - -; support for changing from old to new nongenerative record types -(define-syntax update-record-type - (syntax-rules () - [(_ (name make-name pred?) (accessor ...) (mutator ...) old-defn new-defn) - (module (name make-name pred? accessor ... mutator ...) - (module old (pred? accessor ... mutator ...) old-defn) - (module new (name make-name pred? accessor ... mutator ...) new-defn) - (import (only new name make-name)) - (define pred? - (lambda (x) - (or ((let () (import old) pred?) x) - ((let () (import new) pred?) x)))) - (define accessor - (lambda (x) - ((if ((let () (import old) pred?) x) - (let () (import old) accessor) - (let () (import new) accessor)) - x))) - ... - (define mutator - (lambda (x v) - ((if ((let () (import old) pred?) x) - (let () (import old) mutator) - (let () (import new) mutator)) - x v))) - ...)])) - -(define-syntax type-check - (lambda (x) - (syntax-case x () - [(_ who type arg) - (identifier? #'type) - #`(let ([x arg]) - (unless (#,(construct-name #'type #'type "?") x) - ($oops who #,(format "~~s is not a ~a" (datum type)) x)))] - [(_ who type pred arg) - (string? (datum type)) - #`(let ([x arg]) - (unless (pred x) - ($oops who #,(format "~~s is not a ~a" (datum type)) x)))]))) - -(eval-when (load eval) -(define-syntax lookup-libspec - (lambda (x) - (syntax-case x () - [(_ x) - (identifier? #'x) - #`(quote #,(datum->syntax #'x - (let ((x (datum x))) - (or ($sgetprop x '*libspec* #f) - ($oops 'lookup-libspec "~s is undefined" x)))))]))) - -(define-syntax lookup-does-not-expect-headroom-libspec - (lambda (x) - (syntax-case x () - [(_ x) - (identifier? #'x) - #`(quote #,(datum->syntax #'x - (let ((x (datum x))) - (or ($sgetprop x '*does-not-expect-headroom-libspec* #f) - ($oops 'lookup-does-not-expect-headroom-libspec "~s is undefined" x)))))]))) - -(define-syntax lookup-c-entry - (lambda (x) - (syntax-case x () - ((_ x) - (identifier? #'x) - (let ((sym (datum x))) - (datum->syntax #'x - (or ($sgetprop sym '*c-entry* #f) - ($oops 'lookup-c-entry "~s is undefined" sym)))))))) - -(let () - (define-syntax declare-library-entries - (lambda (x) - (syntax-case x () - ((_ (name closure? interface error? has-does-not-expect-headroom-version?) ...) - (with-syntax ([(index-base ...) (enumerate (datum (name ...)))]) - (for-each (lambda (name closure? interface error? has-does-not-expect-headroom-version?) - (define (nnfixnum? x) (and (fixnum? x) (fxnonnegative? x))) - (unless (and (symbol? name) - (boolean? closure?) - (nnfixnum? interface) - (boolean? error?)) - ($oops 'declare-library-entries "invalid entry for ~s" name))) - (datum (name ...)) - (datum (closure? ...)) - (datum (interface ...)) - (datum (error? ...)) - (datum (has-does-not-expect-headroom-version? ...))) - #`(begin - (define-constant library-entry-vector-size #,(* (length (datum (index-base ...))) 2)) - (for-each (lambda (xname xindex-base xclosure? xinterface xerror? xhas-does-not-expect-headroom-version?) - ($sputprop xname '*libspec* - (make-libspec xname - (make-libspec-flags xindex-base #f xclosure? xinterface xerror? xhas-does-not-expect-headroom-version?))) - (when xhas-does-not-expect-headroom-version? - ($sputprop xname '*does-not-expect-headroom-libspec* - (make-libspec xname - (make-libspec-flags xindex-base #t xclosure? xinterface xerror? xhas-does-not-expect-headroom-version?))))) - '(name ...) - '(index-base ...) - '(closure? ...) - '(interface ...) - '(error? ...) - '(has-does-not-expect-headroom-version? ...)))))))) - - (declare-library-entries - (main #f 0 #f #f) ;; fake entry for main, never called directly (part of fasl load) - (car #f 1 #t #t) - (cdr #f 1 #t #t) - (unbox #f 1 #t #t) - (set-box! #f 2 #t #t) - (box-cas! #f 3 #t #t) - (= #f 2 #f #t) - (< #f 2 #f #t) - (> #f 2 #f #t) - (<= #f 2 #f #t) - (>= #f 2 #f #t) - (+ #f 2 #f #t) - (- #f 2 #f #t) - (* #f 2 #f #t) - (/ #f 2 #f #t) - (unsafe-read-char #f 1 #f #t) - (safe-read-char #f 1 #f #t) - (unsafe-peek-char #f 1 #f #t) - (safe-peek-char #f 1 #f #t) - (unsafe-write-char #f 2 #f #t) - (safe-write-char #f 2 #f #t) - (unsafe-newline #f 1 #f #t) - (safe-newline #f 1 #f #t) - ($top-level-value #f 1 #f #t) - (event #f 0 #f #t) - (zero? #f 1 #f #t) - (1+ #f 1 #f #t) - (1- #f 1 #f #t) - (fx+ #f 2 #t #t) - (fx- #f 2 #t #t) - (fx= #f 2 #t #t) - (fx< #f 2 #t #t) - (fx> #f 2 #t #t) - (fx<= #f 2 #t #t) - (fx>= #f 2 #t #t) - (fl+ #f 2 #t #t) - (fl- #f 2 #t #t) - (fl* #f 2 #t #t) - (fl/ #f 2 #t #t) - (fl= #f 2 #t #t) - (fl< #f 2 #t #t) - (fl> #f 2 #t #t) - (fl<= #f 2 #t #t) - (fl>= #f 2 #t #t) - (callcc #f 1 #f #f) - (display-string #f 2 #f #t) - (cfl* #f 2 #f #t) - (cfl+ #f 2 #f #t) - (cfl- #f 2 #f #t) - (cfl/ #f 2 #f #t) - (negate #f 1 #f #t) - (flnegate #f 1 #t #t) - (call-error #f 0 #f #f) - (unsafe-unread-char #f 2 #f #t) - (map-car #f 1 #f #t) - (map-cons #f 2 #f #t) - (fx1+ #f 1 #t #t) - (fx1- #f 1 #t #t) - (fxzero? #f 1 #t #t) - (fxpositive? #f 1 #t #t) - (fxnegative? #f 1 #t #t) - (fxnonpositive? #f 1 #t #t) - (fxnonnegative? #f 1 #t #t) - (fxeven? #f 1 #t #t) - (fxodd? #f 1 #t #t) - (fxlogor #f 2 #t #t) - (fxlogxor #f 2 #t #t) - (fxlogand #f 2 #t #t) - (fxlognot #f 1 #t #t) - (fxsll #f 2 #f #t) - (fxsrl #f 2 #t #t) - (fxsra #f 2 #t #t) - (append #f 2 #f #t) - (values-error #f 0 #f #f) - (dooverflow #f 0 #f #f) - (dooverflood #f 0 #f #f) - (nonprocedure-code #f 0 #f #f) - (dounderflow #f 0 #f #f) - (dofargint32 #f 1 #f #f) - (map-cdr #f 1 #f #t) - (dofretint32 #f 1 #f #f) - (dofretuns32 #f 1 #f #f) - (domvleterr #f 0 #f #f) - (doargerr #f 0 #f #f) - (get-room #f 0 #f #f) - (map1 #f 2 #f #t) - (map2 #f 3 #f #t) - (for-each1 #f 2 #f #t) - (vector-ref #f 2 #t #t) - (vector-cas! #f 4 #t #t) - (vector-set! #f 3 #t #t) - (vector-length #f 1 #t #t) - (string-ref #f 2 #t #t) - (string-set! #f 3 #f #t) - (string-length #f 1 #t #t) - (char=? #f 2 #t #t) - (char? #f 2 #t #t) - (char<=? #f 2 #t #t) - (char>=? #f 2 #t #t) - (char->integer #f 1 #t #t) - (memv #f 2 #f #t) - (eqv? #f 2 #f #t) - (set-car! #f 2 #t #t) - (set-cdr! #f 2 #t #t) - (caar #f 1 #t #t) - (cadr #f 1 #t #t) - (cdar #f 1 #t #t) - (cddr #f 1 #t #t) - (caaar #f 1 #t #t) - (caadr #f 1 #t #t) - (cadar #f 1 #t #t) - (caddr #f 1 #t #t) - (cdaar #f 1 #t #t) - (cdadr #f 1 #t #t) - (cddar #f 1 #t #t) - (cdddr #f 1 #t #t) - (caaaar #f 1 #t #t) - (caaadr #f 1 #t #t) - (caadar #f 1 #t #t) - (caaddr #f 1 #t #t) - (cadaar #f 1 #t #t) - (cadadr #f 1 #t #t) - (caddar #f 1 #t #t) - (cadddr #f 1 #t #t) - (cdaaar #f 1 #t #t) - (cdaadr #f 1 #t #t) - (cdadar #f 1 #t #t) - (cdaddr #f 1 #t #t) - (cddaar #f 1 #t #t) - (cddadr #f 1 #t #t) - (cdddar #f 1 #t #t) - (cddddr #f 1 #t #t) - (dounderflow* #f 2 #f #t) - (call1cc #f 1 #f #f) - (dorest0 #f 0 #f #f) - (dorest1 #f 0 #f #f) - (dorest2 #f 0 #f #f) - (dorest3 #f 0 #f #f) - (dorest4 #f 0 #f #f) - (dorest5 #f 0 #f #f) - (add1 #f 1 #f #t) - (sub1 #f 1 #f #t) - (-1+ #f 1 #f #t) - (fx* #f 2 #t #t) - (dofargint64 #f 1 #f #f) - (dofretint64 #f 1 #f #f) - (dofretuns64 #f 1 #f #f) - (apply0 #f 2 #f #t) - (apply1 #f 3 #f #t) - (apply2 #f 4 #f #t) - (apply3 #f 5 #f #t) - (logand #f 2 #f #t) - (logor #f 2 #f #t) - (logxor #f 2 #f #t) - (lognot #f 1 #f #t) - (flround #f 1 #f #t) - (fxlogtest #f 2 #t #t) - (fxlogbit? #f 2 #f #t) - (logtest #f 2 #f #t) - (logbit? #f 2 #f #t) - (fxlogior #f 2 #t #t) - (logior #f 2 #f #t) - (fxlogbit0 #f 2 #t #t) - (fxlogbit1 #f 2 #t #t) - (logbit0 #f 2 #f #t) - (logbit1 #f 2 #f #t) - (vector-set-fixnum! #f 3 #t #t) - (fxvector-ref #f 2 #t #t) - (fxvector-set! #f 3 #t #t) - (fxvector-length #f 1 #t #t) - (scan-remembered-set #f 0 #f #f) - (fold-left1 #f 3 #f #t) - (fold-left2 #f 4 #f #t) - (fold-right1 #f 3 #f #t) - (fold-right2 #f 4 #f #t) - (for-each2 #f 3 #f #t) - (vector-map1 #f 2 #f #t) - (vector-map2 #f 3 #f #t) - (vector-for-each1 #f 2 #f #t) - (vector-for-each2 #f 3 #f #t) - (bytevector-length #f 1 #t #t) - (bytevector-s8-ref #f 2 #t #t) - (bytevector-u8-ref #f 2 #t #t) - (bytevector-s8-set! #f 3 #f #t) - (bytevector-u8-set! #f 3 #f #t) - (bytevector=? #f 2 #f #f) - (real->flonum #f 2 #f #t) - (unsafe-port-eof? #f 1 #f #t) - (unsafe-lookahead-u8 #f 1 #f #t) - (unsafe-unget-u8 #f 2 #f #t) - (unsafe-get-u8 #f 1 #f #t) - (unsafe-lookahead-char #f 1 #f #t) - (unsafe-unget-char #f 2 #f #t) - (unsafe-get-char #f 1 #f #t) - (unsafe-put-u8 #f 2 #f #t) - (put-bytevector #f 4 #f #t) - (unsafe-put-char #f 2 #f #t) - (put-string #f 4 #f #t) - (string-for-each1 #f 2 #f #t) - (string-for-each2 #f 3 #f #t) - (fx=? #f 2 #t #t) - (fx? #f 2 #t #t) - (fx<=? #f 2 #t #t) - (fx>=? #f 2 #t #t) - (fl=? #f 2 #t #t) - (fl? #f 2 #t #t) - (fl<=? #f 2 #t #t) - (fl>=? #f 2 #t #t) - (bitwise-and #f 2 #f #t) - (bitwise-ior #f 2 #f #t) - (bitwise-xor #f 2 #f #t) - (bitwise-not #f 1 #f #t) - (fxior #f 2 #t #t) - (fxxor #f 2 #t #t) - (fxand #f 2 #t #t) - (fxnot #f 1 #t #t) - (fxarithmetic-shift-left #f 2 #f #t) - (fxarithmetic-shift-right #f 2 #t #t) - (fxarithmetic-shift #f 2 #f #t) - (bitwise-bit-set? #f 2 #f #t) - (fxbit-set? #f 2 #f #t) - (fxcopy-bit #f 2 #t #t) - (reverse #f 1 #f #t) - (andmap1 #f 2 #f #t) - (ormap1 #f 2 #f #t) - (put-bytevector-some #f 4 #f #t) - (put-string-some #f 4 #f #t) - (dofretu8* #f 1 #f #f) - (dofretu16* #f 1 #f #f) - (dofretu32* #f 1 #f #f) - (eq-hashtable-ref #f 3 #f #t) - (eq-hashtable-contains? #f 2 #f #t) - (eq-hashtable-cell #f 3 #f #t) - (eq-hashtable-set! #f 3 #f #t) - (eq-hashtable-update! #f 4 #f #t) - (eq-hashtable-delete! #f 2 #f #t) - (symbol-hashtable-ref #f 3 #f #t) - (symbol-hashtable-contains? #f 2 #f #t) - (symbol-hashtable-cell #f 3 #f #t) - (symbol-hashtable-set! #f 3 #f #t) - (symbol-hashtable-update! #f 4 #f #t) - (symbol-hashtable-delete! #f 2 #f #t) - (safe-port-eof? #f 1 #f #t) - (safe-lookahead-u8 #f 1 #f #t) - (safe-unget-u8 #f 2 #f #t) - (safe-get-u8 #f 1 #f #t) - (safe-lookahead-char #f 1 #f #t) - (safe-unget-char #f 2 #f #t) - (safe-get-char #f 1 #f #t) - (safe-put-u8 #f 2 #f #t) - (safe-put-char #f 2 #f #t) - (safe-unread-char #f 2 #f #t) - (dorest0 #f 0 #f #t) - (dorest1 #f 0 #f #t) - (dorest2 #f 0 #f #t) - (dorest3 #f 0 #f #t) - (dorest4 #f 0 #f #t) - (dorest5 #f 0 #f #t) - (nuate #f 0 #f #t) - (virtual-register #f 1 #t #t) - (set-virtual-register! #f 1 #t #t) - )) - -(let () - (define-syntax declare-c-entries - (lambda (x) - (syntax-case x () - ((_ x ...) - (andmap identifier? #'(x ...)) - (with-syntax ((size (length (datum (x ...)))) - ((i ...) (enumerate (datum (x ...))))) - #'(let ([name-vec (make-vector size)]) - (define-constant c-entry-vector-size size) - (define-constant c-entry-name-vector name-vec) - (for-each (lambda (s n) - (vector-set! name-vec n s) - ($sputprop s '*c-entry* n)) - '(x ...) - '(i ...)))))))) - - (declare-c-entries - thread-context - get-thread-context - handle-apply-overflood - handle-docall-error - handle-overflow - handle-overflood - handle-nonprocedure-symbol - thread-list - split-and-resize - raw-collect-cond - raw-tc-mutex - activate-thread - deactivate-thread - unactivate-thread - handle-values-error - handle-mvlet-error - handle-arg-error - foreign-entry - install-library-entry - get-more-room - scan-remembered-set - instantiate-code-object - Sreturn - Scall-one-result - Scall-any-results - )) -) diff --git a/ta6ob/s/compile.ss b/ta6ob/s/compile.ss deleted file mode 100644 index 6120017..0000000 --- a/ta6ob/s/compile.ss +++ /dev/null @@ -1,2121 +0,0 @@ -;;; compile.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; use fixnum arithmetic in code building & output routines - -(let () -(import (nanopass)) -(include "types.ss") -(include "base-lang.ss") -(include "expand-lang.ss") - -; for tracing: -#;(define-syntax do-trace - (syntax-rules () - ((_ . r) (trace-output . r)))) -; no tracing: -(define-syntax do-trace - (syntax-rules () - ((_ . r) r))) - -(define trace-output - (lambda (fun . args) - (when ($assembly-output) - (fprintf ($assembly-output) "~s ====>~%" ($procedure-name fun))) - (let ([x (apply fun args)]) - (when ($assembly-output) - (parameterize ([print-graph #t]) - (pretty-print x ($assembly-output)) - (newline ($assembly-output)))) - x))) - -(define cheat? - (lambda (x) - (nanopass-case (Lsrc Expr) x - [,pr #t] - [(quote ,d) #t] - [(if ,e0 ,e1 ,e2) (and (cheat? e0) (cheat? e1) (cheat? e2))] - [(seq ,e1 ,e2) (and (cheat? e1) (cheat? e2))] - [(call ,preinfo ,e ,e* ...) - (and (andmap cheat? e*) (cheat? e))] - [else #f]))) - -(define cheat-eval - (rec compile - (lambda (x) - (nanopass-case (Lsrc Expr) x - [,pr ($top-level-value (primref-name pr))] - [(quote ,d) d] - [(if ,e0 ,e1 ,e2) - (compile (if (compile e0) e1 e2))] - [(seq ,e1 ,e2) (compile e1) (compile e2)] - [(call ,preinfo ,e ,e* ...) - (#2%apply (compile e) (map compile e*))] - [else ($oops #f "unexpected form ~s" x)])))) - -(define c-compile - (lambda (x) - (with-output-language (Lsrc Expr) - ($c-make-closure - ; pretending main is a library routine to avoid argument-count check - (let ([x `(case-lambda ,(make-preinfo-lambda #f #f (lookup-libspec main)) (clause () 0 ,x))]) - ($np-compile x #f)))))) - -(define c-set-code-quad! - (foreign-procedure "(cs)s_set_code_quad" - (scheme-object scheme-object scheme-object) - void)) - -(define lookup-c-entry-index - (foreign-procedure "(cs)lookup_c_entry" - (iptr) - scheme-object)) - -(define-who (c-mkcode x) - (define (mkcode x) - (record-case x - [(object) (x) x] - [(entry) (i) (lookup-c-entry-index i)] - [(library) (x) ($lookup-library-entry (libspec-index x) #t)] - [(library-code) (x) - ($closure-code ($lookup-library-entry (libspec-index x) #t))] - [(closure) func - ; call mkcode on code record first or we might set func-closure field multiple times - (let ([cp (mkcode ($c-func-code-record func))]) - ; i.e., the remainder must be atomic wrt mkcode - (or ($c-func-closure func) - (let ([p ($make-closure (constant code-data-disp) cp)]) - (set-$c-func-closure! func p) - p)))] - [(code) (func subtype free name arity-mask size code-list info pinfo*) - (or ($c-func-code-object func) - (let ([p ($make-code-object subtype free name arity-mask size info pinfo*)]) - (set-$c-func-code-object! func p) - (let mkc0 ([c* code-list] - [a (constant code-data-disp)] - [r* '()] - [ra 0] - [x* '()]) - (if (null? c*) - ($make-relocation-table! p (reverse r*) (reverse x*)) - (let ([c (car c*)]) - (record-case c - [(word) n - ($set-code-word! p a n) - (mkc0 (cdr c*) (fx+ a 2) r* ra x*)] - [(byte) n - ($set-code-byte! p a n) - (mkc0 (cdr c*) (fx+ a 1) r* ra x*)] - [(long) n - ($set-code-long! p a n) - (mkc0 (cdr c*) (fx+ a 4) r* ra x*)] - [(quad) n - ($set-code-quad! p a n) - (mkc0 (cdr c*) (fx+ a 8) r* ra x*)] - [(code-top-link) () - (constant-case ptr-bits - [(64) - ($set-code-quad! p a a) - (mkc0 (cdr c*) (fx+ a 8) r* ra x*)] - [(32) - ($set-code-long! p a a) - (mkc0 (cdr c*) (fx+ a 4) r* ra x*)])] - [(abs) (n x) - (let ([x* (cons (mkcode x) x*)]) - (let ([r ($reloc (constant reloc-abs) n (fx- a ra))]) - (constant-case ptr-bits - [(64) (mkc0 (cdr c*) (fx+ a 8) (cons r r*) a x*)] - [(32) (mkc0 (cdr c*) (fx+ a 4) (cons r r*) a x*)])))] - [else - (constant-case architecture - [(x86) - (record-case c - [(rel) (n x) - (let ([x* (cons (mkcode x) x*)]) - (let ([r ($reloc (constant reloc-rel) n (fx- a ra))]) - (mkc0 (cdr c*) (fx+ a 4) (cons r r*) a x*)))] - [else (c-assembler-output-error c)])] - [(arm32) - (record-case c - [(arm32-abs) (n x) - ; on ARMV7 would be 8: 4-byte movi, 4-byte movt - (let ([a1 (fx- a 12)]) ; 4-byte ldr, 4-byte bra, 4-byte value - (let ([x* (cons (mkcode x) x*)]) - (let ([r ($reloc (constant reloc-arm32-abs) n (fx- a1 ra))]) - (mkc0 (cdr c*) a (cons r r*) a1 x*))))] - [(arm32-call) (n x) - ; on ARMV7 would be 12: 4-byte movi, 4-byte movt, 4-byte blx - (let ([a1 (fx- a 16)]) ; 4-byte ldr, 4-byte bra, 4-byte value, 4-byte blx - (let ([x* (cons (mkcode x) x*)]) - (let ([r ($reloc (constant reloc-arm32-call) n (fx- a1 ra))]) - (mkc0 (cdr c*) a (cons r r*) a1 x*))))] - [(arm32-jump) (n x) - ; on ARMV7 would be 12: 4-byte movi, 4-byte movt, 4-byte bx - (let ([a1 (fx- a 16)]) ; 4-byte ldr, 4-byte bra, 4-byte value, 4-byte bx - (let ([x* (cons (mkcode x) x*)]) - (let ([r ($reloc (constant reloc-arm32-jump) n (fx- a1 ra))]) - (mkc0 (cdr c*) a (cons r r*) a1 x*))))] - [else (c-assembler-output-error c)])] - [(ppc32) - (record-case c - [(ppc32-abs) (n x) - (let ([a1 (fx- a 8)]) - (let ([x* (cons (mkcode x) x*)]) - (let ([r ($reloc (constant reloc-ppc32-abs) n (fx- a1 ra))]) - (mkc0 (cdr c*) a (cons r r*) a1 x*))))] - [(ppc32-call) (n x) - (let ([a1 (fx- a 16)]) - (let ([x* (cons (mkcode x) x*)]) - (let ([r ($reloc (constant reloc-ppc32-call) n (fx- a1 ra))]) - (mkc0 (cdr c*) a (cons r r*) a1 x*))))] - [(ppc32-jump) (n x) - (let ([a1 (fx- a 16)]) - (let ([x* (cons (mkcode x) x*)]) - (let ([r ($reloc (constant reloc-ppc32-jump) n (fx- a1 ra))]) - (mkc0 (cdr c*) a (cons r r*) a1 x*))))] - [else (c-assembler-output-error c)])] - [(x86_64) - (record-case c - [(x86_64-jump) (n x) - (let ([a1 (fx- a 12)] [x* (cons (mkcode x) x*)]) - (let ([r ($reloc (constant reloc-x86_64-jump) n (fx- a1 ra))]) - (mkc0 (cdr c*) a (cons r r*) a1 x*)))] - [(x86_64-call) (n x) - (let ([a1 (fx- a 12)] [x* (cons (mkcode x) x*)]) - (let ([r ($reloc (constant reloc-x86_64-call) n (fx- a1 ra))]) - (mkc0 (cdr c*) a (cons r r*) a1 x*)))] - [else (c-assembler-output-error c)])] - [else (c-assembler-output-error c)])])))) - p))] - [else (c-assembler-output-error x)])) - ; rationale for the critical section: - ; (1) the code objects we create here may be mutually recursive, and we - ; need for them all to be in the same generation. - ; (2) code objects are created without relocation tables, and linked - ; after relocation tables are added, potentially confusing the - ; collector. this could be addressed by maintaining a LINKED flag - ; in the code-object header. - ; (3) we record code modifications as code objects are allocated, then - ; flush once at the end to avoid multiple flushes. - ; rationale for the dynamic-wind: - ; we have to flush the instruction cache even if mkcode errors out or is - ; interrupted with a noncontinuable interrupt so that no code modifications - ; are recorded for code objects that have been dropped and for which the - ; memory containing them has been returned to the O/S. - (critical-section - (dynamic-wind - void - (lambda () (mkcode x)) - $flush-instruction-cache))) - -(define c-build-fasl - (lambda (x t a?) - (let build ([x x]) - (record-case x - [(object) (x) ($fasl-enter x t a?)] - [(closure) func - ($fasl-bld-graph x t a? - (lambda (x t a?) - (build ($c-func-code-record func))))] - [(code) stuff - ($fasl-bld-graph x t a? - (lambda (x t a?) - (record-case x - [(code) (func subtype free name arity-mask size code-list info pinfo*) - ($fasl-enter name t a?) - ($fasl-enter arity-mask t a?) - ($fasl-enter info t a?) - ($fasl-enter pinfo* t a?) - (for-each - (lambda (x) - (record-case x - [(abs) (n x) (build x)] - [else - (constant-case architecture - [(x86) - (record-case x - [(rel) (n x) (build x)] - [else (void)])] - [(x86_64) - (record-case x - [(x86_64-jump x86_64-call) (n x) (build x)] - [else (void)])] - [(arm32) - (record-case x - [(arm32-abs arm32-call arm32-jump) (n x) (build x)] - [else (void)])] - [(ppc32) - (record-case x - [(ppc32-abs ppc32-call ppc32-jump) (n x) (build x)] - [else (void)])])])) - code-list)])))])))) - -(include "fasl-helpers.ss") - -(define c-assembler-output-error - (lambda (x) - ($oops 'compile-internal - "invalid assembler output ~s" - x))) - -(define (c-faslobj x t p a?) - (let faslobj ([x x]) - (record-case x - [(object) (x) ($fasl-out x p t a?)] - [(entry) (i) - (put-u8 p (constant fasl-type-entry)) - (put-uptr p i)] - [(library) (x) - (put-u8 p (constant fasl-type-library)) - (put-uptr p (libspec-index x))] - [(library-code) (x) - (put-u8 p (constant fasl-type-library-code)) - (put-uptr p (libspec-index x))] - [(closure) func - ($fasl-wrf-graph x p t a? - (lambda (x p t a?) - (put-u8 p (constant fasl-type-closure)) - (put-uptr p (constant code-data-disp)) - (faslobj ($c-func-code-record func))))] - [(code) (func subtype free name arity-mask size code-list info pinfo*) - ($fasl-wrf-graph x p t a? - (lambda (x p t a?) - (put-u8 p (constant fasl-type-code)) - (put-u8 p subtype) - (put-uptr p free) - (put-uptr p size) - ($fasl-out name p t a?) - ($fasl-out arity-mask p t a?) - ($fasl-out info p t a?) - ($fasl-out pinfo* p t a?) - (let prf0 ([c* code-list] - [a (constant code-data-disp)] - [r* '()] - [ra 0] - [x* '()]) - (if (null? c*) - (begin - (let ([actual-size (- a (constant code-data-disp))]) - (unless (= actual-size size) - ($oops 'c-faslcode - "wrote ~s bytes, expected ~s bytes" - actual-size size))) - (put-uptr p (fold-left (lambda (m r) (fx+ m (if (reloc-long? r) 3 1))) 0 r*)) - (for-each - (lambda (r x) - (let ([item-offset (reloc-item-offset r)]) - (put-u8 p - (let* ([k (fxsll (reloc-type r) 2)] - [k (if (eqv? item-offset 0) k (fxlogor k 2))]) - (if (reloc-long? r) (fxlogor k 1) k))) - (put-uptr p (reloc-code-offset r)) - (unless (eqv? item-offset 0) (put-uptr p item-offset)) - (faslobj x))) - (reverse r*) - (reverse x*))) - (let ([c (car c*)]) - (record-case c - [(word) n - (put16 p n) - (prf0 (cdr c*) (fx+ a 2) r* ra x*)] - [(byte) n - (put8 p n) - (prf0 (cdr c*) (fx+ a 1) r* ra x*)] - [(long) n - (put32 p n) - (prf0 (cdr c*) (fx+ a 4) r* ra x*)] - [(quad) n - (put64 p n) - (prf0 (cdr c*) (fx+ a 8) r* ra x*)] - [(code-top-link) () - (constant-case ptr-bits - [(64) - (put64 p a) - (prf0 (cdr c*) (fx+ a 8) r* ra x*)] - [(32) - (put32 p a) - (prf0 (cdr c*) (fx+ a 4) r* ra x*)])] - [(abs) (n x) - (let ([r ($reloc (constant reloc-abs) n (fx- a ra))]) - (constant-case ptr-bits - [(64) - (put64 p 0) - (prf0 (cdr c*) (fx+ a 8) (cons r r*) a (cons x x*))] - [(32) - (put32 p 0) - (prf0 (cdr c*) (fx+ a 4) (cons r r*) a (cons x x*))]))] - [else - (constant-case architecture - [(x86) - (record-case c - [(rel) (n x) - (put32 p 0) - (let ([r ($reloc (constant reloc-rel) n (fx- a ra))]) - (prf0 (cdr c*) (fx+ a 4) (cons r r*) a (cons x x*)))] - [else (c-assembler-output-error c)])] - [(arm32) - (record-case c - [(arm32-abs) (n x) - ; on ARMV7 would be 8: 4-byte movi, 4-byte movt - (let ([a1 (fx- a 12)]) ; 4-byte ldr, 4-byte bra, 4-byte value - (let ([r ($reloc (constant reloc-arm32-abs) n (fx- a1 ra))]) - (prf0 (cdr c*) a (cons r r*) a1 (cons x x*))))] - [(arm32-call) (n x) - ; on ARMV7 would be 12: 4-byte movi, 4-byte movt, 4-byte blx - (let ([a1 (fx- a 16)]) ; 4-byte ldr, 4-byte bra, 4-byte value, 4-byte blx - (let ([r ($reloc (constant reloc-arm32-call) n (fx- a1 ra))]) - (prf0 (cdr c*) a (cons r r*) a1 (cons x x*))))] - [(arm32-jump) (n x) - ; on ARMV7 would be 12: 4-byte movi, 4-byte movt, 4-byte bx - (let ([a1 (fx- a 16)]) ; 4-byte ldr, 4-byte bra, 4-byte value, 4-byte bx - (let ([r ($reloc (constant reloc-arm32-jump) n (fx- a1 ra))]) - (prf0 (cdr c*) a (cons r r*) a1 (cons x x*))))] - [else (c-assembler-output-error c)])] - [(ppc32) - (record-case c - [(ppc32-abs) (n x) - (let ([a1 (fx- a 8)]) - (let ([r ($reloc (constant reloc-ppc32-abs) n (fx- a1 ra))]) - (prf0 (cdr c*) a (cons r r*) a1 (cons x x*))))] - [(ppc32-call) (n x) - (let ([a1 (fx- a 16)]) - (let ([r ($reloc (constant reloc-ppc32-call) n (fx- a1 ra))]) - (prf0 (cdr c*) a (cons r r*) a1 (cons x x*))))] - [(ppc32-jump) (n x) - (let ([a1 (fx- a 16)]) - (let ([r ($reloc (constant reloc-ppc32-jump) n (fx- a1 ra))]) - (prf0 (cdr c*) a (cons r r*) a1 (cons x x*))))] - [else (c-assembler-output-error c)])] - [(x86_64) - (record-case c - [(x86_64-jump) (n x) - (let ([a1 (fx- a 12)]) ; 10-byte moviq followed by 2-byte jmp - (let ([r ($reloc (constant reloc-x86_64-jump) n (fx- a1 ra))]) - (prf0 (cdr c*) a (cons r r*) a1 (cons x x*))))] - [(x86_64-call) (n x) - (let ([a1 (fx- a 12)]) ; 10-byte moviq followed by 2-byte call - (let ([r ($reloc (constant reloc-x86_64-call) n (fx- a1 ra))]) - (prf0 (cdr c*) a (cons r r*) a1 (cons x x*))))] - [else (c-assembler-output-error c)])] - [else (c-assembler-output-error c)])]))))))] - [else (c-assembler-output-error x)]))) - -(define (c-print-fasl x p situation) - (let ([t ($fasl-table)] - [a? (let ([flags (fxlogor - (if (generate-inspector-information) (constant annotation-debug) 0) - (if (eq? ($compile-profile) 'source) (constant annotation-profile) 0))]) - (and (not (fx= flags 0)) flags))]) - (c-build-fasl x t a?) - ($fasl-start p t situation - (lambda (p) (c-faslobj x t p a?))))) - -(define-record-type visit-chunk - (nongenerative) - (fields chunk)) - -(define-record-type revisit-chunk - (nongenerative) - (fields chunk)) - -(define-who (host-machine-type) - (let ([m (machine-type)]) - (let lookup ([ra* (constant machine-type-alist)]) - (if (null? ra*) - ($oops who "unrecognized machine type ~s" m) - (if (eq? (cdar ra*) m) (caar ra*) (lookup (cdr ra*))))))) - -(define with-whacked-optimization-locs - (lambda (x1 th) - (define ht (make-eq-hashtable)) - (define-pass whack! : Lexpand (ir f) -> * () - (Outer : Outer (ir) -> * () - [,inner (Inner ir)] - [(group ,[] ,[]) (values)] - [(visit-only ,[]) (values)] - [(revisit-only ,[]) (values)] - [else (values)]) - (Inner : Inner (ir) -> * () - [(library/rt ,uid (,dl* ...) (,db* ...) (,dv* ...) (,de* ...) ,body) - (for-each f db*) - (values)] - [else (values)])) - (whack! x1 - (lambda (db) - (when db - (eq-hashtable-set! ht db (unbox db)) - (set-box! db '())))) - (th) - (whack! x1 - (lambda (db) - (when db - (set-box! db (eq-hashtable-ref ht db '()))))))) - -(define check-prelex-flags - (lambda (x after) - (when ($enable-check-prelex-flags) - ($pass-time 'cpcheck-prelex-flags (lambda () (do-trace $cpcheck-prelex-flags x after)))))) - -(define compile-file-help - (lambda (op hostop wpoop source-table machine sfd do-read outfn) - (parameterize ([$target-machine machine] - [$sfd sfd] - [$current-mso ($current-mso)] - [$block-counter 0] - [optimize-level (optimize-level)] - [debug-level (debug-level)] - [run-cp0 (run-cp0)] - [cp0-effort-limit (cp0-effort-limit)] - [cp0-score-limit (cp0-score-limit)] - [cp0-outer-unroll-limit (cp0-outer-unroll-limit)] - [generate-inspector-information (generate-inspector-information)] - [generate-procedure-source-information (generate-procedure-source-information)] - [$compile-profile ($compile-profile)] - [generate-interrupt-trap (generate-interrupt-trap)] - [$optimize-closures ($optimize-closures)] - [enable-cross-library-optimization (enable-cross-library-optimization)] - [generate-covin-files (generate-covin-files)]) - (emit-header op (constant scheme-version) (constant machine-type)) - (when hostop (emit-header hostop (constant scheme-version) (host-machine-type))) - (when wpoop (emit-header wpoop (constant scheme-version) (host-machine-type))) - (let cfh0 ([n 1] [rrcinfo** '()] [rlpinfo** '()] [rfinal** '()]) - (let ([x0 ($pass-time 'read do-read)]) - (if (eof-object? x0) - (compile-file-help2 op (reverse rrcinfo**) (reverse rlpinfo**) (reverse rfinal**)) - (let () - (define source-info-string - (and (or ($assembly-output) (expand-output) (expand/optimize-output)) - (with-output-to-string - (lambda () - (printf "expression #~s" n) - (when (and (annotation? x0) (fxlogtest (annotation-flags x0) (constant annotation-debug))) - (let ((s (annotation-source x0))) - (call-with-values - (lambda () ((current-locate-source-object-source) s #t #t)) - (case-lambda - [() (void)] - [(path line char) (printf " on line ~s" line)])))))))) - (when ($assembly-output) - (when source-info-string - (fprintf ($assembly-output) "~%;; ~a\n" source-info-string)) - (parameterize ([print-graph #t]) - (pretty-print (if (annotation? x0) (annotation-stripped x0) x0) - ($assembly-output))) - (flush-output-port ($assembly-output))) - (let ([x1 ($pass-time 'expand - (lambda () - (expand x0 (if (eq? (subset-mode) 'system) ($system-environment) (interaction-environment)) #t #t outfn)))]) - (check-prelex-flags x1 'expand) - ($uncprep x1 #t) ; populate preinfo sexpr fields - (check-prelex-flags x1 'uncprep) - (when source-table ($insert-profile-src! source-table x1)) - (when wpoop - ; cross-library optimization locs might be set by cp0 during the expander's compile-time - ; evaluation of library forms. since we have no need for the optimization information in - ; the wpo file, we temporarily whack the optimization locs while writing the wpo file. - (with-whacked-optimization-locs x1 - (lambda () - ($with-fasl-target (host-machine-type) - (lambda () - (parameterize ([$target-machine (machine-type)]) - (let ([t ($fasl-table)]) - ($fasl-enter x1 t (constant annotation-all)) - ($fasl-start wpoop t (constant fasl-type-visit-revisit) (lambda (p) ($fasl-out x1 p t (constant annotation-all))))))))))) - (let-values ([(rcinfo* lpinfo* final*) (compile-file-help1 x1 source-info-string)]) - (when hostop - ; the host library file contains expander output possibly augmented with - ; cross-library optimization information inserted by cp0. this write must come - ; after cp0, at least, so that cp0 has a chance to insert that information. - ($with-fasl-target (host-machine-type) - (lambda () - (parameterize ([$target-machine (machine-type)]) - (let ([t ($fasl-table)]) - ($fasl-enter x1 t (constant annotation-all)) - ($fasl-start hostop t (constant fasl-type-visit-revisit) (lambda (p) ($fasl-out x1 p t (constant annotation-all))))))))) - (cfh0 (+ n 1) (cons rcinfo* rrcinfo**) (cons lpinfo* rlpinfo**) (cons final* rfinal**))))))))))) - -(define library/program-info? - (lambda (x) - (or (program-info? x) (library-info? x)))) - -(define-who compile-file-help1 - (lambda (x1 source-info-string) - (define-who expand-Lexpand - (lambda (e) - ; we might want to export expand-Inner from syntax.ss instead of $build-install-library/ct-code - ; and $build-install-library/rt-code - (define-pass expand-Inner : Lexpand (ir) -> Lexpand () - (Inner : Inner (ir) -> Inner () - [,lsrc lsrc] ; NB: workaround for nanopass tag snafu - [(program ,uid ,body) ($build-invoke-program uid body)] - [(library/ct ,uid (,export-id* ...) ,import-code ,visit-code) - ($build-install-library/ct-code uid export-id* import-code visit-code)] - [(library/rt ,uid (,dl* ...) (,db* ...) (,dv* ...) (,de* ...) ,body) - ($build-install-library/rt-code uid dl* db* dv* de* body)] - [else ir])) - (with-output-language (Lsrc Expr) - (define (lambda-chunk lsrc) - ; pretending main is a library routine to avoid argument-count check - `(case-lambda ,(make-preinfo-lambda #f #f (lookup-libspec main)) - (clause () 0 ,lsrc))) - (define (visit lsrc e* rchunk*) - (define (rchunks) (cons (make-visit-chunk (lambda-chunk lsrc)) rchunk*)) - (if (null? e*) - (rchunks) - (let f ([e (car e*)] [e* (cdr e*)]) - (nanopass-case (Lexpand Outer) e - [(group ,outer1 ,outer2) (f outer1 (cons outer2 e*))] - [(visit-only ,lsrc2) (visit `(seq ,lsrc ,lsrc2) e* rchunk*)] - [else (common e e* (rchunks))])))) - (define (revisit lsrc e* rchunk*) - (define (rchunks) (cons (make-revisit-chunk (lambda-chunk lsrc)) rchunk*)) - (if (null? e*) - (rchunks) - (let f ([e (car e*)] [e* (cdr e*)]) - (nanopass-case (Lexpand Outer) e - [(group ,outer1 ,outer2) (f outer1 (cons outer2 e*))] - [(revisit-only ,lsrc2) (revisit `(seq ,lsrc ,lsrc2) e* rchunk*)] - [else (common e e* (rchunks))])))) - (define (visit-revisit lsrc e* rchunk*) - (define (rchunks) (cons (lambda-chunk lsrc) rchunk*)) - (if (null? e*) - (rchunks) - (let f ([e (car e*)] [e* (cdr e*)]) - (nanopass-case (Lexpand Outer) e - [(group ,outer1 ,outer2) (f outer1 (cons outer2 e*))] - [,lsrc2 (visit-revisit `(seq ,lsrc ,lsrc2) e* rchunk*)] - [else (common e e* (rchunks))])))) - (define (unwrap-inner e) - (nanopass-case (Lexpand Inner) e - [(library/ct-info ,linfo/ct) linfo/ct] - [(library/rt-info ,linfo/rt) linfo/rt] - [(program-info ,pinfo) pinfo] - [else e])) - (define (common e e* rchunk*) - (nanopass-case (Lexpand Outer) e - [(visit-only ,lsrc) (visit lsrc e* rchunk*)] - [(revisit-only ,lsrc) (revisit lsrc e* rchunk*)] - [,lsrc (visit-revisit lsrc e* rchunk*)] - [else (let ([rchunk* (cons (nanopass-case (Lexpand Outer) e - [(visit-only ,inner) (make-visit-chunk (unwrap-inner inner))] - [(revisit-only ,inner) (make-revisit-chunk (unwrap-inner inner))] - [(recompile-info ,rcinfo) rcinfo] - [,inner (unwrap-inner inner)] - [else (sorry! who "unexpected Outer ~s" e)]) - rchunk*)]) - (if (null? e*) rchunk* (start (car e*) (cdr e*) rchunk*)))])) - (define (start e e* rchunk*) - (nanopass-case (Lexpand Outer) e - [(group ,outer1 ,outer2) (start outer1 (cons outer2 e*) rchunk*)] - [else (common e e* rchunk*)])) - (reverse (start (expand-Inner e) '() '()))))) - (when (expand-output) - (when source-info-string - (fprintf (expand-output) "~%;; expand output for ~a\n" source-info-string)) - (pretty-print ($uncprep x1) (expand-output)) - (flush-output-port (expand-output))) - (let loop ([chunk* (expand-Lexpand x1)] [rx2b* '()] [rfinal* '()] [rlpinfo* '()] [rrcinfo* '()]) - (if (null? chunk*) - (begin - (when (expand/optimize-output) - (when source-info-string - (fprintf (expand/optimize-output) "~%;; expand/optimize output for ~a\n" source-info-string)) - (let ([e* (map (lambda (x2b) - (define (finish x2b) - ($uncprep - (cond - [(recompile-info? x2b) (with-output-language (Lexpand Outer) `(recompile-info ,x2b))] - [(library/ct-info? x2b) (with-output-language (Lexpand Inner) `(library/ct-info ,x2b))] - [(library/rt-info? x2b) (with-output-language (Lexpand Inner) `(library/rt-info ,x2b))] - [(program-info? x2b) (with-output-language (Lexpand Inner) `(program-info ,x2b))] - [else - (nanopass-case (Lsrc Expr) x2b - [(case-lambda ,preinfo (clause () ,interface ,body)) body] - [else (sorry! 'compile-file-help "unexpected optimizer output ~s" x2b)])]))) - (if (pair? x2b) - (case (car x2b) - [(visit-stuff) `(eval-when (visit) ,(finish (cdr x2b)))] - [(revisit-stuff) `(eval-when (revisit) ,(finish (cdr x2b)))] - [else (sorry! who "unrecognized stuff ~s" x2b)]) - (finish x2b))) - rx2b*)]) - (pretty-print (if (fx= (length e*) 1) (car e*) `(begin ,@(reverse e*))) (expand/optimize-output)) - (flush-output-port (expand/optimize-output)))) - (values (reverse rrcinfo*) (reverse rlpinfo*) (reverse rfinal*))) - (let ([x1 (car chunk*)] [chunk* (cdr chunk*)]) - (define finish-compile - (lambda (x1 f) - (if (library/program-info? x1) - (loop chunk* (cons (f x1) rx2b*) rfinal* (cons (f `(object ,x1)) rlpinfo*) rrcinfo*) - (let* ([waste (check-prelex-flags x1 'before-cpvalid)] - [x2 ($pass-time 'cpvalid (lambda () (do-trace $cpvalid x1)))] - [waste (check-prelex-flags x2 'cpvalid)] - [x2a (let ([cpletrec-ran? #f]) - (let ([x ((run-cp0) - (lambda (x) - (set! cpletrec-ran? #t) - (let* ([x ($pass-time 'cp0 (lambda () (do-trace $cp0 x)))] - [waste (check-prelex-flags x 'cp0)] - [x ($pass-time 'cpletrec (lambda () (do-trace $cpletrec x)))] - [waste (check-prelex-flags x 'cpletrec)]) - x)) - x2)]) - (if cpletrec-ran? - x - (let ([x ($pass-time 'cpletrec (lambda () (do-trace $cpletrec x)))]) - (check-prelex-flags x 'cpletrec) - x))))] - [x2b ($pass-time 'cpcheck (lambda () (do-trace $cpcheck x2a)))] - [waste (check-prelex-flags x2b 'cpcheck)] - [x2b ($pass-time 'cpcommonize (lambda () (do-trace $cpcommonize x2b)))] - [waste (check-prelex-flags x2b 'cpcommonize)] - [x7 (do-trace $np-compile x2b #t)] - [x8 ($c-make-closure x7)]) - (loop chunk* (cons (f x2b) rx2b*) (cons (f x8) rfinal*) rlpinfo* rrcinfo*))))) - (cond - [(recompile-info? x1) (loop chunk* (cons x1 rx2b*) rfinal* rlpinfo* (cons x1 rrcinfo*))] - [(visit-chunk? x1) (finish-compile (visit-chunk-chunk x1) (lambda (x) `(visit-stuff . ,x)))] - [(revisit-chunk? x1) (finish-compile (revisit-chunk-chunk x1) (lambda (x) `(revisit-stuff . ,x)))] - [else (finish-compile x1 values)])))))) - -(define compile-file-help2 - (lambda (op rcinfo** lpinfo** final**) - (define (libreq-hash x) (symbol-hash (libreq-uid x))) - (define (libreq=? x y) (eq? (libreq-uid x) (libreq-uid y))) - (let ([import-ht (make-hashtable libreq-hash libreq=?)] - [include-ht (make-hashtable string-hash string=?)]) - (for-each - (lambda (rcinfo*) - (for-each - (lambda (rcinfo) - (for-each - (lambda (x) (hashtable-set! import-ht x #t)) - (recompile-info-import-req* rcinfo)) - (for-each - (lambda (x) (hashtable-set! include-ht x #t)) - (recompile-info-include-req* rcinfo))) - rcinfo*)) - rcinfo**) - (let ([import-req* (vector->list (hashtable-keys import-ht))] - [include-req* (vector->list (hashtable-keys include-ht))]) - ; the first entry is always a recompile-info record with recompile information for the entire object file - ($pass-time 'pfasl - (lambda () - (c-print-fasl `(object ,(make-recompile-info import-req* include-req*)) op (constant fasl-type-visit-revisit)) - (for-each - (lambda (final*) - (for-each - (lambda (x) - (record-case x - [(visit-stuff) x (c-print-fasl x op (constant fasl-type-visit))] - [(revisit-stuff) x (c-print-fasl x op (constant fasl-type-revisit))] - [else (c-print-fasl x op (constant fasl-type-visit-revisit))])) - final*)) - ; inserting #t after lpinfo as an end-of-header marker - (append lpinfo** (cons (list `(object #t)) final**))))))))) - -(define (new-extension new-ext fn) - (let ([old-ext (path-extension fn)]) - (format "~a.~a" - (if (or (string=? old-ext "") (string=? old-ext new-ext)) fn (path-root fn)) - new-ext))) - -(module (with-object-file with-host-file with-wpo-file with-coverage-file) - (define call-with-port/cleanup - (lambda (ofn op p) - (on-reset (delete-file ofn #f) - (on-reset (close-port op) - (p op)) - (close-port op)))) - - (define with-object-file - (lambda (who ofn p) - (call-with-port/cleanup ofn - ($open-file-output-port who ofn - (file-options replace)) - p))) - - (define with-host-file - (lambda (who ofn p) - (if ofn - (call-with-port/cleanup ofn - ($open-file-output-port who ofn - (file-options replace)) - p) - (p #f)))) - - (define with-wpo-file - (lambda (who ofn p) - (if (generate-wpo-files) - (let ([ofn (new-extension "wpo" ofn)]) - (call-with-port/cleanup ofn - ($open-file-output-port who ofn - (file-options replace)) - p)) - (p #f)))) - - (define with-coverage-file - (lambda (who ofn p) - (if (generate-covin-files) - (let ([ofn (new-extension "covin" ofn)]) - (call-with-port/cleanup ofn - ($open-file-output-port who ofn - (file-options compressed replace) - (buffer-mode block) - (current-transcoder)) - (lambda (op) - (let ([source-table (make-source-table)]) - (p source-table) - (put-source-table op source-table))))) - (p #f))))) - -(set! $compile-host-library - (lambda (who iofn) - (let ([ip ($open-file-input-port who iofn)]) - (on-reset (close-port ip) - (let loop ([rx1* '()] [rcinfo* '()] [rother* '()]) - (let ([x1 (fasl-read ip)]) - (cond - [(eof-object? x1) - (close-port ip) - (unless (null? rx1*) - (unless (null? rother*) ($oops 'compile-library "unexpected value ~s read from file ~s that also contains ~s" (car rother*) iofn (car rx1*))) - (with-object-file who iofn - (lambda (op) - (emit-header op (constant scheme-version) (constant machine-type)) - (let loop ([x1* (reverse rx1*)] [rrcinfo** (list rcinfo*)] [rlpinfo** '()] [rfinal** '()]) - (if (null? x1*) - (compile-file-help2 op (reverse rrcinfo**) (reverse rlpinfo**) (reverse rfinal**)) - (let-values ([(rcinfo* lpinfo* final*) - (let ([x1 (car x1*)]) - (if (recompile-info? x1) - (values (list x1) '() '()) - (compile-file-help1 (car x1*) "host library")))]) - (loop (cdr x1*) (cons rcinfo* rrcinfo**) (cons lpinfo* rlpinfo**) (cons final* rfinal**))))))))] - [(recompile-info? x1) (loop rx1* (cons x1 rcinfo*) rother*)] - [(Lexpand? x1) (loop (cons x1 rx1*) rcinfo* rother*)] - [else (loop rx1* rcinfo* (cons x1 rother*))]))))))) - -(let () - (define-record-type node (nongenerative) - (fields (mutable depend*) (mutable use-count)) - (protocol - (lambda (new) - (lambda () - (new #f 0))))) - (define-record-type program-node (nongenerative) (sealed #t) (parent node) - (fields pinfo (mutable ir)) - (protocol - (lambda (pargs->new) - (lambda (pinfo) - ((pargs->new) pinfo #f))))) - (define program-node-uid - (lambda (node) - (program-info-uid (program-node-pinfo node)))) - (define program-node-invoke-req* - (lambda (node) - (program-info-invoke-req* (program-node-pinfo node)))) - - (define-record-type library-node (nongenerative) (parent node) - (fields binary? (mutable ctinfo) (mutable rtinfo) (mutable ctir) (mutable rtir) (mutable visible?) fn) - (protocol - (lambda (pargs->new) - (lambda (binary? ctinfo rtinfo visible? fn) - (safe-assert (or ctinfo rtinfo)) - ((pargs->new) binary? ctinfo rtinfo #f #f visible? fn))))) - (define library-node-path - (lambda (node) - (library-info-path (or (library-node-ctinfo node) (library-node-rtinfo node))))) - (define library-node-uid - (lambda (node) - (library-info-uid (or (library-node-ctinfo node) (library-node-rtinfo node))))) - (define library-node-version - (lambda (node) - (library-info-version (or (library-node-ctinfo node) (library-node-rtinfo node))))) - (define library-node-invoke-req* - (lambda (node) - (library/rt-info-invoke-req* (library-node-rtinfo node)))) - (define library-node-import-req* - (lambda (node) - (library/ct-info-import-req* (library-node-ctinfo node)))) - - (define read-input-file - (lambda (who ifn) - (call-with-port ($open-file-input-port who ifn) - (lambda (ip) - (on-reset (close-port ip) - (let ([hash-bang-line - (let ([start-pos (port-position ip)]) - (if (and (eqv? (get-u8 ip) (char->integer #\#)) - (eqv? (get-u8 ip) (char->integer #\!)) - (let ([b (lookahead-u8 ip)]) - (or (eqv? b (char->integer #\space)) - (eqv? b (char->integer #\/))))) - (let-values ([(op get-bv) (open-bytevector-output-port)]) - (put-u8 op (char->integer #\#)) - (put-u8 op (char->integer #\!)) - (let loop () - (let ([b (get-u8 ip)]) - (unless (eof-object? b) - (put-u8 op b) - (unless (eqv? b (char->integer #\newline)) - (loop))))) - (get-bv)) - (begin (set-port-position! ip start-pos) #f)))]) - (if ($compiled-file-header? ip) - (let loop ([rls '()]) - (let ([x (fasl-read ip)]) - (cond - [(eof-object? x) (values hash-bang-line (reverse rls))] - [(Lexpand? x) (loop (cons x rls))] - [else ($oops who "unexpected wpo file object ~s" x)]))) - ($oops who "input file is source ~s" ifn)))))))) - - (define find-library - (lambda (who path what library-ext*) - (with-values - ($library-search who path (library-directories) library-ext*) - (lambda (src-path lib-path lib-exists?) - (and lib-exists? - (begin - (when (and src-path (time library-node-path] - [else uid]))) - (define read-library - (lambda (path libs-visible?) - (cond - [(find-library who path "wpo" (map (lambda (ext) (cons (car ext) (string-append (path-root (cdr ext)) ".wpo"))) (library-extensions))) => - (lambda (fn) - (let*-values ([(hash-bang-line ir*) (read-input-file who fn)] - [(no-program node* ignore-rcinfo*) (process-ir*! ir* fn #f libs-visible?)]) - (values fn node*)))] - [(find-library who path "so" (library-extensions)) => - (lambda (fn) (values fn (read-binary-file path fn libs-visible?)))] - [else ($oops who "unable to locate expanded library file for library ~s" path)]))) - (define read-binary-file - (lambda (path fn libs-visible?) - (call-with-port ($open-file-input-port who fn) - (lambda (ip) - (on-reset (close-port ip) - (if ($compiled-file-header? ip) - (let ([libs-in-file '()]) - (let loop! () - (let ([x (fasl-read ip)]) - (if (eof-object? x) - (begin - (for-each - (lambda (node) - (unless (library-node-ctinfo node) - ($oops who "missing compile-time information for ~s" (library-node-path node))) - (unless (library-node-rtinfo node) - ($oops who "missing run-time information for ~s" (library-node-path node)))) - libs-in-file) - libs-in-file) - (begin - (cond - [(recompile-info? x)] - [(procedure? x)] - [(library/ct-info? x) - (let ([node (record-ct-lib! x #t fn libs-visible?)]) - (when node (set! libs-in-file (cons node libs-in-file))))] - [(library/rt-info? x) - (let ([node (record-rt-lib! x #t fn libs-visible?)]) - (when node (set! libs-in-file (cons node libs-in-file))))] - [(program-info? x) ($oops who "found program while looking for library ~s in ~a" path fn)] - ; NB: this is here to support the #t inserted by compile-file-help2 after header information - [(eq? x #t)] - [else ($oops who "unexpected value ~s read from ~a" x fn)]) - (loop!)))))) - ($oops who "malformed binary input file ~s" fn))))))) - (define process-ir*! - (lambda (ir* ifn capture-program? libs-visible?) - (define outer-who who) - (let ([libs-in-file '()] [maybe-program #f] [rcinfo* '()]) - (define-pass process-ir! : Lexpand (ir) -> * () - (Outer : Outer (ir situation) -> * () - [(recompile-info ,rcinfo) (set! rcinfo* (cons rcinfo rcinfo*)) (values)] - [(group ,[] ,[]) (values)] - [(visit-only ,[inner 'visit ->]) (values)] - [(revisit-only ,[inner 'revisit ->]) (values)]) - (Inner : Inner (ir situation) -> * () - [,lsrc ($oops outer-who "expected program or library form, but encountered top-level expression ~s processing file ~a" ($uncprep lsrc) ifn)] - [(library/ct-info ,linfo/ct) - (let ([node (record-ct-lib! linfo/ct #f ifn libs-visible?)]) - (when node (set! libs-in-file (cons node libs-in-file)))) - (values)] - [(library/rt-info ,linfo/rt) - (let ([node (record-rt-lib! linfo/rt #f ifn libs-visible?)]) - (when node (set! libs-in-file (cons node libs-in-file)))) - (values)] - [(program-info ,pinfo) - (unless capture-program? ($oops outer-who "found program while reading library wpo file ~a" ifn)) - (when (eq? situation 'visit) ($oops outer-who "encountered visit-only program while processing file ~s" ifn)) - (when maybe-program ($oops outer-who "found multiple programs in entry file ~a" ifn)) - (set! maybe-program (make-program-node pinfo)) - (values)]) - (Program : Program (ir situation) -> * () - [(program ,uid ,body) - (unless capture-program? ($oops outer-who "found program while reading library wpo file ~a" ifn)) - (when (eq? situation 'visit) ($oops outer-who "encountered visit-only program while processing file ~s" ifn)) - (unless maybe-program ($oops outer-who "unable to locate program descriptor for ~s" uid)) - (unless (eq? uid (program-node-uid maybe-program)) - ($oops outer-who "expected code for program uid ~s, but found code for program uid ~s" (program-node-uid maybe-program) uid)) - (program-node-ir-set! maybe-program ir) - (values)]) - (ctLibrary : ctLibrary (ir situation) -> * () - [(library/ct ,uid (,export-id* ...) ,import-code ,visit-code) - (when (eq? situation 'revisit) ($oops outer-who "encountered revisit-only compile-time library ~s while processing file ~s" (lookup-path uid) ifn)) - (record-ct-lib-ir! uid ir) - (values)]) - (rtLibrary : rtLibrary (ir situation) -> * () - [(library/rt ,uid (,dl* ...) (,db* ...) (,dv* ...) (,de* ...) ,body) - (when (eq? situation 'visit) ($oops outer-who "encountered visit-only run-time library ~s while processing file ~s" (lookup-path uid) ifn)) - (record-rt-lib-ir! uid ir) - (values)]) - (when capture-wpo? (set! wpo* (cons ir wpo*))) - (Outer ir 'load)) - (for-each process-ir! ir*) - (for-each - (lambda (node) - (unless (library-node-ctinfo node) - ($oops who "missing compile-time information for ~s" (library-node-path node))) - (unless (library-node-rtinfo node) - ($oops who "missing run-time information for ~s" (library-node-path node))) - (unless (library-node-ctir node) - ($oops who "missing compile-time code for ~s" (library-node-path node))) - (unless (library-node-rtir node) - ($oops who "missing run-time code for ~s" (library-node-path node)))) - libs-in-file) - (values maybe-program libs-in-file rcinfo*)))) - (define record-ct-lib! - (lambda (linfo/ct binary? ifn libs-visible?) - (let* ([uid (library-info-uid linfo/ct)] - [cell (symbol-hashtable-cell libs uid #f)] - [node (cdr cell)]) - (if node - (if (library-node-ctinfo node) - ($oops who "encountered library ~s in ~a, but had already encountered it in ~a" - (library-info-path linfo/ct) ifn (library-node-fn node)) - (begin (library-node-ctinfo-set! node linfo/ct) #f)) - (let ([node (make-library-node binary? linfo/ct #f (or libs-visible? binary?) ifn)]) - (set-cdr! cell node) - node))))) - (define record-rt-lib! - (lambda (linfo/rt binary? ifn libs-visible?) - (let* ([uid (library-info-uid linfo/rt)] - [cell (symbol-hashtable-cell libs uid #f)] - [node (cdr cell)]) - (if node - (if (library-node-rtinfo node) - ($oops who "encountered library ~s in ~a, but had already encountered it in ~a" - (library-info-path linfo/rt) ifn (library-node-fn node)) - (begin (library-node-rtinfo-set! node linfo/rt) #f)) - (let ([node (make-library-node binary? #f linfo/rt (or libs-visible? binary?) ifn)]) - (set-cdr! cell node) - node))))) - (define record-ct-lib-ir! - (lambda (uid ir) - (let ([node (symbol-hashtable-ref libs uid #f)]) - (unless node ($oops "missing descriptor for compile-time library code ~s" uid)) - (library-node-ctir-set! node ir)))) - (define record-rt-lib-ir! - (lambda (uid ir) - (let ([node (symbol-hashtable-ref libs uid #f)]) - (unless node ($oops "missing descriptor for run-time library code ~s" uid)) - (library-node-rtir-set! node ir)))) - (define chase-library - (lambda (req libs-visible?) - (let ([a (symbol-hashtable-cell libs (libreq-uid req) #f)]) - (cond - [(cdr a) => - (lambda (node) - (when libs-visible? - (unless (library-node-visible? node) - (library-node-visible?-set! node #t) - (chase-library-dependencies! node))))] - [else - (let ([path (libreq-path req)]) - (let-values ([(fn node*) (read-library path libs-visible?)]) - (unless (symbol-hashtable-ref libs (libreq-uid req) #f) - ($oops who "~s does not define expected compilation instance of library ~s" fn path)) - (for-each chase-library-dependencies! node*)))])))) - (define find-dependencies - (lambda (req* maybe-import-req*) - (let ([dep* (map (lambda (req) - (let ([node (symbol-hashtable-ref libs (libreq-uid req) #f)]) - (node-use-count-set! node (fx+ (node-use-count node) 1)) - node)) - req*)]) - (if maybe-import-req* - (fold-right (lambda (req dep*) - (let ([node (symbol-hashtable-ref libs (libreq-uid req) #f)]) - (if node - (begin - (node-use-count-set! node (fx+ (node-use-count node) 1)) - (cons node dep*)) - dep*))) - dep* maybe-import-req*) - dep*)))) - (define chase-program-dependencies! - (lambda (node) - (for-each (lambda (req) (chase-library req libs-visible?)) (program-node-invoke-req* node)) - (node-depend*-set! node (find-dependencies (program-node-invoke-req* node) #f)))) - (define chase-library-dependencies! - (lambda (node) - (if (library-node-visible? node) - (for-each - (lambda (req) - (unless ($system-library? (libreq-path req)) - (chase-library req (library-node-visible? node)))) - (library-node-import-req* node)) - (for-each - (lambda (req) (chase-library req (library-node-visible? node))) - (library-node-invoke-req* node))) - (unless (node-depend* node) - (node-depend*-set! node - (find-dependencies - (library-node-invoke-req* node) - (and (library-node-visible? node) (library-node-import-req* node))))))) - (let-values ([(maybe-program node* rcinfo*) (process-ir*! ir* ifn capture-program? libs-visible?)]) - (when capture-program? - (unless maybe-program ($oops who "missing entry program in file ~a" ifn)) - (unless (program-node-ir maybe-program) ($oops who "loading ~a did not define expected program pieces" ifn)) - (chase-program-dependencies! maybe-program)) - (for-each chase-library-dependencies! node*) - (let-values ([(visible* invisible*) (partition library-node-visible? (vector->list (hashtable-values libs)))]) - (values maybe-program visible* invisible* rcinfo* wpo*)))))) - - (define topological-sort - (lambda (program-entry library-entry*) - (define topological-sort - (lambda (dep* node*) - (if (null? dep*) - node* - (let* ([dep (car dep*)] [use-count (node-use-count dep)]) - (node-use-count-set! dep (fx- use-count 1)) - (if (fx= use-count 1) - (topological-sort (cdr dep*) (topological-sort (node-depend* dep) (cons dep node*))) - (topological-sort (cdr dep*) node*)))))) - (fold-right - (lambda (entry node*) (topological-sort (node-depend* entry) (cons entry node*))) - (if program-entry (topological-sort (node-depend* program-entry) '()) '()) - (filter (lambda (node) (fx= (node-use-count node) 0)) library-entry*)))) - - (define void-pr (lookup-primref 3 'void)) - - (with-output-language (Lsrc Expr) - (define build-install-library/ct-code - (lambda (node) - (nanopass-case (Lexpand ctLibrary) (library-node-ctir node) - [(library/ct ,uid (,export-id* ...) ,import-code ,visit-code) - (if (library-node-visible? node) - ($build-install-library/ct-code uid export-id* import-code visit-code) - void-pr)]))) - - (define build-void (let ([void-rec `(quote ,(void))]) (lambda () void-rec))) - - (define gen-var (lambda (sym) (make-prelex sym 0 #f #f))) - (define build-let - (lambda (ids exprs body) - `(call ,(make-preinfo) ,(build-lambda ids body) ,exprs ...))) - - (define build-lambda - (lambda (ids body) - `(case-lambda ,(make-preinfo-lambda) - (clause (,ids ...) ,(length ids) ,body)))) - - (define build-call - (lambda (e . e*) - `(call ,(make-preinfo) ,e ,e* ...))) - - (define-syntax build-primcall - ; written as a macro to give lookup-primref a chance to lookup the primref at expansion time - (syntax-rules () - [(_ ?name ?arg ...) (build-call (lookup-primref 3 ?name) ?arg ...)])) - - (define-syntax build-primref - (syntax-rules () - [(_ ?level ?name) (lookup-primref ?level ?name)])) - - (define build-install-library/rt-code - (lambda (node thunk) - (build-primcall '$install-library/rt-code `(quote ,(library-node-uid node)) thunk))) - - (define-pass patch : Lsrc (ir env) -> Lsrc () - (definitions - (define with-initialized-ids - (lambda (old-id* proc) - (let ([new-id* (map (lambda (old-id) - (let ([new-id (make-prelex - (prelex-name old-id) - (let ([flags (prelex-flags old-id)]) - (fxlogor - (fxlogand flags (constant prelex-sticky-mask)) - (fxsll (fxlogand flags (constant prelex-is-mask)) - (constant prelex-was-flags-offset)))) - (prelex-source old-id) - #f)]) - (prelex-operand-set! old-id new-id) - new-id)) - old-id*)]) - (let-values ([v* (proc new-id*)]) - (for-each (lambda (old-id) (prelex-operand-set! old-id #f)) old-id*) - (apply values v*))))) - (define build-ref - (case-lambda - [(x) (build-ref #f x)] - [(src x) - (let ([x (prelex-operand x)]) - (safe-assert (prelex? x)) - (if (prelex-referenced x) - (set-prelex-multiply-referenced! x #t) - (set-prelex-referenced! x #t)) - `(ref ,src ,x))]))) - (Expr : Expr (ir) -> Expr () - [(ref ,maybe-src ,x) (build-ref maybe-src x)] - [(call ,preinfo ,pr (quote ,d)) - (guard (eq? (primref-name pr) '$top-level-value) (symbol? d)) - (cond - [(symbol-hashtable-ref env d #f) => (lambda (x) (build-ref (preinfo-src preinfo) x))] - [else ir])] - [(set! ,maybe-src ,x ,[e]) - (let ([x (prelex-operand x)]) - (safe-assert (prelex? x)) - (set-prelex-assigned! x #t) - `(set! ,maybe-src ,x ,e))] - [(letrec ([,x* ,e*] ...) ,body) - (with-initialized-ids x* - (lambda (x*) - `(letrec ([,x* ,(map Expr e*)] ...) ,(Expr body))))] - [(letrec* ([,x* ,e*] ...) ,body) - (with-initialized-ids x* - (lambda (x*) - `(letrec* ([,x* ,(map Expr e*)] ...) ,(Expr body))))]) - (CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause () - [(clause (,x* ...) ,interface ,body) - (with-initialized-ids x* - (lambda (x*) - `(clause (,x* ...) ,interface ,(Expr body))))])) - - (define build-top-level-set!* - (lambda (node) - (nanopass-case (Lexpand rtLibrary) (library-node-rtir node) - [(library/rt ,uid (,dl* ...) (,db* ...) (,dv* ...) (,de* ...) ,body) - (fold-right - (lambda (dl db dv body) - (if dl - `(seq ,(build-primcall '$set-top-level-value! `(quote ,dl) - `(cte-optimization-loc ,db (ref #f ,dv))) - ,body) - body)) - (build-void) dl* db* dv*)]))) - - (define make-patch-env - (lambda (cluster*) - (let ([patch-env (make-hashtable symbol-hash eq?)]) - (for-each - (lambda (cluster) - (for-each - (lambda (node) - (unless (library-node-binary? node) - (nanopass-case (Lexpand rtLibrary) (library-node-rtir node) - [(library/rt ,uid (,dl* ...) (,db* ...) (,dv* ...) (,de* ...) ,body) - (for-each (lambda (label var) - (when label - (symbol-hashtable-set! patch-env label var))) - dl* dv*)]))) - cluster)) - cluster*) - patch-env))) - - (define build-combined-program-ir - (lambda (program node*) - `(seq - ,(build-primcall 'for-each - (build-primref 3 '$mark-pending!) - `(quote ,(map library-node-uid (remp library-node-binary? node*)))) - ,(patch - (fold-right - (lambda (node combined-body) - (if (library-node-binary? node) - `(seq - ,(build-primcall '$invoke-library - `(quote ,(library-node-path node)) - `(quote ,(library-node-version node)) - `(quote ,(library-node-uid node))) - ,combined-body) - (nanopass-case (Lexpand rtLibrary) (library-node-rtir node) - [(library/rt ,uid (,dl* ...) (,db* ...) (,dv* ...) (,de* ...) ,body) - `(letrec* ([,dv* ,de*] ...) - (seq ,body - (seq - ,(build-install-library/rt-code node - (if (library-node-visible? node) - (build-lambda '() (build-top-level-set!* node)) - void-pr)) - ,combined-body)))]))) - (nanopass-case (Lexpand Program) (program-node-ir program) - [(program ,uid ,body) body]) - node*) - (make-patch-env (list node*)))))) - - (define build-combined-library-ir - (lambda (cluster*) - (define build-mark-invoked! - (lambda (node) - (build-primcall '$mark-invoked! `(quote ,(library-node-uid node))))) - - (define build-cluster - (lambda (node* cluster-body) - (fold-right - (lambda (node cluster-body) - (nanopass-case (Lexpand rtLibrary) (library-node-rtir node) - [(library/rt ,uid (,dl* ...) (,db* ...) (,dv* ...) (,de* ...) ,body) - `(letrec* ([,dv* ,de*] ...) - (seq ,body - (seq - ,(if (library-node-visible? node) - `(seq ,(build-top-level-set!* node) ,(build-mark-invoked! node)) - (build-mark-invoked! node)) - ,cluster-body)))])) - cluster-body node*))) - (patch - ; example: D imports C; C imports A, B; B imports A; A imports nothing - ; have wpos for D, A, B; obj for C - ; (let ([lib-f (void)]) - ; (set! lib-f - ; (lambda (idx) - ; (letrec ([A-local ---] ...) - ; A-body - ; (begin ($top-level-set! A-export A-local) ...) - ; (letrec ([B-local ---] ...) - ; B-body - ; (begin ($top-level-set! B-export B-local) ...) - ; (let ([t (lambda (idx) - ; (letrec ([D-local ---] ...) - ; D-body - ; (begin ($top-level-set! D-export B-local) ...) - ; (set! lib-f (lambda (idx) (void)))))]) - ; (if (eqv? idx 0) - ; (set! lib-f t) - ; (t idx))))))) - ; ($install-library/rt-code 'A-uid (lambda () (lib-f 0))) - ; ($install-library/rt-code 'B-uid (lambda () (lib-f 0))) - ; ($install-library/rt-code 'D-uid (lambda () (lib-f 1))) - ; (void)) - (let ([lib-f (gen-var 'lib-f)]) - (let ([cluster-idx* (enumerate cluster*)]) - (build-let (list lib-f) (list (build-void)) - `(seq - (set! #f ,lib-f - ,(let f ([cluster* cluster*] [cluster-idx* cluster-idx*]) - (let ([idx (gen-var 'idx)]) - (build-lambda (list idx) - (build-cluster (car cluster*) - (let ([cluster* (cdr cluster*)]) - (if (null? cluster*) - (let ([idx (gen-var 'idx)]) - `(set! #f ,lib-f ,(build-lambda (list idx) (build-void)))) - (let ([t (gen-var 't)]) - (build-let (list t) (list (f cluster* (cdr cluster-idx*))) - `(if ,(build-primcall 'eqv? `(ref #f ,idx) `(quote ,(car cluster-idx*))) - (set! #f ,lib-f (ref #f ,t)) - ,(build-call `(ref #f ,t) `(ref #f ,idx)))))))))))) - ,(fold-right (lambda (cluster cluster-idx body) - (fold-right (lambda (node body) - `(seq - ,(build-install-library/rt-code node - (if (library-node-visible? node) - (build-lambda '() - (build-call `(ref #f ,lib-f) `(quote ,cluster-idx))) - void-pr)) - ,body)) - body cluster)) - (build-void) cluster* cluster-idx*))))) - (make-patch-env cluster*))))) - - (with-output-language (Lexpand Outer) - (define add-recompile-info - (lambda (rcinfo* body) - (fold-left - (lambda (body rcinfo) - `(group (recompile-info ,rcinfo) ,body)) - body - rcinfo*))) - - (define requirements-join - (lambda (req* maybe-collected-invoke-req*) - (define (->libreq node) - (make-libreq - (library-node-path node) - (library-node-version node) - (library-node-uid node))) - (if maybe-collected-invoke-req* - (let f ([invoke-req* maybe-collected-invoke-req*]) - (if (null? invoke-req*) - req* - (let* ([invoke-req (car invoke-req*)] [uid (library-node-uid invoke-req)]) - (if (memp (lambda (req) (eq? (libreq-uid req) uid)) req*) - (f (cdr invoke-req*)) - (cons (->libreq invoke-req) (f (cdr invoke-req*))))))) - req*))) - - (define add-library/rt-records - (lambda (maybe-ht node* body) - (fold-left - (lambda (body node) - (if (library-node-binary? node) - body - (let* ([info (library-node-rtinfo node)] - [uid (library-info-uid info)]) - `(group (revisit-only - (library/rt-info - ,(make-library/rt-info - (library-info-path info) - (library-info-version info) - uid - (library-node-visible? node) - (requirements-join - (library/rt-info-invoke-req* info) - (and maybe-ht (symbol-hashtable-ref maybe-ht uid #f)))))) - ,body)))) - body node*))) - - (define add-library/ct-records - (lambda (maybe-ht visit-lib* body) - (fold-left - (lambda (body visit-lib) - (if (library-node-binary? visit-lib) - body - (let* ([info (library-node-ctinfo visit-lib)] - [uid (library-info-uid info)]) - `(group (visit-only - (library/ct-info - ,(make-library/ct-info - (library-info-path info) - (library-info-version info) - uid - (library-node-visible? visit-lib) - (requirements-join - (library/ct-info-import-req* info) - (and maybe-ht (symbol-hashtable-ref maybe-ht uid #f))) - (library/ct-info-visit-visit-req* info) - (library/ct-info-visit-req* info)))) - ,body)))) - body visit-lib*))) - - (define add-program-record - (lambda (node body) - `(group (revisit-only - (program-info - ,(make-program-info - (program-node-uid node) - ; NB: possibly list direct or indirect binary library reqs here - (program-node-invoke-req* node)))) - ,body))) - - (define add-visit-lib-install* - (lambda (visit-lib* body) - (fold-left (lambda (body visit-lib) - (if (library-node-binary? visit-lib) - body - `(group (visit-only ,(build-install-library/ct-code visit-lib)) ,body))) - body visit-lib*))) - - (define build-cluster* - (lambda (node* ht) - (define (add-deps! node deps) - (symbol-hashtable-set! ht (library-node-uid node) deps)) - (define (s-entry/binary node* rcluster* deps) - (if (null? node*) - (reverse rcluster*) - (let ([node (car node*)]) - (if (library-node-binary? node) - (s-entry/binary (cdr node*) rcluster* (cons node deps)) - (begin - (add-deps! node deps) - (s-source (cdr node*) (list node) rcluster* (list node))))))) - (define (s-source node* rnode* rcluster* deps) - (if (null? node*) - (reverse (cons (reverse rnode*) rcluster*)) - (let ([node (car node*)]) - (if (library-node-binary? node) - (s-entry/binary (cdr node*) (cons (reverse rnode*) rcluster*) - (cons node deps)) - (begin - (add-deps! node deps) - (s-source (cdr node*) (cons node rnode*) rcluster* deps)))))) - (s-entry/binary node* '() '()))) - - (define build-program-body - (lambda (program-entry node* visit-lib* invisible* rcinfo*) - (add-recompile-info rcinfo* - (add-library/rt-records #f node* - (add-library/ct-records #f visit-lib* - (add-library/ct-records #f invisible* - (add-program-record program-entry - (add-visit-lib-install* visit-lib* - (add-visit-lib-install* invisible* - `(revisit-only ,(build-combined-program-ir program-entry node*))))))))))) - - (define build-library-body - (lambda (node* visit-lib* rcinfo*) - (let* ([collected-req-ht (make-hashtable symbol-hash eq?)] - [cluster* (build-cluster* node* collected-req-ht)]) - (add-recompile-info rcinfo* - (add-library/rt-records collected-req-ht node* - (add-library/ct-records collected-req-ht visit-lib* - (add-visit-lib-install* visit-lib* - `(revisit-only ,(build-combined-library-ir cluster*)))))))))) - - (define finish-compile - (lambda (who msg ifn ofn hash-bang-line x1) - (with-object-file who ofn - (lambda (op) - (with-coverage-file who ofn - (lambda (source-table) - (when hash-bang-line (put-bytevector op hash-bang-line)) - (parameterize ([$target-machine (constant machine-type-name)] - ; dummy sfd for block-profile optimization - [$sfd (make-source-file-descriptor ifn #xc7 #xc7c7)] - [$block-counter 0]) - (when source-table ($insert-profile-src! source-table x1)) - (emit-header op (constant scheme-version) (constant machine-type)) - (let-values ([(rcinfo* lpinfo* final*) (compile-file-help1 x1 msg)]) - (compile-file-help2 op (list rcinfo*) (list lpinfo*) (list final*)))))))))) - - (define write-wpo-file - (lambda (who ofn ir*) - (with-wpo-file who ofn - (lambda (wpoop) - (when wpoop - (emit-header wpoop (constant scheme-version) (host-machine-type)) - ($with-fasl-target (host-machine-type) - (lambda () - (parameterize ([$target-machine (machine-type)]) - (let ([t ($fasl-table)]) - (let ([x (fold-left (lambda (outer ir) (with-output-language (Lexpand Outer) `(group ,outer ,ir))) - (car ir*) (cdr ir*))]) - ($fasl-enter x t (constant annotation-all)) - ($fasl-start wpoop t (constant fasl-type-visit-revisit) (lambda (p) ($fasl-out x p t (constant annotation-all)))))))))))))) - - (define build-required-library-list - (lambda (node* visit-lib*) - (let ([ht (make-hashtable symbol-hash eq?)]) - (fold-left - (lambda (ls node) - (if (and (library-node-binary? node) (not (symbol-hashtable-contains? ht (library-node-uid node)))) - (cons (library-node-path node) ls) - ls)) - (fold-left - (lambda (ls node) - (if (library-node-binary? node) - (begin - (symbol-hashtable-set! ht (library-node-uid node) #t) - (cons (library-node-path node) ls)) - ls)) - '() node*) - visit-lib*)))) - - ;; TODO: Add automatic recompliation ala scheme import/load-library - (set-who! compile-whole-program - (rec compile-whole-program - (case-lambda - [(ifn ofn) (compile-whole-program ifn ofn #f)] - [(ifn ofn libs-visible?) - (unless (string? ifn) ($oops who "~s is not a string" ifn)) - (unless (string? ofn) ($oops who "~s is not a string" ofn)) - (let*-values ([(hash-bang-line ir*) (read-input-file who ifn)] - [(program-entry lib* invisible* rcinfo* no-wpo*) (build-graph who ir* ifn #t #f libs-visible?)]) - (safe-assert program-entry) - (safe-assert (null? no-wpo*)) - (let ([node* (topological-sort program-entry lib*)]) - (finish-compile who "whole program" ifn ofn hash-bang-line - (build-program-body program-entry node* lib* invisible* rcinfo*)) - (build-required-library-list node* lib*)))]))) - - (set-who! compile-whole-library - (lambda (ifn ofn) - (unless (string? ifn) ($oops who "~s is not a string" ifn)) - (unless (string? ofn) ($oops who "~s is not a string" ofn)) - (let*-values ([(hash-bang-line ir*) (read-input-file who ifn)] - [(no-program lib* invisible* rcinfo* wpo*) (build-graph who ir* ifn #f (generate-wpo-files) #t)]) - (safe-assert (not no-program)) - (safe-assert (null? invisible*)) - (safe-assert (or (not (generate-wpo-files)) (not (null? wpo*)))) - (when (null? lib*) ($oops "did not find libraries in input file ~s" ifn)) - (let ([node* (topological-sort #f lib*)]) - (write-wpo-file who ofn wpo*) - (finish-compile who "whole library" ifn ofn hash-bang-line - (build-library-body node* lib* rcinfo*)) - (build-required-library-list node* lib*)))))) - -(set! $c-make-code - (lambda (func subtype free name arity-mask size code-list info pinfo*) - (let ([code `(code ,func - ,subtype - ,free - ,(if (symbol? name) - (symbol->string name) - (and (string? name) name)) - ,arity-mask - ,size - ,code-list - ,info - ,pinfo*)]) - (set-$c-func-code-record! func code) - code))) - -(set! $c-make-closure - (lambda (func) - (or ($c-func-closure-record func) - (let ([x `(closure . ,func)]) - (set-$c-func-closure-record! func x) - x)))) - -(set-who! compile - (rec compile - (case-lambda - [(x0) - (compile x0 - (if (eq? (subset-mode) 'system) - ($system-environment) - (interaction-environment)))] - [(x0 env-spec) - (define-pass expand-Lexpand : Lexpand (ir) -> Lsrc () - (Inner : Inner (ir) -> Expr () - [,lsrc lsrc] - [(program ,uid ,body) ($build-invoke-program uid body)] - [(library/ct ,uid (,export-id* ...) ,import-code ,visit-code) - ($build-install-library/ct-code uid export-id* import-code visit-code)] - [(library/rt ,uid (,dl* ...) (,db* ...) (,dv* ...) (,de* ...) ,body) - ($build-install-library/rt-code uid dl* db* dv* de* body)] - [else (sorry! who "unexpected Lexpand record ~s" ir)]) - (Outer : Outer (ir) -> Expr () - [(group ,[e1] ,[e2]) `(seq ,e1 ,e2)] - [,inner (Inner inner)] - [else (sorry! who "unexpected Lexpand record ~s" ir)])) - (unless (environment? env-spec) ($oops who "~s is not an environment" env-spec)) - ((parameterize ([$target-machine (constant machine-type-name)] [$sfd #f]) - (let* ([x1 (expand-Lexpand ($pass-time 'expand (lambda () (expand x0 env-spec #t))))] - [waste ($uncprep x1 #t)] ; populate preinfo sexpr fields - [waste (when (and (expand-output) (not ($noexpand? x0))) - (pretty-print ($uncprep x1) (expand-output)) - (flush-output-port (expand-output)))] - [x2 ($pass-time 'cpvalid (lambda () ($cpvalid x1)))] - [x2a (let ([cpletrec-ran? #f]) - (let ([x ((run-cp0) - (lambda (x) - (set! cpletrec-ran? #t) - (let ([x ($pass-time 'cp0 (lambda () ($cp0 x)))]) - ($pass-time 'cpletrec (lambda () ($cpletrec x))))) - x2)]) - (if cpletrec-ran? x ($pass-time 'cpletrec (lambda () ($cpletrec x))))))] - [x2b ($pass-time 'cpcheck (lambda () ($cpcheck x2a)))] - [x2b ($pass-time 'cpcommonize (lambda () ($cpcommonize x2b)))]) - (when (and (expand/optimize-output) (not ($noexpand? x0))) - (pretty-print ($uncprep x2b) (expand/optimize-output)) - (flush-output-port (expand/optimize-output))) - (if (and (compile-interpret-simple) - (not ($assembly-output)) - (cheat? x2b)) - (lambda () (cheat-eval x2b)) - ($compile-backend x2b)))))]))) - -(set! $compile-backend - (lambda (x2) - (c-mkcode (c-compile x2)))) - -(let () - (define emit-boot-header - (lambda (op machine bootfiles) - (emit-header op (constant scheme-version) (constant machine-type) (map path-root (map path-last bootfiles))) - (when (null? bootfiles) - (parameterize ([$target-machine machine] [$sfd #f]) - (c-print-fasl ($np-boot-code 'error-invoke) op (constant fasl-type-visit-revisit)) - (c-print-fasl ($np-boot-code 'invoke) op (constant fasl-type-visit-revisit)) - ($fasl-base-rtd #!base-rtd op))))) - - (define do-make-boot-file - (lambda (who outfn machine bootfile* infn*) - (unless (string? outfn) ($oops who "~s is not a string" outfn)) - (unless (symbol? machine) ($oops who "~s is not a symbol" machine)) - (unless (eq? machine (constant machine-type-name)) - ($oops who "compiler for ~s is not loaded" machine)) - (unless (and (list? bootfile*) (andmap string? bootfile*)) - ($oops who "~s is not a list of strings" bootfile*)) - (for-each - (lambda (infn) (unless (string? infn) ($oops who "~s is not a string" infn))) - infn*) - (with-object-file who outfn - (lambda (op) - (with-coverage-file who outfn - (lambda (source-table) - (unless (and (eq? who 'make-boot-file) (null? bootfile*)) - (emit-boot-header op machine bootfile*)) - (for-each - (lambda (infn) - (let ([ip ($open-file-input-port who infn)]) - (on-reset (close-port ip) - (if ($compiled-file-header? ip) - (begin - (let* ([bufsiz (file-buffer-size)] [buf (make-bytevector bufsiz)]) - (let loop () - (let ([n (get-bytevector-n! ip buf 0 bufsiz)]) - (unless (eof-object? n) - (put-bytevector op buf 0 n) - (loop))))) - (when source-table - (guard (c [else (void)]) - (let ([ip ($open-file-input-port who (new-extension "covin" infn) - (file-options compressed) - (buffer-mode block) - (current-transcoder))]) - (on-reset (close-port ip) - (get-source-table! ip source-table)) - (close-port ip))))) - (let ([sfd ($source-file-descriptor infn ip)]) - ; whack ip so close-port calls close the text port - (set! ip (transcoded-port ip (current-transcoder))) - (compile-file-help op #f #f source-table machine sfd ($make-read ip sfd 0) outfn)))) - (close-port ip))) - infn*))))))) - - (define do-make-boot-header - ; create boot loader (invoke) for entry into Scheme from C - (lambda (who out machine bootfiles) - (unless (string? out) ($oops who "~s is not a string" out)) - (unless (symbol? machine) ($oops who "~s is not a symbol" machine)) - (unless (eq? machine (constant machine-type-name)) - ($oops who "compiler for ~s is not loaded" machine)) - (for-each (lambda (x) - (unless (string? x) - ($oops who "~s is not a string" x))) - bootfiles) - (with-object-file who out - (lambda (op) - (emit-boot-header op machine bootfiles))))) - - (set-who! make-boot-file - (lambda (outfn bootfile* . infn*) - (do-make-boot-file who outfn (machine-type) bootfile* infn*))) - - (set-who! $make-boot-file - (lambda (outfn machine bootfile* . infn*) - (do-make-boot-file who outfn machine bootfile* infn*))) - - (set-who! make-boot-header - ; exported interface: machine-type implicit and requires one or more - ; subordinate boot files - (lambda (out bootfile . bootfiles) - (do-make-boot-header who out (machine-type) (cons bootfile bootfiles)))) - - (set-who! $make-boot-header - ; create boot loader (invoke) for entry into Scheme from C - (lambda (out machine . bootfiles) - (do-make-boot-header who out machine bootfiles)))) - -(let () - (define (libreq-hash x) (symbol-hash (libreq-uid x))) - (define (libreq=? x y) (eq? (libreq-uid x) (libreq-uid y))) - (define do-concatenate-object-files - (lambda (who outfn infn*) - (unless (string? outfn) ($oops who "~s is not a string" outfn)) - (for-each (lambda (infn) (unless (string? infn) ($oops who "~s is not a string" infn))) infn*) - (let ([import-ht (make-hashtable libreq-hash libreq=?)] - [include-ht (make-hashtable string-hash string=?)]) - (let in-loop ([infn* infn*] [rip* '()]) - (if (null? infn*) - (let ([ip* (reverse rip*)]) - (with-object-file who outfn - (lambda (op) - (emit-header op (constant scheme-version) (constant machine-type)) - (c-print-fasl `(object ,(make-recompile-info - (vector->list (hashtable-keys import-ht)) - (vector->list (hashtable-keys include-ht)))) - op (constant fasl-type-visit-revisit)) - (for-each (lambda (ip) - (let loop () ;; NB: This loop consumes one entry past the last library/program info record, - ;; which we presume is the #t end-of-header marker. - (let ([ty (lookahead-u8 ip)]) - (unless (eof-object? ty) - ;; perhaps should verify ty here. - (let ([x (fasl-read ip)]) - (when (or (library-info? x) (program-info? x)) - (c-print-fasl `(object ,x) op ty) - (loop))))))) - ip*) - ;; inserting #t after lpinfo as an end-of-header marker - (c-print-fasl `(object #t) op (constant fasl-type-visit-revisit)) - (let* ([bufsiz (file-buffer-size)] [buf (make-bytevector bufsiz)]) - (for-each (lambda (ip) - (let loop () - (let ([n (get-bytevector-n! ip buf 0 bufsiz)]) - (unless (eof-object? n) - (put-bytevector op buf 0 n) - (loop)))) - (close-port ip)) - ip*))))) - (let* ([fn (car infn*)] - [ip ($open-file-input-port who fn)]) - (on-reset (close-port ip) - ;; NB: Does not currently support files beginning with a #! line. Add that here if desired. - (unless ($compiled-file-header? ip) ($oops who "missing header for compiled file ~s" fn)) - (let ([rcinfo (fasl-read ip)]) - (unless (recompile-info? rcinfo) ($oops who "expected recompile info at start of ~s, found ~a" fn rcinfo)) - (for-each - (lambda (x) - ;; NB: this could be enhanced to perform additional checks for compatible versions - (hashtable-set! import-ht x x)) - (recompile-info-import-req* rcinfo)) - (for-each - (lambda (x) (hashtable-set! include-ht x #t)) - (recompile-info-include-req* rcinfo)) - (in-loop (cdr infn*) (cons ip rip*)) - )))))))) - - (set-who! concatenate-object-files - (lambda (outfn infn0 . infn*) - (do-concatenate-object-files who outfn (cons infn0 infn*)))) - ) - -(set-who! compile-port - (rec compile-port - (case-lambda - [(ip op) (compile-port ip op #f)] - [(ip op sfd) (compile-port ip op sfd #f)] - [(ip op sfd wpoop) (compile-port ip op sfd wpoop #f)] - [(ip op sfd wpoop covop) (compile-port ip op sfd wpoop covop (constant machine-type-name))] - [(ip op sfd wpoop covop machine) (compile-port ip op sfd wpoop covop machine #f)] - [(ip op sfd wpoop covop machine hostop) - (unless (and (input-port? ip) (textual-port? ip)) - ($oops who "~s is not a textual input port" ip)) - (unless (and (output-port? op) (binary-port? op)) - ($oops who "~s is not a binary output port" op)) - (when ($port-flags-set? op (constant port-flag-compressed)) ($compressed-warning who op)) - (when sfd - (unless (source-file-descriptor? sfd) - ($oops who "~s is not a source-file descriptor or #f" sfd))) - (when wpoop - (unless (and (output-port? wpoop) (binary-port? wpoop)) - ($oops who "~s is not a binary output port or #f" wpoop)) - (when ($port-flags-set? wpoop (constant port-flag-compressed)) ($compressed-warning who wpoop))) - (when covop - (unless (and (output-port? covop) (textual-port? covop)) - ($oops who "~s is not a textual output port or #f" covop))) - (unless (symbol? machine) ($oops who "~s is not a symbol" machine)) - (unless (eq? machine (constant machine-type-name)) - ($oops who "compiler for ~s is not loaded" machine)) - (when hostop - (unless (and (output-port? hostop) (binary-port? hostop)) - ($oops who "~s is not a binary output port or #f" hostop)) - (when ($port-flags-set? hostop (constant port-flag-compressed)) ($compressed-warning who hostop))) - (let ([source-table (and covop (make-source-table))]) - (let ([fp (and (port-has-port-position? ip) - (let ([fp (port-position ip)]) - (if ($port-flags-set? ip (constant port-flag-char-positions)) - fp - (and (eqv? fp 0) fp))))]) - (compile-file-help op hostop wpoop source-table machine sfd ($make-read ip sfd fp) #f) - (when covop (put-source-table covop source-table))))]))) - -(set-who! compile-to-port - (rec compile-to-port - (case-lambda - [(sexpr* op) (compile-to-port sexpr* op #f)] - [(sexpr* op sfd) (compile-to-port sexpr* op sfd #f)] - [(sexpr* op sfd wpoop) (compile-to-port sexpr* op sfd wpoop #f)] - [(sexpr* op sfd wpoop covop) (compile-to-port sexpr* op sfd wpoop covop (constant machine-type-name))] - [(sexpr* op sfd wpoop covop machine) (compile-to-port sexpr* op sfd wpoop covop machine #f)] - [(sexpr* op sfd wpoop covop machine hostop) - (define do-compile-to-port - (lambda () - (let ([source-table (and covop (make-source-table))]) - (compile-file-help op hostop wpoop source-table machine sfd - (lambda () - (if (null? sexpr*) - (eof-object) - (let ([x (car sexpr*)]) - (set! sexpr* (cdr sexpr*)) - x))) - (port-name op)) - (when covop (put-source-table covop source-table))))) - (unless (list? sexpr*) - ($oops who "~s is not a proper list" sexpr*)) - (unless (and (output-port? op) (binary-port? op)) - ($oops who "~s is not a binary output port" op)) - (when ($port-flags-set? op (constant port-flag-compressed)) ($compressed-warning who op)) - (when sfd - (unless (source-file-descriptor? sfd) - ($oops who "~s is not a source-file descriptor or #f" sfd))) - (when wpoop - (unless (and (output-port? wpoop) (binary-port? wpoop)) - ($oops who "~s is not a binary output port or #f" wpoop)) - (when ($port-flags-set? wpoop (constant port-flag-compressed)) ($compressed-warning who wpoop))) - (when covop - (unless (and (output-port? covop) (textual-port? covop)) - ($oops who "~s is not a textual output port or #f" covop))) - (unless (symbol? machine) ($oops who "~s is not a symbol" machine)) - (unless (eq? machine (constant machine-type-name)) - ($oops who "compiler for ~s is not loaded" machine)) - (when hostop - (unless (and (output-port? hostop) (binary-port? hostop)) - ($oops who "~s is not a binary output port or #f" hostop)) - (when ($port-flags-set? hostop (constant port-flag-compressed)) ($compressed-warning who hostop))) - (if (and (= (length sexpr*) 1) (pair? (car sexpr*)) (eq? (caar sexpr*) 'top-level-program)) - (let ([library-collector (make-parameter '())]) - (parameterize ([$require-libraries library-collector]) - (do-compile-to-port)) - (library-collector)) - (do-compile-to-port))]))) - -(let () - (define (in&out in) - (let ([ext (path-extension in)]) - (cond - [(string=? ext "") (values (format "~a.ss" in) (format "~a.so" in))] - [(string=? ext "so") (values in (format "~a.so" in))] - [else (values in (format "~a.so" (path-root in)))]))) - - (define (do-compile-to-file who out hostout machine sfd do-read) - (with-object-file who out - (lambda (op) - (with-host-file who hostout - (lambda (hostop) - (with-wpo-file who out - (lambda (wpoop) - (with-coverage-file who out - (lambda (source-table) - (compile-file-help op hostop wpoop source-table machine sfd do-read out)))))))))) - - (define (do-compile-file who in out hostout machine r6rs?) - (unless (string? in) ($oops who "~s is not a string" in)) - (unless (string? out) ($oops who "~s is not a string" out)) - (unless (symbol? machine) ($oops who "~s is not a symbol" machine)) - (unless (eq? machine (constant machine-type-name)) ($oops who "compiler for ~s is not loaded" machine)) - (when (compile-file-message) (printf "compiling ~a with output to ~a~@[ (host output to ~a)~]\n" in out hostout)) - (let ([ip ($open-file-input-port who in)]) - (on-reset (close-port ip) - (let ([sfd ($source-file-descriptor in ip)]) - ; whack existing ip so close-port calls close the text port - (set! ip (transcoded-port ip (current-transcoder))) - (when r6rs? ($set-port-flags! ip (constant port-flag-r6rs))) - (let ([fp (let ([start-pos (port-position ip)]) - (if (and (eqv? (read-char ip) #\#) - (eqv? (read-char ip) #\!) - (memv (read-char ip) '(#\space #\/))) - (let loop ([fp 3]) - (let ([c (read-char ip)]) - (if (eof-object? c) - fp - (let ([fp (+ fp 1)]) - (if (char=? c #\newline) - fp - (loop fp)))))) - (begin - (set-port-position! ip start-pos) - 0)))]) - (do-compile-to-file who out hostout machine sfd ($make-read ip sfd fp))))) - (close-port ip))) - - (define (do-compile-script who in out machine r6rs?) - (define ($make-read-program ip sfd fp) - (let ([do-read ($make-read ip sfd fp)]) - (lambda () - (let f ([form* '()]) - (let ([x (do-read)]) - (if (eof-object? x) - (if (null? form*) x `(top-level-program ,@(reverse form*))) - (f (cons x form*)))))))) - (unless (string? in) ($oops who "~s is not a string" in)) - (unless (string? out) ($oops who "~s is not a string" out)) - (unless (symbol? machine) ($oops who "~s is not a symbol" machine)) - (unless (eq? machine (constant machine-type-name)) ($oops who "compiler for ~s is not loaded" machine)) - (when (compile-file-message) (printf "compiling ~a with output to ~a\n" in out)) - (let ([ip ($open-file-input-port who in)]) - (on-reset (close-port ip) - (let ([sfd ($source-file-descriptor in ip)]) - ; whack existing ip so close-port calls close the text port - (set! ip (transcoded-port ip (current-transcoder))) - (when r6rs? ($set-port-flags! ip (constant port-flag-r6rs))) - (let ([start-pos (port-position ip)]) - (if (and (eqv? (read-char ip) #\#) - (eqv? (read-char ip) #\!) - (memv (lookahead-char ip) '(#\space #\/))) - ; copy #! line - (with-object-file who out - (lambda (op) - (with-wpo-file who out - (lambda (wpoop) - (with-coverage-file who out - (lambda (source-table) - (put-u8 op (char->integer #\#)) - (put-u8 op (char->integer #\!)) - (when wpoop (put-u8 wpoop (char->integer #\#))) - (when wpoop (put-u8 wpoop (char->integer #\!))) - (let ([fp (let loop ([fp 2]) - (let ([c (read-char ip)]) - (when (eof-object? c) - ($oops who "unexpected eof reading script header on ~s" in)) - (let ([n (char->integer c)]) - (unless (fx< n 256) - ($oops who - "integer code for ~s script header character ~s is too large to copy to output port" - in c)) - (put-u8 op n) - (when wpoop (put-u8 wpoop n))) - (let ([fp (+ fp 1)]) - (if (char=? c #\newline) fp (loop fp)))))]) - (compile-file-help op #f wpoop source-table machine sfd ((if r6rs? $make-read-program $make-read) ip sfd fp) out)))))))) - ; no #! line - (with-object-file who out - (lambda (op) - (set-port-position! ip start-pos) - (with-wpo-file who out - (lambda (wpoop) - (with-coverage-file who out - (lambda (source-table) - (compile-file-help op #f wpoop source-table machine sfd ((if r6rs? $make-read-program $make-read) ip sfd 0) out))))))))))) - (close-port ip)) - (unless-feature windows (chmod out #o755))) - - (set-who! compile-file - (case-lambda - [(in out machine) (do-compile-file who in out #f machine #f)] - [(in out) (do-compile-file who in out #f (constant machine-type-name) #f)] - [(in) - (unless (string? in) ($oops who "~s is not a string" in)) - (let-values ([(in out) (in&out in)]) - (do-compile-file who in out #f (constant machine-type-name) #f))])) - - (set-who! compile-library - (let () - (define do-compile-library - (lambda (in out machine) - (do-compile-file who in out - (and (not (eq? machine (machine-type))) - (format "~a.~s" (path-root out) (machine-type))) - machine - #t))) - (case-lambda - [(in out machine) (do-compile-library in out machine)] - [(in out) (do-compile-library in out (constant machine-type-name))] - [(in) - (unless (string? in) ($oops who "~s is not a string" in)) - (let-values ([(in out) (in&out in)]) - (do-compile-library in out (constant machine-type-name)))]))) - - (set-who! compile-script - (case-lambda - [(in out machine) (do-compile-script who in out machine #f)] - [(in out) (do-compile-script who in out (constant machine-type-name) #f)] - [(in) - (unless (string? in) ($oops who "~s is not a string" in)) - (let-values ([(in out) (in&out in)]) - (do-compile-script who in out (constant machine-type-name) #f))])) - - (set-who! compile-program - (let () - (define (do-compile-program in out machine) - (let ([library-collector (make-parameter '())]) - (parameterize ([$require-libraries library-collector]) - (do-compile-script who in out machine #t)) - (library-collector))) - (case-lambda - [(in out machine) (do-compile-program in out machine)] - [(in out) (do-compile-program in out (constant machine-type-name))] - [(in) - (unless (string? in) ($oops who "~s is not a string" in)) - (let-values ([(in out) (in&out in)]) - (do-compile-program in out (constant machine-type-name)))]))) - - (set-who! maybe-compile-file - (case-lambda - [(in out) - (unless (string? in) ($oops who "~s is not a string" in)) - (unless (string? out) ($oops who "~s is not a string" out)) - ($maybe-compile-file who in out compile-file) - (void)] - [(in) - (unless (string? in) ($oops who "~s is not a string" in)) - (let-values ([(in out) (in&out in)]) - ($maybe-compile-file who in out compile-file)) - (void)])) - - (set-who! maybe-compile-library - (case-lambda - [(in out) - (unless (string? in) ($oops who "~s is not a string" in)) - (unless (string? out) ($oops who "~s is not a string" out)) - ($maybe-compile-file who in out (compile-library-handler)) - (void)] - [(in) - (unless (string? in) ($oops who "~s is not a string" in)) - (let-values ([(in out) (in&out in)]) - ($maybe-compile-file who in out (compile-library-handler))) - (void)])) - - (set-who! maybe-compile-program - (case-lambda - [(in out) - (unless (string? in) ($oops who "~s is not a string" in)) - (unless (string? out) ($oops who "~s is not a string" out)) - ($maybe-compile-file who in out (compile-program-handler)) - (void)] - [(in) - (unless (string? in) ($oops who "~s is not a string" in)) - (let-values ([(in out) (in&out in)]) - ($maybe-compile-file who in out (compile-program-handler))) - (void)])) - - (set-who! compile-to-file - (rec compile-to-file - (case-lambda - [(sexpr* out) (compile-to-file sexpr* out #f)] - [(sexpr* out sfd) - (unless (list? sexpr*) ($oops who "~s is not a proper list" sexpr*)) - (unless (string? out) ($oops who "~s is not a string" out)) - (when sfd (unless (source-file-descriptor? sfd) ($oops who "~s is not a source-file descriptor or #f" sfd))) - (let ([library? (and (= (length sexpr*) 1) (pair? (car sexpr*)) (eq? (caar sexpr*) 'library))] - [program? (and (= (length sexpr*) 1) (pair? (car sexpr*)) (eq? (caar sexpr*) 'top-level-program))]) - (define (go) - (do-compile-to-file who out - (and library? - (not (eq? (constant machine-type-name) (machine-type))) - (format "~a.~s" (path-root out) (machine-type))) - (constant machine-type-name) - sfd - (lambda () - (if (null? sexpr*) - (eof-object) - (let ([x (car sexpr*)]) - (set! sexpr* (cdr sexpr*)) - x))))) - (if program? - (let ([library-collector (make-parameter '())]) - (parameterize ([$require-libraries library-collector]) (go)) - (library-collector)) - (go)))])))) -);let diff --git a/ta6ob/s/compile.ta6ob b/ta6ob/s/compile.ta6ob deleted file mode 100644 index 7fc5467..0000000 Binary files a/ta6ob/s/compile.ta6ob and /dev/null differ diff --git a/ta6ob/s/costctr.ss b/ta6ob/s/costctr.ss deleted file mode 100644 index 6698409..0000000 --- a/ta6ob/s/costctr.ss +++ /dev/null @@ -1,161 +0,0 @@ -;;; costctr.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(module ($cost-center) - (if-feature pthreads - (define-record-type ($cost-center $make-cost-center $cost-center?) - (fields - (mutable level) - (mutable instr-count) - (mutable alloc-count) - (mutable time-ns) - (mutable time-s) - (immutable mutex)) - (nongenerative #{cost-center fgbx8g23emx4rf0txn2sr0-1}) - (opaque #t) - (protocol - (lambda (new) - (lambda () - (new (make-thread-parameter 0) 0 0 0 0 (make-mutex)))))) - (define-record-type ($cost-center $make-cost-center $cost-center?) - (fields - (mutable level) - (mutable instr-count) - (mutable alloc-count) - (mutable time-ns) - (mutable time-s)) - (nongenerative #{cost-center fgbx8g23emx4rf0txn2sr0-2}) - (opaque #t) - (protocol - (lambda (new) - (lambda () (new 0 0 0 0 0)))))) - - (define-syntax cc-level - (lambda (x) - (syntax-case x () - [(_ x) - (if-feature pthreads - #'(($cost-center-level x)) - #'($cost-center-level x))]))) - - (define-syntax cc-level-set! - (lambda (x) - (syntax-case x () - [(_ x v) - (if-feature pthreads - #'(($cost-center-level x) v) - #'($cost-center-level-set! x v))]))) - - (define $with-cost-center - (let () - (define who 'with-cost-center) - (define-syntax with-mutex-if-threaded - (lambda (x) - (syntax-case x () - [(_ mexp e0 e1 ...) - (if-feature pthreads - #'(with-mutex mexp e0 e1 ...) - #'(begin e0 e1 ...))]))) - (define mod- - (lambda (x y) - (let ([r (- x y)]) - (if (< r 0) (+ (expt 2 64) r) r)))) - (lambda (timed? cc th) - (define-record-type saved - (sealed #t) - (nongenerative) - (fields (mutable alloc) (mutable intr) (mutable time))) - (unless ($cost-center? cc) ($oops who "~s is not a cost center" cc)) - (unless (procedure? th) ($oops who "~s is not a procedure" th)) - (let ([saved (make-saved 0 0 #f)]) - (dynamic-wind #t - (lambda () - (let ([level (cc-level cc)]) - (cc-level-set! cc (fx+ level 1)) - (when (fx= level 0) - (saved-alloc-set! saved ($object-ref 'unsigned-64 ($tc) (constant tc-alloc-counter-disp))) - (saved-intr-set! saved ($object-ref 'unsigned-64 ($tc) (constant tc-instr-counter-disp))) - (when timed? (saved-time-set! saved (current-time 'time-thread)))))) - th - (lambda () - (let ([level (cc-level cc)]) - (cc-level-set! cc (fx- level 1)) - (when (fx= level 1) - ; grab time first -- to use up as little as possible - (let* ([curr-time (and timed? (current-time 'time-thread))] - [alloc-count (mod- ($object-ref 'unsigned-64 ($tc) (constant tc-alloc-counter-disp)) - (saved-alloc saved))] - [instr-count (mod- ($object-ref 'unsigned-64 ($tc) (constant tc-instr-counter-disp)) - (saved-intr saved))]) - (with-mutex-if-threaded ($cost-center-mutex cc) - ($cost-center-alloc-count-set! cc - (+ ($cost-center-alloc-count cc) alloc-count)) - ($cost-center-instr-count-set! cc - (+ ($cost-center-instr-count cc) instr-count)) - (when timed? - (let ([saved-time (saved-time saved)]) - (let-values ([(s ns) (let ([ns (- (time-nanosecond curr-time) (time-nanosecond saved-time))] - [s (- (time-second curr-time) (time-second saved-time))]) - (if (< ns 0) - (values (- s 1) (+ ns (expt 10 9))) - (values s ns)))]) - (let-values ([(s ns) (let ([ns (+ ($cost-center-time-ns cc) ns)] - [s (+ ($cost-center-time-s cc) s)]) - (if (>= ns (expt 10 9)) - (values (+ s 1) (- ns (expt 10 9))) - (values s ns)))]) - ($cost-center-time-s-set! cc s) - ($cost-center-time-ns-set! cc ns))))))))))))))) - - (set-who! cost-center-instruction-count - (lambda (cc) - (unless ($cost-center? cc) ($oops who "~s is not a cost center" cc)) - ($cost-center-instr-count cc))) - - (set-who! cost-center-allocation-count - (lambda (cc) - (unless ($cost-center? cc) ($oops who "~s is not a cost center" cc)) - (ash ($cost-center-alloc-count cc) (constant log2-ptr-bytes)))) - - (set-who! cost-center-time - (lambda (cc) - (unless ($cost-center? cc) ($oops who "~s is not a cost center" cc)) - (make-time 'time-duration ($cost-center-time-ns cc) ($cost-center-time-s cc)))) - - (set-who! reset-cost-center! - (lambda (cc) - (unless ($cost-center? cc) ($oops who "~s is not a cost center" cc)) - ($cost-center-instr-count-set! cc 0) - ($cost-center-alloc-count-set! cc 0) - ($cost-center-time-s-set! cc 0) - ($cost-center-time-ns-set! cc 0))) - - (set! cost-center? (lambda (x) ($cost-center? x))) - - (set! make-cost-center (lambda () ($make-cost-center))) - - (set! with-cost-center - (rec with-cost-center - (case-lambda - [(cc th) ($with-cost-center #f cc th)] - [(timed? cc th) ($with-cost-center timed? cc th)]))) - - (record-writer (record-type-descriptor $cost-center) - (lambda (x p wr) - (let ([ns ($cost-center-time-ns x)] [s ($cost-center-time-s x)]) - (fprintf p "#" - (+ ns s) s ns - ($cost-center-instr-count x) - ($cost-center-alloc-count x)))))) diff --git a/ta6ob/s/costctr.ta6ob b/ta6ob/s/costctr.ta6ob deleted file mode 100644 index b8655b9..0000000 Binary files a/ta6ob/s/costctr.ta6ob and /dev/null differ diff --git a/ta6ob/s/cp0.ss b/ta6ob/s/cp0.ss deleted file mode 100644 index a6fb8ae..0000000 --- a/ta6ob/s/cp0.ss +++ /dev/null @@ -1,4807 +0,0 @@ -;;; cp0.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;; TODO: -;; * make seq should just drop effect-free portions of e1 rather than -;; asking if the whole of e1 is simple. -;; * folding/specializing loops -;; * later (much) -;; - split up score for seqs to allow us to avoid adding in score of -;; e2 when we encounter (seq e1 e2) for simple e2 in residualize-call-opnds -;; * try using other than value in visit-operand in contexts where we visit the -;; operand of a singly referenced identifier, e.g., if we see (values opnd) in -;; test context, visit opnd in test context -;; -;; we now no longer collapse quote's into void and true quotes, but -;; rather make if suffer through a (very slightly) more expensive test for -;; record equality - -;; N.B.: we use (operand-wd opnd) in cp0 singly referenced case; this is not quite -;; legitimate, since we can visit the operand more than once with the same (possibly -;; passive) watchdog. Thus we are potentially nonlinear, but in practice it allows -;; us to integrate many harmless singly referenced procedures. - -;; calls to not multiply-referenced identifiers handled as follows: -;; * propagate multiply-referenced flag on copy propagation -;; (let ((x e1)) -;; (let ((y x)) ; set multiply referenced flag on x -;; (let ((z y)) -;; (z y)))) -;; * don't treat as singly referenced when id => id on env lookup, i.e., id is free -;; (presumably outside of operator position, or we would have integrated during -;; value-visit-operand) in procedure being integrated -;; (let ((f e)) -;; (let ((g (lambda () f))) -;; (g) ; don't treat f as singly referenced -;; (g))) -;; * exploit as follows: -;; - maintain singly-referenced-score in operand -;; - if operand-exp of singly-referenced id is a lambda, -;; run with it with operand's watchdog and passive scorer -;; - otherwise value-visit operand, run with result-exp -;; with alert watchdog and passive scorer -;; - set singly-referenced to score from passive scorer in either case -;; if integration succeeds -;; - residualize-call-opnds uses singly-referenced-score if non-false - -(define $cp0 -(let () - (import (nanopass)) - (include "base-lang.ss") - - ;;; set to #f for monovariant filter - (define-threaded polyvariant #t) - - ;;; set to #f to disable inlining of various primitives into code containing - ;;; lambda expressions, e.g., for-each and record-accessor---generally not - ;;; desirable when interpreting rather than compiling the residual code. - (define-threaded likely-to-be-compiled?) - - ;;; score-limit determines max amount of code any integration attempt - ;;; can result in; effort-limit determines max amount of work that can - ;;; be done attempting to integrate - (define-threaded score-limit 20) - (define-threaded effort-limit 200) - - ;;; inner unrolling doesn't work, and when set nonzero, effectively - ;;; disables outer unrolling as well - (define-threaded inner-unroll-limit 0) - - ;;; outer-unroll-limit of 0 disables integration of recursive - ;;; procedures. outer-unroll-limit of 1 is probably a more - ;;; reasonable default, except we then trash cp1's loop recognition - (define-threaded outer-unroll-limit 0) - - ;;; used to memoize pure?, etc. - (define-threaded cp0-info-hashtable) - - (module () - (define-syntax define-cp0-param - (syntax-rules () - [(_ global-name local-name filter) - (set! global-name - (case-lambda - [() local-name] - [(x) (set! local-name (filter 'global-name x))]))])) - - (define filter-limit - (lambda (who x) - (unless (and (fixnum? x) (fx>= x 0)) - ($oops who "invalid limit ~s" x)) - x)) - - (define filter-bool (lambda (who x) (and x #t))) - - (define-cp0-param cp0-effort-limit effort-limit filter-limit) - (define-cp0-param cp0-score-limit score-limit filter-limit) - (define-cp0-param cp0-outer-unroll-limit outer-unroll-limit filter-limit) - - (define-cp0-param $cp0-inner-unroll-limit inner-unroll-limit filter-limit) - (define-cp0-param $cp0-polyvariant polyvariant filter-bool)) - - (define (rappend ls1 ls2) - (if (null? ls1) - ls2 - (rappend (cdr ls1) (cons (car ls1) ls2)))) - - ; don't use rtd-* as defined in record.ss in case we're building a patch - ; file for cross compilation, because the offsets may be incorrect - (define rtd-flds (csv7:record-field-accessor #!base-rtd 'flds)) - (define rtd-parent (csv7:record-field-accessor #!base-rtd 'parent)) - (define rtd-size (csv7:record-field-accessor #!base-rtd 'size)) - (define rtd-pm (csv7:record-field-accessor #!base-rtd 'pm)) - - ; compile-time rtds (ctrtds) - (define ctrtd-opaque-known #b0000001) - (define ctrtd-sealed-known #b0000010) - - (define base-ctrtd ($make-record-type #!base-rtd #!base-rtd "ctrtd" '((immutable flags)) #t #f)) - (define ctrtd? (record-predicate base-ctrtd)) - (define ctrtd-flags (record-accessor base-ctrtd 0)) - - (define record-type-sealed-known? - (lambda (rtd) - (or (not (ctrtd? rtd)) - (fxlogtest (ctrtd-flags rtd) ctrtd-sealed-known)))) - - (define record-type-opaque-known? - (lambda (rtd) - (or (not (ctrtd? rtd)) - (fxlogtest (ctrtd-flags rtd) ctrtd-opaque-known)))) - - (with-output-language (Lsrc Expr) - (define void-rec `(quote ,(void))) - (define true-rec `(quote #t)) - (define false-rec `(quote #f)) - (define null-rec `(quote ())) - (define empty-vector-rec `(quote #())) - (define empty-string-rec `(quote "")) - (define empty-bytevector-rec `(quote #vu8())) - (define empty-fxvector-rec `(quote #vfx())) - - ;;; environments - (module (empty-env with-extended-env lookup) - (define empty-env '()) - - (define-record-type env - (nongenerative) - (fields old-ids new-ids next)) - - (define-syntax with-extended-env - (syntax-rules () - [(_ ((new-env new-ids) (?old-env ?old-ids ?opnds)) e1 e2 ...) - (let-values ([(new-env new-ids) (extend-env ?old-env ?old-ids ?opnds)]) - (let ([e (let () e1 e2 ...)]) - (deinitialize-ids! new-ids) - e))])) - - (define extend-env - (lambda (old-env old-ids opnds) - (let ([new-ids (let loop ([old-ids old-ids] [opnds opnds] [rnew-ids '()]) - (if (null? old-ids) - (reverse rnew-ids) - (loop - (cdr old-ids) - (and opnds (cdr opnds)) - (cons - (let ([old-id (car old-ids)]) - (make-prelex - (prelex-name old-id) - (let ([flags (prelex-flags old-id)]) - (fxlogor - (fxlogand flags (constant prelex-sticky-mask)) - (fxsll (fxlogand flags (constant prelex-is-mask)) - (constant prelex-was-flags-offset)))) - (prelex-source old-id) - (and opnds - (let ([opnd (car opnds)]) - (when (operand? opnd) - (operand-name-set! opnd (prelex-name old-id))) - opnd)))) - rnew-ids))))]) - (values (make-env (list->vector old-ids) (list->vector new-ids) old-env) new-ids)))) - - (define deinitialize-ids! - (lambda (ids) - ; clear operand field (a) to release storage the operands occupy and (b) to - ; prevent fasling of useless operands in cte-optimization-locs. clear even - ; if we didn't set (i.e., even if opnds or the corresponding opnd is #f), for - ; the benefit of cp0-rec-let, which sets operand fields after creating env - (for-each (lambda (id) (prelex-operand-set! id #f)) ids))) - - (define lookup - (lambda (id env) - (let loop1 ([env env]) - (if (eqv? env empty-env) - id - (let ([old-rib (env-old-ids env)] [new-rib (env-new-ids env)]) - (let ([n (vector-length old-rib)]) - (let loop2 ([i 0]) - (if (fx= i n) - (loop1 (env-next env)) - (if (eq? (vector-ref old-rib i) id) - (vector-ref new-rib i) - (let ([i (fx+ i 1)]) - (if (fx= i n) - (loop1 (env-next env)) - (if (eq? (vector-ref old-rib i) id) - (vector-ref new-rib i) - (loop2 (fx+ i 1))))))))))))))) - - (define cp0-make-temp ; returns an unassigned temporary - (lambda (multiply-referenced?) - (let ([t (make-prelex*)]) - (when multiply-referenced? (set-prelex-multiply-referenced! t #t)) - (set-prelex-referenced! t #t) - t))) - - ;;; contexts - - ;; app context: - ;; opnds are the operands at the call site - ;; ctxt is the outer context - ;; convention is a symbol: call, apply2 (safe), or apply3 (unsafe) - ;; src is the call source - ;; used is set to a list of operands used (let-bound) by integrated call - ;; unused is set to a list of operands not used by integrated call - (define-record-type app - (fields opnds ctxt convention name preinfo (mutable used) (mutable unused)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (opnds ctxt convention name preinfo) - (new opnds ctxt convention name preinfo #f #f))))) - - (define-syntax context-case - (lambda (x) - (define predicate - (lambda (type) - (syntax-case type (app) - [app #'app?] - [_ (with-syntax ([type type]) - #'(lambda (x) (eq? x 'type)))]))) - (syntax-case x (else) - [(_ ctxt-exp [(type ...) e1 e2 ...] more ...) - (with-syntax (((pred ...) (map predicate #'(type ...)))) - #'(let ((ctxt ctxt-exp)) - (if (or (pred ctxt) ...) - (begin e1 e2 ...) - (context-case ctxt more ...))))] - [(_ ctxt-exp [else e1 e2 ...]) #'(begin e1 e2 ...)] - [(_ ctxt-exp) - #'($oops 'cp0-internal "unexpected context ~s" ctxt-exp)]))) - - (define-syntax convention-case - (lambda (x) - (syntax-case x (else) - [(_ conv-exp [(key ...) e1 e2 ...] more ...) - #'(let ((conv conv-exp)) - (if (or (eq? conv 'key) ...) - (begin e1 e2 ...) - (convention-case conv more ...)))] - [(_ conv-exp [else e1 e2 ...]) #'(begin e1 e2 ...)] - [(_ conv-exp) - #'($oops 'cp0-internal "unexpected app convention ~s" conv-exp)]))) - - - ;;; operands - - (define-record-type operand - (fields - (immutable exp) - (immutable env) - (immutable wd) - (immutable moi) - (mutable name) - (mutable score) - (mutable pending) - (mutable opending) - (mutable value) - (mutable singly-referenced-score) - (mutable lifted)) - (nongenerative) - (protocol - (lambda (new) - (lambda (exp env wd moi) - (new exp env wd moi #f 0 0 0 #f #f #f))))) - - (define-record-type lifted - (fields (immutable seq?) (immutable ids) (immutable vals)) - (nongenerative) - (sealed #t)) - - (define build-operands - (lambda (args env wd moi) - (map (lambda (x) (make-operand x env wd moi)) args))) - - (define build-cooked-opnd - (lambda (e) - (let ([o (make-operand #f #f #f #f)]) - (operand-value-set! o e) - o))) - - ;;; cycle detection - - (define inner-cyclic? - (lambda (opnd) - (when (fx> (operand-pending opnd) 0) - ; seed outer pending flag if cycle is detected - (operand-opending-set! opnd 1)) - (fx> (operand-pending opnd) inner-unroll-limit))) - - (define outer-cyclic? - (lambda (opnd) - (fx> (operand-opending opnd) outer-unroll-limit))) - - (define-threaded opending-list '()) - - (define unwind-pending! - (lambda (oplist) - (do ((ls opending-list (cdr ls))) - ((eq? ls oplist) (set! opending-list ls)) - (operand-opending-set! (car ls) - (fx- (operand-opending (car ls)) 1))))) - - (define-syntax pending-protect - ; we don't need to maintain list of inner pending operands to be - ; unwound by bug-out, since we never abort a visit to an operand - ; that we actually need. in other words, when we bug out of an - ; inlining attempt, we abort the visiting of only operands created - ; during the inlining attempt. - (syntax-rules () - ((_ opnd e1 e2 ...) - (let ((o opnd)) - (operand-pending-set! o (fx+ (operand-pending o) 1)) - (let ((t (begin e1 e2 ...))) - (operand-pending-set! o (fx- (operand-pending o) 1)) - t))))) - - (define-syntax opending-protect - ; dynamic wind could be used but is much slower - (syntax-rules () - ((_ opnd e1 e2 ...) - (let ((o opnd)) - (operand-opending-set! o (fx+ (operand-opending o) 1)) - (set! opending-list (cons opnd opending-list)) - (let ((t (begin e1 e2 ...))) - (set! opending-list (cdr opending-list)) - (operand-opending-set! o (fx- (operand-opending o) 1)) - t))))) - - ;;; scorers - - (define-record-type scorer - (fields (mutable limit) (immutable ctxt) (immutable k) (immutable oplist)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (limit ctxt k) - (new limit ctxt k opending-list))))) - - (define new-scorer - ; with no arguments, create a passive scorer with a high limit that - ; (we assume) won't overflow; this allows us to keep a tally without - ; ever bugging out. with two arguments n and k, create a scorer that - ; will bug out to if bumped n times. - (case-lambda - [() (make-scorer (most-positive-fixnum) #f oops-k)] - [(n ctxt k) (make-scorer n ctxt k)])) - - (define oops-k - (list (lambda (x) - ($oops 'compiler-internal "bug out from passive scorer")))) - - (define scorer-score - ; assuming we'll ask for score only of passive scorers - (lambda (sc) - (- (most-positive-fixnum) (scorer-limit sc)))) - - (define passive-scorer? - (lambda (sc) - (eq? (scorer-k sc) oops-k))) - - (define new-watchdog - (case-lambda - [() (make-scorer (most-positive-fixnum) #f oops-k)] - [(wd ctxt k) - ; create a new watchdog only if the old one isn't alert - (if (passive-scorer? wd) - (make-scorer effort-limit ctxt k) - wd)])) - - (define bump - (lambda (sc amount) - (let ((n (fx- (scorer-limit sc) amount))) - (scorer-limit-set! sc n) - (when (fx< n 0) (bug-out! sc))))) - - (define bug-out! - (lambda (sc) - (reset-integrated! (scorer-ctxt sc)) - (unwind-pending! (scorer-oplist sc)) - ((scorer-k sc) #f))) - - (define reset-integrated! - (lambda (ctxt) - (app-used-set! ctxt #f) - (let ((ctxt (app-ctxt ctxt))) - (when (app? ctxt) (reset-integrated! ctxt))))) - - ;;; visiting operands - - (define visit-operand! - (lambda (opnd ctxt) - ; NB: commonize with np-recognize-let - (define extract-profile-forms - (lambda (e) - (define seqs-and-profiles? - (lambda (e) - (nanopass-case (Lsrc Expr) e - [(profile ,src) #t] - [(seq ,e1 ,e2) (and (seqs-and-profiles? e1) (seqs-and-profiles? e2))] - [else #f]))) - (if (eq? ($compile-profile) 'source) - (let loop ([e e] [eprof #f]) - (nanopass-case (Lsrc Expr) e - [(seq ,e1 ,e2) - (guard (seqs-and-profiles? e1)) - (loop e2 (if eprof `(seq ,eprof ,e1) e1))] - [else (values e eprof)])) - (values e #f)))) - ; set up to assimilate nested let/letrec/letrec* bindings. - ; lifting job is completed by cp0-call or letrec/letrec* - (define (split-value e) - (nanopass-case (Lsrc Expr) e - [(call ,preinfo0 (case-lambda ,preinfo1 (clause (,x* ...) ,interface ,body)) ,e* ...) - (guard (fx= interface (length e*))) - (cond - ; when lifting all assimilated let bindings, require each RHS to be - ; simple, since they are treated as letrec/letrec* bindings, which does - ; not preserve let semantics wrt continuation grabs in RHS expressions. - ; further, require each RHS to be pure unless the body is pure, since it's - ; unsound to split apart two things that can observe a side effect or two - ; allocation operations that can be separated by a continuation grab. - [(if (ivory? body) (andmap simple/profile? e*) (andmap ivory? e*)) - ; associate each lhs with cooked operand for corresponding rhs. make-record-constructor-descriptor, - ; at least, counts on this to allow protocols to be inlined. - (for-each (lambda (x e) (prelex-operand-set! x (build-cooked-opnd e)) (operand-name-set! opnd (prelex-name x))) x* e*) - (values (make-lifted #f x* e*) body)] - ; okay, so we don't pass that test. if body and e* are simple, we can - ; still lift by making a binding for body and requesting letrec* semantics. - ; that way, we aren't splitting e* and body. we still can't lift anything - ; that might capture a continuation, though it's tricky to come up with - ; example that breaks. - ; we don't presently have any justification (benchmark results or expand/optimize - ; mats) that establish the benefit of this, but might want to revisit/refine at - ; some point. - #;[(and (simple? body) (andmap simple? e*)) - (let ([t (cp0-make-temp #f)]) ; mark was-referenced? - (let ([x* (append x* (list t))] [e* (append e* (list body))]) - (for-each (lambda (x e) (prelex-operand-set! x (build-cooked-opnd e)) (operand-name-set! opnd (prelex-name x))) x* e*) - (values (make-lifted #t x* e*) (build-ref t))))] - ; otherwise lift out only bindings with unasigned lhs and ivory rhs - ; we don't presently have any justification (benchmark results or expand/optimize - ; mats) that establish the benefit of this, but might want to revisit/refine at - ; some point. - #;[(ormap (lambda (x e) (and (not (prelex-assigned x)) (ivory? e))) x* e*) - (let loop ([x* x*] [e* e*] [rx* '()] [re* '()] [rlx* '()] [rle* '()]) - (if (null? x*) - (values (make-lifted #f (reverse rlx*) (reverse rle*)) - (build-let (reverse rx*) (reverse re*) body)) - (let ([x (car x*)] [e (car e*)]) - (if (and (not (prelex-assigned x)) (ivory? e)) - (begin - ; associate each lhs with cooked operand for corresponding rhs. see note above. - (prelex-operand-set! x (build-cooked-opnd e)) - (operand-name-set! opnd (prelex-name x)) - (loop (cdr x*) (cdr e*) rx* re* (cons x rlx*) (cons e rle*))) - (loop (cdr x*) (cdr e*) (cons x rx*) (cons e re*) rlx* rle*)))))] - [else (values #f e)])] - ; for assimilated letrec/letrec* bindings, require each RHS to be - ; pure OR body to be pure, since we can't separate non-pure - ; RHS and body expressions - [(letrec ([,x* ,e*] ...) ,body) - (guard (or (ivory? body) (andmap ivory? e*))) - ; associate each lhs with cooked operand for corresponding rhs. see note above. - (for-each (lambda (x e) (prelex-operand-set! x (build-cooked-opnd e)) (operand-name-set! opnd (prelex-name x))) x* e*) - (values (make-lifted #f x* e*) body)] - ; force the issue by creating an extra tmp for body - ; we don't presently have any justification (benchmark results or expand/optimize - ; mats) that establish the benefit of this, but might want to revisit/refine at - ; some point. - #;[(letrec ([,x* ,e*] ...) ,body) - (let ([x (cp0-make-temp #f)]) - (let ([x* (append x* (list x))] [e* (append e* (list body))]) - (for-each (lambda (x e) (prelex-operand-set! x (build-cooked-opnd e)) (operand-name-set! opnd (prelex-name x))) x* e*) - (values (make-lifted #t x* e*) (build-ref x))))] - [(letrec* ([,x* ,e*] ...) ,body) - (guard (or (ivory? body) (andmap ivory? e*))) - ; associate each lhs with cooked operand for corresponding rhs. see note above. - (for-each (lambda (x e) (prelex-operand-set! x (build-cooked-opnd e)) (operand-name-set! opnd (prelex-name x))) x* e*) - (values (make-lifted #t x* e*) body)] - ; force the issue by creating an extra tmp for body. - ; we don't presently have any justification (benchmark results or expand/optimize - ; mats) that establish the benefit of this, but might want to revisit/refine at - ; some point. - #;[(letrec* ([,x* ,e*] ...) ,body) - (let ([x (cp0-make-temp #f)]) - (let ([x* (append x* (list x))] [e* (append e* (list body))]) - (for-each (lambda (x e) (prelex-operand-set! x (build-cooked-opnd e)) (operand-name-set! opnd (prelex-name x))) x* e*) - (values (make-lifted #t x* e*) (build-ref x))))] - ; we can lift arbitrary subforms of record forms if we also lift - ; a binding for the record form itself. there's no worry about - ; continuation captures: if rtd-expr or e* capture a continuation, - ; invoking the continuation to return from a rhs is no worse than - ; invoking the continuation to build the record and then return - ; from a rhs. - [(record ,rtd ,rtd-expr ,e* ...) - (let-values ([(liftmt* liftme* e*) - (let ([fld* (rtd-flds rtd)]) - (let f ([e* e*] [fld* fld*]) - (if (null? e*) - (values '() '() '()) - (let ([e (car e*)]) - (let-values ([(liftmt* liftme* e*) (f (cdr e*) (cdr fld*))]) - (if (nanopass-case (Lsrc Expr) e - [(ref ,maybe-src ,x) #f] - [(quote ,d) #f] - [,pr #f] - [else (not (fld-mutable? (car fld*)))]) - (let ([t (cp0-make-temp #f)]) - (values (cons t liftmt*) (cons e liftme*) (cons (build-ref t) e*))) - (values liftmt* liftme* (cons e e*))))))))]) - (let ([e `(record ,rtd ,rtd-expr ,e* ...)]) - (if (null? liftmt*) - (values #f e) - (let ([x (cp0-make-temp #f)]) - (let ([x* (append liftmt* (list x))] [e* (append liftme* (list e))]) - (for-each (lambda (x e) (prelex-operand-set! x (build-cooked-opnd e)) (operand-name-set! opnd (prelex-name x))) x* e*) - (values (make-lifted #t x* e*) (build-ref x)))))))] - [else (values #f e)])) - (or (operand-value opnd) - (let ([sc (new-scorer)]) - (let ([e0 (pending-protect opnd - (cp0 (operand-exp opnd) ctxt (operand-env opnd) sc (operand-wd opnd) (operand-name opnd) (operand-moi opnd)))]) - (let-values ([(e1 eprof) (extract-profile-forms e0)]) - (with-values (split-value e1) - (lambda (lifted e) - (let ([e (if eprof (make-seq ctxt eprof e) e)]) - (operand-lifted-set! opnd lifted) - (operand-value-set! opnd e) - (operand-score-set! opnd (scorer-score sc)) - e))))))))) - - (define value-visit-operand! - (lambda (opnd) - (visit-operand! opnd 'value))) - - (define test-visit-operand! - (lambda (opnd) - (visit-operand! opnd 'test))) - - (define value-visit-operands! - (lambda (opnds) - (map value-visit-operand! opnds))) - - (define residualize-seq - ; ctxt must be an app context. set used and unused lists in context - (lambda (used unused ctxt) - (safe-assert (fx= (fx+ (length used) (length unused)) (length (app-opnds ctxt)))) - (app-used-set! ctxt used) - (app-unused-set! ctxt unused))) - - (define residualize-call-opnds - (lambda (used unused e ctxt sc) - (let f ((used used) (n 0)) - (if (null? used) - (let f ((unused unused) (n n) (todo '())) - (if (null? unused) - (begin - (bump sc n) - (let f ((todo todo) (e e)) - (if (null? todo) - e - (f (cdr todo) - (make-seq ctxt - (let ((opnd (car todo))) - (cp0 (operand-exp opnd) 'effect (operand-env opnd) - sc (operand-wd opnd) (operand-name opnd) (operand-moi opnd))) - e))))) - (let ((opnd (car unused))) - (let ((e (operand-value opnd))) - (if e - (if (simple? e) - (if (operand-singly-referenced-score opnd) - ; singly-referenced integration attempt in copy2 succeeded - (f (cdr unused) (fx+ (operand-singly-referenced-score opnd) n) todo) - (f (cdr unused) n todo)) - ; overscoring bug: make-seq may drop e2 if e is (seq e1 e2), but - ; we add in the entire score here - ; if singly-referenced integration attempt in copy2 succeeded, but - ; value isn't simple, we also pay the whole price - (make-seq ctxt e (f (cdr unused) (fx+ n (operand-score opnd)) todo))) - (if (operand-singly-referenced-score opnd) - ; singly-referenced integration attempt in ref-case of cp0 succeeded - (f (cdr unused) (fx+ (operand-singly-referenced-score opnd) n) todo) - (f (cdr unused) n (cons opnd todo)))))))) - (f (cdr used) (fx+ (operand-score (car used)) n)))))) - - (define cp0-constant? - (case-lambda - [(x) - (nanopass-case (Lsrc Expr) x - [(quote ,d) #t] - [else #f])] - [(pred? x) - (nanopass-case (Lsrc Expr) x - [(quote ,d) (pred? d)] - [else #f])])) - - (define-who cp0-datum - (lambda (x) - (nanopass-case (Lsrc Expr) x - [(quote ,d) d] - [else (sorry! who "~s is not a constant" x)]))) - - (define preinfo-call->preinfo-lambda - (lambda (preinfo) - (make-preinfo-lambda (preinfo-src preinfo) (preinfo-sexpr preinfo)))) - - (define build-quote - (lambda (d) - `(quote ,d))) - - (define build-ref - (lambda (x) - `(ref #f ,x))) - - (module (build-primcall) - (define $build-primcall - (case-lambda - [(primref args) ($build-primcall (make-preinfo) primref args)] - [(preinfo primref args) `(call ,preinfo ,primref ,args ...)])) - (define-syntax build-primcall - (syntax-rules () - [(_ level name args) ($build-primcall (lookup-primref level name) args)] - [(_ preinfo level name args) ($build-primcall preinfo (lookup-primref level name) args)]))) - - (define build-lambda - (case-lambda - [(ids body) (build-lambda (make-preinfo-lambda) ids body)] - [(preinfo ids body) `(case-lambda ,preinfo (clause (,ids ...) ,(length ids) ,body))])) - - (define build-case-lambda - (case-lambda - [(clause*) (build-case-lambda (make-preinfo-lambda) clause*)] - [(preinfo clause*) - `(case-lambda ,preinfo - ,(map (lambda (clause) - (with-output-language (Lsrc CaseLambdaClause) - (let ([x* (car clause)]) - `(clause (,x* ...) ,(length x*) ,(cadr clause))))) - clause*) ...)])) - - ; build-call is not very cp0-like, since it doesn't enable further - ; optimization, but it does clean up some silly looking code. - (define build-call - (lambda (preinfo proc args) - (let ([n (length args)]) - (nanopass-case (Lsrc Expr) proc - ; eta reduce ((lambda (x ...) (prim x ...)) e ...) => (prim e ...) - [(case-lambda ,preinfo0 - (clause (,x* ...) ,interface - (call ,preinfo1 ,pr ,e* ...))) - (guard (fx= interface n) (fx= (length e*) n) - (andmap (lambda (x e) - (nanopass-case (Lsrc Expr) e - [(ref ,maybe-src ,x1) (eq? x1 x)] - [else #f])) - x* e*)) - `(call ,preinfo1 ,pr ,args ...)] - [else `(call ,preinfo ,proc ,args ...)])))) - - (define build-let - (case-lambda - [(lambda-preinfo ids exps body) - (build-call (make-preinfo) (build-lambda lambda-preinfo ids body) exps)] - [(ids exps body) (build-call (make-preinfo) (build-lambda ids body) exps)])) - - (define build-named-let - (lambda (name ids exps body) - `(call ,(make-preinfo) - (letrec ([,name ,(build-lambda ids body)]) - (ref #f ,name)) - ,exps ...))) - - (define make-seq - ; ensures that the right subtree of the output seq is not a seq if the - ; second argument is similarly constrained, to facilitate result-exp - (lambda (ctxt e1 e2) - (if (simple? e1) - e2 - (if (and (eq? ctxt 'effect) (simple? e2)) - e1 - (let ([e1 (nanopass-case (Lsrc Expr) e1 - [(seq ,e11 ,e12) - (guard (simple? e12)) - e11] - [else e1])]) - (nanopass-case (Lsrc Expr) e2 - [(seq ,e21 ,e22) `(seq (seq ,e1 ,e21) ,e22)] - [else `(seq ,e1 ,e2)])))))) - - (define make-seq* ; requires at least one operand - (lambda (ctxt e*) - (if (null? (cdr e*)) - (car e*) - (make-seq ctxt (car e*) (make-seq* ctxt (cdr e*)))))) - - (define make-if - (lambda (ctxt sc e1 e2 e3) - (cond - [(record-equal? e2 e3 ctxt) (make-seq ctxt e1 e2)] - [(and (cp0-constant? (lambda (x) (eq? x #f)) e3) - (record-equal? e1 e2 (if (eq? ctxt 'test) 'test 'value)) - (simple? e1)) - e1] - [(nanopass-case (Lsrc Expr) (result-exp e1) - [(if ,e11 ,[result-exp : e12 -> re12] ,[result-exp : e13 -> re13]) - (if (and (cp0-constant? re12) (cp0-constant? re13)) - (let ([d12 (cp0-datum re12)] [d13 (cp0-datum re13)]) - (non-result-exp e1 - (cond - [(and d12 d13) (make-seq ctxt (make-if 'effect sc e11 e12 e13) e2)] - [(not (or d12 d13)) (make-seq ctxt (make-if 'effect sc e11 e12 e13) e3)] - [else (let-values ([(e2 e3) (if d12 (values e2 e3) (values e3 e2))]) - (make-if ctxt sc e11 (non-result-exp e12 e2) (non-result-exp e13 e3)))]))) - #f)] - [else #f])] - [else - (bump sc 1) - `(if ,e1 ,e2 ,e3)]))) - - (define result-exp - (lambda (e) - (nanopass-case (Lsrc Expr) e - [(seq ,e1 ,e2) e2] - [else e]))) - - (define result-exp/indirect-ref - ; useful only when interested in non-propagatable result expressions, e.g., lambda expressions - ; NB: to avoid code duplication, don't residualize the resulting value - (lambda (x) - (let ([x (result-exp x)]) - (or (nanopass-case (Lsrc Expr) x - [(ref ,maybe-src ,x) - (and (not (prelex-was-assigned x)) - (let ([opnd (prelex-operand x)]) - (and opnd - (let ([x (operand-value opnd)]) - (and x (result-exp x))))))] - [else #f]) - x)))) - - (define non-result-exp - (lambda (e body) - (nanopass-case (Lsrc Expr) e - [(seq ,e1 ,e2) `(seq ,e1 ,body)] - [else body]))) - - (define (arity-okay? arity n) - (or (not arity) ; presumably system routine w/no recorded arity - (ormap - (lambda (a) - (or (fx= n a) - (and (fx< a 0) (fx>= n (fx- -1 a))))) - arity))) - - (define okay-to-copy? - (lambda (obj) - ; okay to copy obj if (eq? (faslin (faslout x)) x) => #t or (in the case of numbers and characters) - ; the value of (eq? x x) is unspecified - (or (symbol? obj) - (number? obj) - (char? obj) - (boolean? obj) - (null? obj) - (eqv? obj "") - (eqv? obj ($tc-field 'null-immutable-string ($tc))) - (eqv? obj '#()) - (eqv? obj ($tc-field 'null-immutable-vector ($tc))) - (eqv? obj '#vu8()) - (eqv? obj ($tc-field 'null-immutable-bytevector ($tc))) - (eqv? obj '#vfx()) - (eqv? obj ($tc-field 'null-immutable-fxvector ($tc))) - (eq? obj (void)) - (eof-object? obj) - (bwp-object? obj) - (eq? obj '#6=#6#) - ($unbound-object? obj) - (record-type-descriptor? obj)))) - - (define externally-inlinable? - (lambda (clause) - (call/cc - (lambda (exit) - (define bump! - (let ([size 0]) - (lambda () - (set! size (fx+ size 1)) - (when (fx> size score-limit) (exit #f))))) - (define (ids->do-clause ids) - (rec do-clause - (lambda (clause) - (define (ids->do-expr ids) - (rec do-expr - (lambda (e) - (nanopass-case (Lsrc Expr) e - [(quote ,d) (if (okay-to-copy? d) (bump!) (exit #f))] - [(moi) (bump!)] - [,pr (bump!)] - [(ref ,maybe-src ,x) (unless (memq x ids) (exit #f)) (bump!)] - [(seq ,[do-expr : e1] ,[do-expr : e2]) (void)] - [(if ,[do-expr : e1] ,[do-expr : e2] ,[do-expr : e3]) (void)] - [(set! ,maybe-src ,x ,e) - (unless (memq x ids) (exit #f)) - (bump!) - (do-expr e)] - [(call ,preinfo ,e ,e* ...) - ; reject calls to gensyms, since they might represent library exports, - ; and we have no way to set up the required invoke dependencies - (when (and (nanopass-case (Lsrc Expr) e - [,pr (eq? (primref-name pr) '$top-level-value)] - [else #f]) - (= (length e*) 1) - (cp0-constant? gensym? (car e*))) - (exit #f)) - (bump!) - (do-expr e) - (for-each do-expr e*)] - [(case-lambda ,preinfo ,cl* ...) - (bump!) - (for-each (ids->do-clause ids) cl*)] - [(letrec ([,x* ,e*] ...) ,body) - (bump!) - (safe-assert (andmap (lambda (x) (not (prelex-operand x))) x*)) - (let ([do-expr (ids->do-expr (append x* ids))]) - (for-each do-expr e*) - (do-expr body))] - [(letrec* ([,x* ,e*] ...) ,body) - (bump!) - (safe-assert (andmap (lambda (x) (not (prelex-operand x))) x*)) - (let ([do-expr (ids->do-expr (append x* ids))]) - (for-each do-expr e*) - (do-expr body))] - [(record-type ,rtd ,[do-expr : e]) (void)] - [(record-cd ,rcd ,rtd-expr ,[do-expr : e]) (void)] - [(record-ref ,rtd ,type ,index ,[do-expr : e]) (bump!)] - [(record-set! ,rtd ,type ,index ,[do-expr : e1] ,[do-expr : e2]) (bump!)] - [(record ,rtd ,[do-expr : rtd-expr] ,[do-expr : e*] ...) (bump!)] - [(immutable-list (,[e*] ...) ,[e]) (void)] - [(pariah) (void)] - [(profile ,src) (void)] - [else (exit #f)])))) - (nanopass-case (Lsrc CaseLambdaClause) clause - [(clause (,x* ...) ,interface ,body) - (safe-assert (andmap (lambda (x) (not (prelex-operand x))) x*)) - ((ids->do-expr (append x* ids)) body)])))) - ((ids->do-clause '()) clause) - #t)))) - - (module (pure? ivory? simple? simple/profile? boolean-valued?) - (define-syntax make-$memoize - (syntax-rules () - [(_ flag-known flag) - (lambda (e pred?) - (let ([a (eq-hashtable-cell cp0-info-hashtable e 0)]) - (let ([flags (cdr a)]) - (if (all-set? (cp0-info-mask flag-known) flags) - (all-set? (cp0-info-mask flag) flags) - (let ([bool (pred?)]) - (set-cdr! a (set-flags (if bool (cp0-info-mask flag-known flag) (cp0-info-mask flag-known)) flags)) - bool)))))])) - - (define-syntax with-memoize - (lambda (x) - (syntax-case x () - [(k (flag-known flag) ?e e* ...) - (with-implicit (k memoize) - #'(let ([$memoize (make-$memoize flag-known flag)] [e ?e]) - (define-syntax memoize - (syntax-rules () - [(_ e1 e2 (... ...)) ($memoize e (lambda () e1 e2 (... ...)))])) - e* ...))]))) - - (define-who pure? - ; does not cause or observe any effects, capture or invoke a continuation, - ; or allocate mutable data structures. might contain profile forms, so - ; pure forms cannot necessarily be discarded. mostly used to determine if - ; we can move an expression. differs from ivory in that restricted primitives - ; and record refs are not considered pur at optimize-level 3, which allows - ; pure expressions to be moved in more circumstances. - (lambda (e) - (with-memoize (pure-known pure) e - ; 2015/02/11 sorted by frequency - (nanopass-case (Lsrc Expr) e - [(ref ,maybe-src ,x) (not (prelex-was-assigned x))] - [(call ,preinfo ,e ,e* ...) - (let () - (define pure-call? - (lambda (maybe-e e) - (nanopass-case (Lsrc Expr) e - [,pr - (and (let ([flags (primref-flags e)]) - (all-set? (prim-mask (or pure unrestricted)) flags)) - (arity-okay? (primref-arity e) (length e*)) - (memoize (and (or (not maybe-e) (pure? maybe-e)) (andmap pure? e*))))] - [(case-lambda ,preinfo1 (clause (,x* ...) ,interface ,body)) - (guard (fx= interface (length e*))) - (memoize (and (or (not maybe-e) (pure? maybe-e)) (pure? body) (andmap pure? e*)))] - [else #f]))) - (nanopass-case (Lsrc Expr) e - [(seq ,e1 ,e2) (pure-call? e1 e2)] - [else (pure-call? #f e)]))] - [(quote ,d) #t] - [,pr (all-set? (prim-mask proc) (primref-flags pr))] - [(case-lambda ,preinfo ,cl* ...) #t] - [(if ,e1 ,e2 ,e3) (memoize (and (pure? e1) (pure? e2) (pure? e3)))] - [(seq ,e1 ,e2) (memoize (and (pure? e1) (pure? e2)))] - [(record-ref ,rtd ,type ,index ,e) #f] - [(record-set! ,rtd ,type ,index ,e1 ,e2) #f] - [(record ,rtd ,rtd-expr ,e* ...) - (and (andmap (lambda (fld) - (and (not (fld-mutable? fld)) - (eq? (filter-foreign-type (fld-type fld)) 'scheme-object))) - (rtd-flds rtd)) - (memoize (and (pure? rtd-expr) (andmap pure? e*))))] - [(set! ,maybe-src ,x ,e) #f] - [(record-cd ,rcd ,rtd-expr ,e) (memoize (pure? e))] - [(letrec ([,x* ,e*] ...) ,body) (memoize (and (andmap pure? e*) (pure? body)))] - [(record-type ,rtd ,e) (memoize (pure? e))] - [(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) (memoize (pure? e))] - [(letrec* ([,x* ,e*] ...) ,body) (memoize (and (andmap pure? e*) (pure? body)))] - [(immutable-list (,e* ...) ,e) (memoize (and (andmap pure? e*) (pure? e)))] - [(profile ,src) #t] - [(cte-optimization-loc ,box ,e) (memoize (pure? e))] - [(moi) #t] - [(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type) (memoize (pure? e))] - [(pariah) #t] - [else ($oops who "unrecognized record ~s" e)])))) - - (define-who ivory? ; 99.44% pure - ; does not cause or observe any effects, capture or invoke a continuation, - ; or allocate mutable data structures. might contain profile forms, so - ; ivory forms cannot necessarily be discarded. mostly used to determine if - ; we can move an expression. differs from pure in that restricted primitives - ; and record refs are considered ivory at optimize-level 3. - (lambda (e) - (with-memoize (ivory-known ivory) e - ; 2015/02/11 sorted by frequency - (nanopass-case (Lsrc Expr) e - [(ref ,maybe-src ,x) (not (prelex-was-assigned x))] - [(call ,preinfo ,e ,e* ...) - (let () - (define ivory-call? - (lambda (maybe-e e) - (nanopass-case (Lsrc Expr) e - [,pr - (and (let ([flags (primref-flags e)]) - ; here ivory? differs from pure? - (if (all-set? (prim-mask unsafe) flags) - (all-set? (prim-mask pure) flags) - (all-set? (prim-mask (or pure unrestricted)) flags))) - (arity-okay? (primref-arity e) (length e*)) - (memoize (and (or (not maybe-e) (ivory? maybe-e)) (andmap ivory? e*))))] - [(case-lambda ,preinfo1 (clause (,x* ...) ,interface ,body)) - (guard (fx= interface (length e*))) - (memoize (and (or (not maybe-e) (ivory? maybe-e)) (ivory? body) (andmap ivory? e*)))] - [else #f]))) - (nanopass-case (Lsrc Expr) e - [(seq ,e1 ,e2) (ivory-call? e1 e2)] - [else (ivory-call? #f e)]))] - [(quote ,d) #t] - [,pr (all-set? (prim-mask proc) (primref-flags pr))] - [(case-lambda ,preinfo ,cl* ...) #t] - [(if ,e1 ,e2 ,e3) (memoize (and (ivory? e1) (ivory? e2) (ivory? e3)))] - [(seq ,e1 ,e2) (memoize (and (ivory? e1) (ivory? e2)))] - [(record-ref ,rtd ,type ,index ,e) - ; here ivory? differs from pure? - (and (not (fld-mutable? (list-ref (rtd-flds rtd) index))) - (memoize (ivory? e)))] - [(record-set! ,rtd ,type ,index ,e1 ,e2) #f] - [(record ,rtd ,rtd-expr ,e* ...) - ; here ivory? differs from pure? - (and (andmap (lambda (fld) (not (fld-mutable? fld))) (rtd-flds rtd)) - (memoize (and (ivory? rtd-expr) (andmap ivory? e*))))] - [(set! ,maybe-src ,x ,e) #f] - [(record-cd ,rcd ,rtd-expr ,e) (memoize (ivory? e))] - [(letrec ([,x* ,e*] ...) ,body) (memoize (and (andmap ivory? e*) (ivory? body)))] - [(record-type ,rtd ,e) (memoize (ivory? e))] - [(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) (memoize (ivory? e))] - [(letrec* ([,x* ,e*] ...) ,body) (memoize (and (andmap ivory? e*) (ivory? body)))] - [(immutable-list (,e* ...) ,e) (memoize (and (andmap ivory? e*) (ivory? e)))] - [(profile ,src) #t] - [(cte-optimization-loc ,box ,e) (memoize (ivory? e))] - [(moi) #t] - [(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type) (memoize (ivory? e))] - [(pariah) #t] - [else ($oops who "unrecognized record ~s" e)])))) - - (define-who simple? - (lambda (e) - (with-memoize (simple-known simple) e - ; does not cause any effects or capture or invoke a continuation, and does not - ; contain profile forms, but might observe effects or allocate mutable data - ; structures. ; mostly used to determine if we can discard an expression. - ; 2015/02/11 sorted by frequency - (nanopass-case (Lsrc Expr) e - ; might be nice to have an ignorem style syntax for the nanopass-case (and passes) - [(quote ,d) #t] - [(call ,preinfo ,e ,e* ...) - (nanopass-case (Lsrc Expr) e - [,pr (let ([flags (primref-flags pr)]) - (and (if (all-set? (prim-mask unsafe) flags) - (all-set? (prim-mask discard) flags) - (all-set? (prim-mask (or discard unrestricted)) flags)) - (arity-okay? (primref-arity pr) (length e*)) - (memoize (andmap simple? e*))))] - [(case-lambda ,preinfo1 (clause (,x* ...) ,interface ,body)) - (guard (fx= interface (length e*))) - (memoize (and (simple? body) (andmap simple? e*)))] - [else #f])] - [(ref ,maybe-src ,x) #t] - [(case-lambda ,preinfo ,cl* ...) #t] - [(if ,e1 ,e2 ,e3) (memoize (and (simple? e1) (simple? e2) (simple? e3)))] - [(seq ,e1 ,e2) (memoize (and (simple? e1) (simple? e2)))] - [(set! ,maybe-src ,x ,e) #f] - [(immutable-list (,e* ...) ,e) (memoize (and (andmap simple? e*) (simple? e)))] - [(letrec ([,x* ,e*] ...) ,body) (memoize (and (andmap simple? e*) (simple? body)))] - [(letrec* ([,x* ,e*] ...) ,body) (memoize (and (andmap simple? e*) (simple? body)))] - [,pr #t] - [(record-cd ,rcd ,rtd-expr ,e) (memoize (simple? e))] - [(record-ref ,rtd ,type ,index ,e) (memoize (simple? e))] - [(record-set! ,rtd ,type ,index ,e1 ,e2) #f] - [(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) (memoize (simple? e))] - [(record-type ,rtd ,e) (memoize (simple? e))] - [(record ,rtd ,rtd-expr ,e* ...) (memoize (and (simple? rtd-expr) (andmap simple? e*)))] - [(pariah) #f] - [(profile ,src) #f] - [(cte-optimization-loc ,box ,e) (memoize (simple? e))] - [(moi) #t] - [(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type) (memoize (simple? e))] - [else ($oops who "unrecognized record ~s" e)])))) - - (define-who simple/profile? - ; like simple? but allows profile forms. used for lifting bindings. - (lambda (e) - (with-memoize (simple-known simple) e - ; does not cause any effects or capture or invoke a continuation, and does not - ; contain profile forms, but might observe effects or allocate mutable data - ; structures. ; mostly used to determine if we can discard an expression. - ; 2015/02/11 sorted by frequency - (nanopass-case (Lsrc Expr) e - ; might be nice to have an ignorem style syntax for the nanopass-case (and passes) - [(quote ,d) #t] - [(call ,preinfo ,e ,e* ...) - (nanopass-case (Lsrc Expr) e - [,pr (let ([flags (primref-flags pr)]) - (and (if (all-set? (prim-mask unsafe) flags) - (all-set? (prim-mask discard) flags) - (all-set? (prim-mask (or discard unrestricted)) flags)) - (arity-okay? (primref-arity pr) (length e*)) - (memoize (andmap simple/profile? e*))))] - [(case-lambda ,preinfo1 (clause (,x* ...) ,interface ,body)) - (guard (fx= interface (length e*))) - (memoize (and (simple/profile? body) (andmap simple/profile? e*)))] - [else #f])] - [(ref ,maybe-src ,x) #t] - [(case-lambda ,preinfo ,cl* ...) #t] - [(if ,e1 ,e2 ,e3) (memoize (and (simple/profile? e1) (simple/profile? e2) (simple/profile? e3)))] - [(seq ,e1 ,e2) (memoize (and (simple/profile? e1) (simple/profile? e2)))] - [(set! ,maybe-src ,x ,e) #f] - [(immutable-list (,e* ...) ,e) (memoize (and (andmap simple/profile? e*) (simple/profile? e)))] - [(letrec ([,x* ,e*] ...) ,body) (memoize (and (andmap simple/profile? e*) (simple/profile? body)))] - [(letrec* ([,x* ,e*] ...) ,body) (memoize (and (andmap simple/profile? e*) (simple/profile? body)))] - [,pr #t] - [(record-cd ,rcd ,rtd-expr ,e) (memoize (simple/profile? e))] - [(record-ref ,rtd ,type ,index ,e) (memoize (simple/profile? e))] - [(record-set! ,rtd ,type ,index ,e1 ,e2) #f] - [(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) (memoize (simple/profile? e))] - [(record-type ,rtd ,e) (memoize (simple/profile? e))] - [(record ,rtd ,rtd-expr ,e* ...) (memoize (and (simple/profile? rtd-expr) (andmap simple/profile? e*)))] - [(pariah) #t] - [(profile ,src) #t] - [(cte-optimization-loc ,box ,e) (memoize (simple/profile? e))] - [(moi) #t] - [(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type) (memoize (simple/profile? e))] - [else ($oops who "unrecognized record ~s" e)])))) - - (define-who boolean-valued? - (lambda (e) - (with-memoize (boolean-valued-known boolean-valued) e - ; 2015/02/11 sorted by frequency - (nanopass-case (Lsrc Expr) e - [(call ,preinfo ,e ,e* ...) - (nanopass-case (Lsrc Expr) (result-exp e) - [,pr (all-set? (prim-mask boolean-valued) (primref-flags pr))] - [(case-lambda ,preinfo1 (clause (,x* ...) ,interface ,body)) - (guard (fx= interface (length e*))) - (memoize (boolean-valued? body))] - [else #f])] - [(if ,e0 ,e1 ,e2) (memoize (and (boolean-valued? e1) (boolean-valued? e2)))] - [(record-ref ,rtd ,type ,index ,e) (eq? type 'boolean)] - [(ref ,maybe-src ,x) #f] - [(quote ,d) (boolean? d)] - [(seq ,e1 ,e2) (memoize (boolean-valued? e2))] - [(case-lambda ,preinfo ,cl* ...) #f] - [(letrec* ([,x* ,e*] ...) ,body) (memoize (boolean-valued? body))] - [(letrec ([,x* ,e*] ...) ,body) (memoize (boolean-valued? body))] - [,pr #f] - [(record-type ,rtd ,e) #f] - [(record-cd ,rcd ,rtd-expr ,e) #f] - [(record-set! ,rtd ,type ,index ,e1 ,e2) #f] - [(record ,rtd ,rtd-expr ,e* ...) #f] - [(immutable-list (,e* ...) ,e) #f] - [(cte-optimization-loc ,box ,e) (memoize (boolean-valued? e))] - [(profile ,src) #f] - [(set! ,maybe-src ,x ,e) #f] - [(moi) #f] - [(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) #f] - [(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type) #f] - [(pariah) #f] - [else ($oops who "unrecognized record ~s" e)]))))) - - (define find-call-lambda-clause - (lambda (exp opnds) - (define rest-clause - ; ((lambda (x1 ... xn . xr) e) a1 ... am) m >= n - ; => ((lambda (x1 ... xn tn+1 ... tm) - ; (let ((xr (list tn+1 ... tm))) - ; e)) - ; a1 ... am) - (lambda (ids opnds body) - (with-values - (let split ((ids ids) (opnds opnds)) - (if (null? (cdr ids)) - (let ((temps (map (lambda (x) (cp0-make-temp #f)) opnds))) - (values temps temps (car ids))) - (with-values (split (cdr ids) (cdr opnds)) - (lambda (new-ids temps rest-id) - (values (cons (car ids) new-ids) temps rest-id))))) - (lambda (ids temps rest-id) - (values ids - (build-let (list rest-id) - (list - (let* ([tref* (map build-ref temps)] - [e (build-primcall 3 'list tref*)]) - ; immutable-value presently set only by record-constructor - (if (prelex-immutable-value rest-id) - `(immutable-list (,tref* ...) ,e) - e))) - body)))))) - (nanopass-case (Lsrc Expr) exp - [(case-lambda ,preinfo ,cl* ...) - (let ((n (length opnds))) - (let find-clause ([cl* cl*]) - (if (null? cl*) - (values) - (nanopass-case (Lsrc CaseLambdaClause) (car cl*) - [(clause (,x* ...) ,interface ,body) - (cond - [(fx= interface n) (values x* body)] - [(and (fx< interface 0) - (fx>= n (fx- -1 interface))) - (rest-clause x* opnds body)] - [else (find-clause (cdr cl*))])]))))]))) - - (define find-apply-lambda-clause - (lambda (exp opnds) - (define apply-clause - ; (apply (lambda (x1 ... xn) e) a1 ... am ar) m <= n - ; => ((lambda (x1 ... xm t) - ; (let ((xm+1 (car t)) (t (cdr t))) - ; ... - ; (let ((xn-1 (car t)) (t (cdr t))) - ; (let ((xn (car t))) - ; e)))) - ; a1 ... am ar) - ; we insist on m <= n to simplify the code below. since this - ; optimization is performed only when optimize-level is 3, we - ; don't otherwise concern ourselves with argument-count checks - (lambda (ids opnds body) - (with-values - (let split ([ids ids] [opnds opnds]) - (if (null? (cdr opnds)) - (let ([t (cp0-make-temp #f)]) - (values (list t) t ids)) - (with-values (split (cdr ids) (cdr opnds)) - (lambda (new-ids t more-ids) - (values (cons (car ids) new-ids) t more-ids))))) - (lambda (ids t more-ids) - (values ids - (if (null? more-ids) - body - (let f ([ids more-ids] [t t]) - (let ([tref (list (build-ref t))]) - (if (null? (cdr ids)) - (build-let ids (list (build-primcall 3 'car tref)) body) - (begin - (set-prelex-multiply-referenced! t #t) - (let ([t (cp0-make-temp #f)]) - (build-let (list (car ids) t) - (list - (build-primcall 3 'car tref) - (build-primcall 3 'cdr tref)) - (f (cdr ids) t))))))))))))) - (nanopass-case (Lsrc Expr) exp - [(case-lambda ,preinfo ,cl* ...) - (let ([n (length opnds)]) - (cond - [(fx= (length cl*) 1) - (nanopass-case (Lsrc CaseLambdaClause) (car cl*) - [(clause (,x* ...) ,interface ,body) - (if (fx>= interface (fx- (length opnds) 1)) - (apply-clause x* opnds body) - (values))])] - [else (values)]))]))) - - (define find-lambda-clause - (lambda (exp ctxt) - (convention-case (app-convention ctxt) - [(call) (find-call-lambda-clause exp (app-opnds ctxt))] - [(apply2) (values)] - [(apply3) (find-apply-lambda-clause exp (app-opnds ctxt))]))) - - (define letify - (case-lambda - [(lambda-preinfo id* ctxt body) (letify lambda-preinfo id* ctxt '() body)] - [(lambda-preinfo id* ctxt used body) - (if (cp0-constant? body) - ; don't allow conservative referenced flags prevent constant folding - (begin - (residualize-seq '() (app-opnds ctxt) ctxt) - body) - (with-values - (let loop ([id* id*] [opnd* (app-opnds ctxt)] [rid* '()] [rrhs* '()] [used used] [unused '()]) - (if (null? id*) - (begin - (residualize-seq used unused ctxt) - (values (reverse rid*) (reverse rrhs*))) - (let ([id (car id*)] [opnd (car opnd*)]) - (cond - [(prelex-referenced id) - (loop (cdr id*) (cdr opnd*) (cons id rid*) (cons (operand-value opnd) rrhs*) (cons opnd used) unused)] - [(prelex-assigned id) - (loop (cdr id*) (cdr opnd*) (cons id rid*) (cons void-rec rrhs*) used (cons opnd unused))] - [else (loop (cdr id*) (cdr opnd*) rid* rrhs* used (cons opnd unused))])))) - (lambda (id* rhs*) - (cond - [(null? id*) body] - [(and (= (length id*) 1) - (nanopass-case (Lsrc Expr) body - [(ref ,maybe-src ,x) (eq? x (car id*))] - [else #f])) - ; (let ((x e)) x) => e - ; x is clearly not assigned, even if flags are polluted and say it is - (car rhs*)] - ; we drop the RHS of a let binding into the let body when the body expression is a call - ; and we can do so without violating evaluation order of bindings wrt the let body: - ; * for pure, singly referenced bindings, we drop them to the variable reference site - ; * for impure, singly referenced bindings, we drop them only into the most deeply - ; nested call of the let body to ensure the expression is fully evaluated before - ; any body (sub-)expressions - ; when we drop an impure let binding, we require the other bindings at the same level - ; to be unassigned so the location creation for the other bindings remains in the - ; continuation of the impure RHS. - ; - ; dropping let bindings enables pattern-based optimizations downstream that would - ; otherwise be inhibited by the let binding. An example is the optimization in - ; expand-primitives to eliminate unnecessary ftype-pointer creation for nested - ; ftype-ref expressions. dropping let bindings can also reduce register pressure, - ; though it can increase it as well. - ; - ; NB. nested let expressions can result in multiple traversals of the inner let bodies - ; NB. via multiple calls to letify, causing O(n^2) behavior. - [(and (ormap (lambda (x) (not (prelex-multiply-referenced x))) id*) - (let ([all-unassigned? (not (ormap (lambda (x) (prelex-assigned x)) id*))]) - (define drop-let - (lambda (e* build-body) - (let ([alist (map cons id* rhs*)]) - (with-values (let f ([e* e*] [pure-left? #t]) - (if (null? e*) - (values '() #t) - (let ([e (car e*)] [e* (cdr e*)]) - (let ([pure-e? (pure? e)]) ; would cause O(n^2) behavior except pure? caches purity of calls - (let-values ([(e* pure-right?) (f e* (and pure-left? pure-e?))]) - (values - (cons - (nanopass-case (Lsrc Expr) e - [(call ,preinfo ,e2 ,e2* ...) - (let ([e2* (cons e2 e2*)]) - (let-values ([(new-e2* pure-e2*?) (f e2* (and pure-left? pure-right?))]) - (if (andmap eq? new-e2* e2*) - e - (build-call preinfo (car new-e2*) (cdr new-e2*)))))] - [(record-ref ,rtd ,type ,index ,e2) - (let-values ([(new-e2* pure-e2*?) (f (list e2) (and pure-left? pure-right?))]) - (safe-assert (= (length new-e2*) 1)) - (let ([new-e2 (car new-e2*)]) - (if (eq? new-e2 e2) - e - `(record-ref ,rtd ,type ,index ,new-e2))))] - [(record-set! ,rtd ,type ,index ,e21 ,e22) - (let-values ([(new-e2* pure-e2*?) (f (list e21 e22) (and pure-left? pure-right?))]) - (safe-assert (= (length new-e2*) 2)) - (let ([new-e21 (car new-e2*)] [new-e22 (cadr new-e2*)]) - (if (and (eq? new-e21 e21) (eq? new-e22 e22)) - e - `(record-set! ,rtd ,type ,index ,new-e21 ,new-e22))))] - [(record ,rtd ,rtd-expr ,e2* ...) - (let ([e2* (cons rtd-expr e2*)]) - (let-values ([(new-e2* pure-e2*?) (f e2* (and pure-left? pure-right?))]) - (if (andmap eq? new-e2* e2*) - e - `(record ,rtd ,(car new-e2*) ,(cdr new-e2*) ...))))] - [(record-type ,rtd ,e) - (let ([e* (list e)]) - (let-values ([(new-e* pure-e*?) (f e* (and pure-left? pure-right?))]) - (safe-assert (= (length new-e*) 1)) - (if (andmap eq? new-e* e*) - e - `(record-type ,rtd ,(car new-e*)))))] - [(ref ,maybe-src ,x) - (guard (not (prelex-assigned x)) (not (prelex-multiply-referenced x))) - (let ([a (assq x alist)]) - (if a - (let ([rhs (cdr a)]) - (safe-assert rhs) - (if (or (and pure-left? pure-right? all-unassigned?) (pure? rhs)) - (begin (set-cdr! a #f) rhs) - e)) - e))] - [else e]) - e*) - (and pure-e? pure-right?))))))) - (lambda (new-e* . ignore) - (let ([body (if (andmap eq? new-e* e*) body (build-body (car new-e*) (cdr new-e*)))]) - (let ([alist (filter cdr alist)]) - (if (null? alist) body (build-let lambda-preinfo (map car alist) (map cdr alist) body))))))))) - (nanopass-case (Lsrc Expr) body - [(call ,preinfo ,e ,e* ...) - (drop-let (cons e e*) (lambda (e e*) (build-call preinfo e e*)))] - [(record-ref ,rtd ,type ,index ,e) - (drop-let (list e) (lambda (e e*) (safe-assert (null? e*)) `(record-ref ,rtd ,type ,index ,e)))] - [(record-set! ,rtd ,type ,index ,e1 ,e2) - (drop-let (list e1 e2) (lambda (e e*) (safe-assert (= (length e*) 1)) `(record-set! ,rtd ,type ,index ,e ,(car e*))))] - [(record ,rtd ,rtd-expr ,e* ...) - (drop-let (cons rtd-expr e*) (lambda (rtd-expr e*) `(record ,rtd ,rtd-expr ,e* ...)))] - [(record-type ,rtd ,e) - (drop-let (list e) (lambda (e e*) (safe-assert (null? e*)) `(record-type ,rtd ,e)))] - [else #f])))] - [else (build-let lambda-preinfo id* rhs* body)]))))])) - - (define cp0-let - (lambda (lambda-preinfo ids body ctxt env sc wd name moi) - (let ((opnds (app-opnds ctxt))) - (with-extended-env ((env ids) (env ids opnds)) - (letify lambda-preinfo ids ctxt (cp0 body (app-ctxt ctxt) env sc wd (app-name ctxt) moi)))))) - - (define cp0-call - (lambda (preinfo e opnds ctxt env sc wd name moi) - (define (build-wrapper b* body) - (if (null? b*) - body - (let ([b (car b*)] [body (build-wrapper (cdr b*) body)]) - (if (not b) - body - (let ([ids (lifted-ids b)] [vals (lifted-vals b)]) - (for-each (lambda (id) (prelex-operand-set! id #f)) ids) - (if (lifted-seq? b) - `(letrec* ([,ids ,vals] ...) ,body) - `(letrec ([,ids ,vals] ...) ,body))))))) - (let* ((ctxt (make-app opnds ctxt 'call name preinfo)) - (e (cp0 e ctxt env sc wd #f moi))) - (build-wrapper (map operand-lifted opnds) - (if (app-used ctxt) - (residualize-call-opnds (app-used ctxt) (app-unused ctxt) e (app-ctxt ctxt) sc) - (build-call preinfo e - (let f ((opnds opnds) (n 0)) - (if (null? opnds) - (begin (bump sc n) '()) - (let ((opnd (car opnds))) - (let ((e (operand-value opnd))) - (if e - (cons e (f (cdr opnds) (fx+ n (operand-score opnd)))) - ; do rest first to bump for previsited operands first so - ; that we bug out quicker if bug out we do - (let ((rest (f (cdr opnds) n))) - (cons (cp0 (operand-exp opnd) 'value env sc wd #f moi) rest))))))))))))) - - (define cp0-rec-let - (lambda (seq? ids vals body ctxt env sc wd name moi) - (with-extended-env ((env ids) (env ids #f)) - (let ((opnds (build-operands vals env wd moi))) - ; these operands will be cleared by with-extended-env - (for-each (lambda (id opnd) - (prelex-operand-set! id opnd) - (operand-name-set! opnd (prelex-name id))) - ids opnds) - ; for r5rs letrec semantics: prevent copy propagation of references - ; to lhs id if rhs might invoke call/cc - ; not needed r6rs - #;(for-each - (lambda (id val) - (unless (simple? val) - (set-prelex-was-assigned! id #t))) - ids vals) - (let ((body (cp0 body ctxt env sc wd name moi))) - ; visit operands as necessary - (let loop ([ids ids] - [opnds opnds] - [pending-ids '()] - [pending-opnds '()] - [change? #f]) - (if (null? ids) - (when change? (loop pending-ids pending-opnds '() '() #f)) - (let ([id (car ids)] [opnd (car opnds)]) - (if (or (prelex-referenced id) - (not (simple? (operand-exp opnd)))) - (begin - (value-visit-operand! opnd) - (loop (cdr ids) (cdr opnds) pending-ids pending-opnds - (not (null? pending-ids)))) - (loop (cdr ids) (cdr opnds) - (cons id pending-ids) - (cons opnd pending-opnds) - change?))))) - (let loop ([old-ids ids] [opnds opnds] [ids '()] [vals '()] [n 0] [seq? seq?]) - (if (null? old-ids) - (begin - (bump sc n) - (if (or (null? ids) - ; don't allow conservative referenced flags prevent constant folding - (and (cp0-constant? body) (andmap simple? vals))) - body - (if seq? - `(letrec* ([,(reverse ids) ,(reverse vals)] ...) ,body) - `(letrec ([,ids ,vals] ...) ,body)))) - (let ([id (car old-ids)] [opnd (car opnds)]) - (cond - [(operand-value opnd) => - (lambda (val) - ; scoring bug: we don't count size of bindings when we - ; drop the rest of the RHS - (define (f ids vals seq?) - (if (or (prelex-referenced id) (not (simple? val))) - (loop (cdr old-ids) (cdr opnds) (cons id ids) - (cons val vals) (+ n (operand-score opnd)) seq?) - (let ([n (+ (or (operand-singly-referenced-score opnd) 0) n)]) - (if (prelex-assigned id) - (loop (cdr old-ids) (cdr opnds) (cons id ids) - (cons void-rec vals) n seq?) - (loop (cdr old-ids) (cdr opnds) ids vals n seq?))))) - (let ([b (operand-lifted opnd)]) - (if (not b) - (f ids vals seq?) - (f (let ([lifted (lifted-ids b)]) - (for-each (lambda (id) (prelex-operand-set! id #f)) lifted) - (rappend lifted ids)) - (rappend (lifted-vals b) vals) - ; must treat outer letrec as letrec* if assimilating - ; letrec* bindings - (or seq? (lifted-seq? b))))))] - [(prelex-assigned id) - (loop (cdr old-ids) (cdr opnds) (cons id ids) (cons void-rec vals) n seq?)] - [else (loop (cdr old-ids) (cdr opnds) ids vals n seq?)]))))))))) - - (define residualize-ref - (lambda (maybe-src id sc) - (bump sc 1) - (when (prelex-referenced id) - (set-prelex-multiply-referenced! id #t)) - (set-prelex-referenced! id #t) - `(ref ,maybe-src ,id))) - - (define copy - ; ctxt is value, test, or app - ; opnd has already been visited - (lambda (maybe-src id opnd ctxt sc wd name moi) - (let ((rhs (result-exp (operand-value opnd)))) - (nanopass-case (Lsrc Expr) rhs - [(quote ,d) rhs] - [(record-type ,rtd ,e) - `(record-type ,rtd - ,(residualize-ref maybe-src - (nanopass-case (Lsrc Expr) e - [(ref ,maybe-src ,x) - (guard (not (prelex-was-assigned x)) - ; protect against (letrec ([x x]) ---) - (not (eq? x id))) - (when (prelex-was-multiply-referenced id) - (set-prelex-was-multiply-referenced! x #t)) - x] - [else id]) - sc))] - [(record-cd ,rcd ,rtd-expr ,e) - `(record-cd ,rcd ,rtd-expr - ,(residualize-ref maybe-src - (nanopass-case (Lsrc Expr) e - [(ref ,maybe-src ,x) - (guard (not (prelex-was-assigned x)) - ; protect against (letrec ([x x]) ---) - (not (eq? x id))) - (when (prelex-was-multiply-referenced id) - (set-prelex-was-multiply-referenced! x #t)) - x] - [else id]) - sc))] - [(immutable-list (,e* ...) ,e) - `(immutable-list (,e* ...) - ,(residualize-ref maybe-src - (nanopass-case (Lsrc Expr) e - [(ref ,maybe-src ,x) - (guard (not (prelex-was-assigned x)) - ; protect against (letrec ([x x]) ---) - (not (eq? x id))) - (when (prelex-was-multiply-referenced id) - (set-prelex-was-multiply-referenced! x #t)) - x] - [else id]) - sc))] - [(ref ,maybe-src1 ,x) - (cond - [(and (not (prelex-was-assigned x)) - ; protect against (letrec ([x x]) ---) - (not (eq? x id))) - (when (prelex-was-multiply-referenced id) - (set-prelex-was-multiply-referenced! x #t)) - (let ([opnd (prelex-operand x)]) - (if (and opnd (operand-value opnd)) - (copy2 maybe-src x opnd ctxt sc wd name moi) - (residualize-ref maybe-src x sc)))] - [else (residualize-ref maybe-src id sc)])] - [else (copy2 maybe-src id opnd ctxt sc wd name moi)])))) - - (define copy2 - ; ctxt is value, test, or app - (lambda (maybe-src id opnd ctxt sc wd name moi) - (let ([rhs (result-exp (operand-value opnd))]) - (nanopass-case (Lsrc Expr) rhs - [(case-lambda ,preinfo1 ,cl* ...) - (context-case ctxt - [(test) true-rec] - [(app) - (with-values (find-lambda-clause rhs ctxt) - (case-lambda - [(ids body) - (let ([limit (if (passive-scorer? sc) - (fx+ score-limit (length (app-opnds ctxt))) - (scorer-limit sc))]) - (if (outer-cyclic? opnd) - (or (and polyvariant - (fx= (operand-opending opnd) (fx+ outer-unroll-limit 1)) - ; Give it one (more) whirl, but bug out if recursive - ; refs remain. We do this by setting id's opnd to new - ; scorer and bugging out when we find a scorer in place - ; of an operand in decode-ref. we don't have to worry - ; about finding an assignment because we don't attempt - ; to integrated assigned variables - (call/1cc - (lambda (k) - (let ([new-sc (new-scorer limit ctxt k)] - [new-wd (new-watchdog wd ctxt k)]) - (with-extended-env ((env ignore-ids) (empty-env (list id) (list new-sc))) - (let ([x (opending-protect opnd - (cp0-let preinfo1 ids body ctxt env new-sc new-wd name moi))]) - (bump sc (fx- limit (scorer-limit new-sc))) - x)))))) - (residualize-ref maybe-src id sc)) - ; the monovariant filter below is flawed because opnd sizes do - ; necessarily reflect integrated singly referenced items - (or (and (or polyvariant (fx< (operand-score opnd) limit)) - (call/1cc - (lambda (k) - (let ([new-wd (new-watchdog wd ctxt k)]) - (if (prelex-was-multiply-referenced id) - (let ([new-sc (new-scorer limit ctxt k)]) - (let ([x (opending-protect opnd - (cp0-let preinfo1 ids body ctxt empty-env new-sc new-wd name moi))]) - (bump sc (fx- limit (scorer-limit new-sc))) - x)) - (let ([new-sc (new-scorer)]) - (let ([x (opending-protect opnd - (cp0-let preinfo1 ids body ctxt empty-env new-sc new-wd name moi))]) - (operand-singly-referenced-score-set! opnd (scorer-score new-sc)) - x))))))) - (residualize-ref maybe-src id sc))))] - [() (residualize-ref maybe-src id sc)]))] - [else (residualize-ref maybe-src id sc)])] - [,pr - (context-case ctxt - [(value) - (if (all-set? (prim-mask (or primitive proc)) (primref-flags pr)) - rhs - (residualize-ref maybe-src id sc))] - [(test) - (if (all-set? (prim-mask proc) (primref-flags pr)) - true-rec - (residualize-ref maybe-src id sc))] - [else (fold-primref rhs ctxt sc wd name moi)])] - [else (residualize-ref maybe-src id sc)])))) - - (define fold-primref - (lambda (pr ctxt sc wd name moi) - (let ([opnds (app-opnds ctxt)]) - (convention-case (app-convention ctxt) - [(call) - (let ([flags (primref-flags pr)] [outer-ctxt (app-ctxt ctxt)]) - (cond - [(and (eq? outer-ctxt 'effect) - (if (all-set? (prim-mask unsafe) flags) - (all-set? (prim-mask discard) flags) - (and (all-set? (prim-mask (or unrestricted discard)) flags) - (arity-okay? (primref-arity pr) (length opnds))))) - (residualize-seq '() opnds ctxt) - void-rec] - [(and (eq? outer-ctxt 'test) - (all-set? - (if (all-set? (prim-mask unsafe) flags) - (prim-mask (or discard true)) - (prim-mask (or unrestricted discard true))) - flags)) - (residualize-seq '() opnds ctxt) - true-rec] - [(and (eq? outer-ctxt 'test) - (all-set? (prim-mask true) flags)) - (make-seq outer-ctxt - (fold-primref2 pr (primref-name pr) opnds flags ctxt sc wd name moi) - true-rec)] - [else (fold-primref2 pr (primref-name pr) opnds flags ctxt sc wd name moi)]))] - [(apply2 apply3) - ; handler for apply will have turned the apply into a call if the last - ; argument is discovered to be a list. nothing more we can do here. - (residualize-primcall pr #f opnds ctxt sc)])))) - - (define fold-primref2 - (lambda (pr sym opnds pflags ctxt sc wd name moi) - (safe-assert (convention-case (app-convention ctxt) [(call) #t] [else #f])) - (let ([handler (or (and (all-set? (prim-mask unsafe) pflags) - (all-set? (prim-mask cp03) pflags) - ($sgetprop sym 'cp03 #f)) - (and (all-set? (prim-mask cp02) pflags) - ($sgetprop sym 'cp02 #f)))]) - (or (and handler - (let ([level (if (all-set? (prim-mask unsafe) pflags) 3 2)]) - (handler level opnds ctxt sc wd name moi))) - (let ([args (value-visit-operands! opnds)]) - (cond - [(and (all-set? (prim-mask mifoldable) pflags) - (let ([objs (objs-if-constant args)]) - (and objs (guard (c [#t #f]) - (call-with-values - (lambda () (apply ($top-level-value sym) objs)) - (case-lambda - [(v) `(quote ,v)] - [v* `(call ,(app-preinfo ctxt) ,(lookup-primref 3 'values) - ,(map (lambda (x) `(quote ,x)) v*) - ...)])))))) => - (lambda (e) - (residualize-seq '() opnds ctxt) - e)] - [else - (residualize-primcall pr args opnds ctxt sc)])))))) - - (define residualize-primcall - (lambda (pr args opnds ctxt sc) - (let ([args (or args (value-visit-operands! opnds))]) - (residualize-seq opnds '() ctxt) - (bump sc 1) - (let ([preinfo (app-preinfo ctxt)]) - (convention-case (app-convention ctxt) - [(call) `(call ,preinfo ,pr ,args ...)] - [(apply2) (build-primcall preinfo 2 'apply (cons pr args))] - [(apply3) (build-primcall preinfo 3 'apply (cons pr args))]))))) - - (define objs-if-constant - (lambda (e*) - (if (null? e*) - '() - (nanopass-case (Lsrc Expr) (result-exp (car e*)) - [(quote ,d) - (let ([rest (objs-if-constant (cdr e*))]) - (and rest (cons d rest)))] - [else #f])))) - - (define record-equal? - ; not very ambitious - (lambda (e1 e2 ctxt) - (if (eq? ctxt 'effect) - (and (simple? e1) (simple? e2)) - (nanopass-case (Lsrc Expr) e1 - [(ref ,maybe-src1 ,x1) - (nanopass-case (Lsrc Expr) e2 - [(ref ,maybe-src2 ,x2) (eq? x1 x2)] - [else #f])] - [(quote ,d1) - (nanopass-case (Lsrc Expr) e2 - [(quote ,d2) - (if (eq? ctxt 'test) - (if d1 d2 (not d2)) - (eq? d1 d2))] - [else #f])] - [else #f])))) - - (module () - (define-syntax define-inline - (lambda (x) - (syntax-case x () - ((_key lev prim clause ...) - (identifier? #'prim) - #'(_key lev (prim) clause ...)) - ((_key lev (prim ...) clause ...) - (andmap identifier? #'(prim ...)) - (with-implicit (_key prim-name level ctxt sc wd name moi) - (with-syntax - ((key (case (datum lev) - ((2) #'cp02) - ((3) #'cp03) - (else ($oops #f "invalid inline level ~s" (datum lev))))) - (body - (let f ((clauses #'(clause ...))) - (if (null? clauses) - #'#f - (with-syntax ((rest (f (cdr clauses)))) - (syntax-case (car clauses) () - (((x ...) e1 e2 ...) - (with-syntax ((n (length #'(x ...)))) - #'(if (eq? count n) - (apply (lambda (x ...) e1 e2 ...) args) - rest))) - ((r e1 e2 ...) - (identifier? #'r) - #'(apply (lambda r e1 e2 ...) args)) - ((r e1 e2 ...) - (with-syntax ((n (let loop ((r #'r) (n 0)) - (syntax-case r () - ((v . r) - (identifier? #'v) - (loop #'r (+ n 1))) - (v - (identifier? #'v) - n))))) - #'(if (fx>= count n) - (apply (lambda r e1 e2 ...) args) - rest))))))))) - (for-each - (lambda (sym-name) - (let ([sym-key (datum key)]) - (if (getprop sym-name sym-key #f) - (warningf #f "duplicate ~s handler for ~s" sym-key sym-name) - (putprop sym-name sym-key #t)) - (unless (all-set? - (case (datum lev) - [(2) (prim-mask cp02)] - [(3) (prim-mask cp03)]) - ($sgetprop sym-name '*flags* 0)) - (warningf #f "undeclared ~s handler for ~s~%" sym-key sym-name)))) - (datum (prim ...))) - #'(let ((foo (lambda (prim-name) - (lambda (level args ctxt sc wd name moi) - (let ((count (length args))) - body))))) - ($sputprop 'prim 'key (foo 'prim)) ...))))))) - - (define generic-nan? - (lambda (x) - (and (flonum? x) ($nan? x)))) - - (define fl-nan? - (lambda (x) - ($nan? x))) - - (define cfl-nan? - (lambda (z) - (and ($nan? (cfl-real-part z)) ($nan? (cfl-imag-part z))))) - - (define exact-zero? - (lambda (x) - (eq? x 0))) - - (define exact-negone? - (lambda (x) - (eq? x -1))) - - ;;; what to include here vs. in cp1in: - ;;; Include here transformations that eliminate the need to evaluate an - ;;; operand (for value) or that may open up opportunities for further - ;;; folding. For example, memq with second argument '() doesn't need - ;;; the value of its first operand. It also evaluates to #f or - ;;; (seq #f) and thus may lead to further folding. - ;;; - ;;; Don't bother with optimizations, such as strength reduction, that - ;;; just result in other calls. For example, memq with a constant, - ;;; non-null second argument expands into calls to eq?, which we can't - ;;; do anything with. - - ;;; caution: - ;;; We must use value-visit-operand here rather than calling cp0 on - ;;; operand expressions. Although at this level we may be guaranteed - ;;; to succeed, we may be succeeding in an outer context of an inner - ;;; context that will eventually fail. For example, in: - ;;; - ;;; (let ((f (lambda () - ;;; (let ((x huge-a)) - ;;; (let ((g (lambda () x))) - ;;; (g) not))))) - ;;; ((f) huge-b)) - ;;; - ;;; where huge-a and huge-b are large unreducible expressions, we - ;;; create an operand O1 for huge-a, process (f) in an app context - ;;; A1, process f in another app context A2 whose outer context is - ;;; A1, encounter reference to f, process the (lambda () ...) for - ;;; value, producing: - ;;; - ;;; (lambda () - ;;; (let ((x huge-a)) - ;;; not)) - ;;; - ;;; then attempt to integrate the body of this lambda expression in - ;;; the outer app context A1, resulting in an attempt to apply not to - ;;; the operand O1. Say not extracts the expression from O1 to - ;;; produce (if huge-b #f #t). We would then process this if, - ;;; including huge-b. when trying to rebuild (let ((x huge-a)) ...), - ;;; we would discover that x is not referenced, but would leave - ;;; behind huge-a and, because of its size, abort the attempted - ;;; inlining of app context A1. We would then residualize the call - ;;; ((f) huge-b), processing O1's expression, huge-b, again. - ;;; - ;;; Primitives that must extract the operand expression (such as - ;;; not and apply) should be caught in the call case of cp0 before - ;;; the expressions are encapsulated in operand structures. A - ;;; downside to catching prims at that level is that in - ;;; (let ((f prim)) (f e)), the call (f e) won't be recognized as - ;;; a primitive application of prim. - ;;; - ;;; On the other hand, this arises only while we are integrating, - ;;; so if we charge the first processing of huge-b to the watchdog - ;;; and scorer associated with the A1 integration attempt rather - ;;; than to the top level watchdog and scorer that we would usually - ;;; use for huge-b, we could be okay. - - ; okay-to-handle? should return #f only when interpreting code on a - ; host machine with a different target-machine compiler loaded. we - ; try to treat the other cases the same (not cross-compiling, with - ; no cross compiler loaded, or cross-compiling, with cross compiler - ; loaded) so that we don't have mostly untested handler code for - ; cross-compiled case. - (define (okay-to-handle?) (eq? ($target-machine) (constant machine-type-name))) - - (define-syntax visit-and-maybe-extract* - (lambda (x) - (syntax-case x () - [(_ ?pred? ([x opnd] ...) e1 e2 ...) - #`(let ([pred? ?pred?]) - (and (okay-to-handle?) - #,(fold-right (lambda (x opnd e) - #`(let ([xval (value-visit-operand! #,opnd)]) - (nanopass-case (Lsrc Expr) (result-exp xval) - [(quote ,d) (and (pred? d) (let ([#,x d]) #,e))] - [else #f]))) - #'(begin e1 e2 ...) #'(x ...) #'(opnd ...))))]))) - - (define handle-shift - (lambda (level ctxt x y) - (and (fx= level 3) - (let ([xval (value-visit-operand! x)] - [yval (value-visit-operand! y)]) - (cond - [(cp0-constant? (lambda (obj) (eqv? obj 0)) (result-exp yval)) - (residualize-seq (list x) (list y) ctxt) - xval] - [else #f]))))) - - ; could handle inequalities as well (returning #f), but that seems less likely to crop up - (define handle-equality - (lambda (ctxt arg arg*) - (and - (or (null? arg*) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! arg)) - [(ref ,maybe-src ,x0) - (and (not (prelex-was-assigned x0)) - (andmap - (lambda (arg) - (and (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! arg)) - [(ref ,maybe-src ,x) (eq? x x0)] - [else #f]))) - arg*))] - [else #f])) - (begin - (residualize-seq '() (cons arg arg*) ctxt) - true-rec)))) - - (define-inline 2 machine-type - [() (begin - (residualize-seq '() '() ctxt) - `(quote ,($target-machine)))]) - - (let () - (define-syntax define-inline-constant-parameter - (syntax-rules () - [(_ (name ...) k) - (define-inline 2 (name ...) - [() (and (okay-to-handle?) - (begin - (residualize-seq '() '() ctxt) - `(quote ,k)))])])) - (define-inline-constant-parameter (native-endianness) (constant native-endianness)) - (define-inline-constant-parameter (directory-separator) (if-feature windows #\\ #\/)) - (define-inline-constant-parameter (threaded?) (if-feature pthreads #t #f)) - (define-inline-constant-parameter (most-negative-fixnum least-fixnum) (constant most-negative-fixnum)) - (define-inline-constant-parameter (most-positive-fixnum greatest-fixnum) (constant most-positive-fixnum)) - (define-inline-constant-parameter (fixnum-width) (constant fixnum-bits)) - (define-inline-constant-parameter (virtual-register-count) (constant virtual-register-count))) - - (define-inline 2 directory-separator? - [(c) (visit-and-maybe-extract* char? ([dc c]) - (residualize-seq '() (list c) ctxt) - `(quote ,(and (memv dc (if-feature windows '(#\\ #\/) '(#\/))) #t)))]) - - (define-inline 2 foreign-sizeof - [(x) (and (okay-to-handle?) - (let ([xval (value-visit-operand! x)]) - (nanopass-case (Lsrc Expr) (result-exp xval) - [(quote ,d) - (let () - (define-syntax size - (syntax-rules () - [(_ type bytes pred) - (begin - (residualize-seq '() (list x) ctxt) - `(quote ,bytes))])) - (record-datatype cases (filter-foreign-type d) size #f))] - [else #f])))]) - - (let ([addr-int? (constant-case address-bits [(32) $integer-32?] [(64) $integer-64?])]) - (define-inline 2 $verify-ftype-address - [(who e) (visit-and-maybe-extract* addr-int? ([de e]) - (residualize-seq '() (list who e) ctxt) - true-rec)])) - - (define-inline 2 (memq memv member assq assv assoc) - [(x ls) - (and (cp0-constant? null? (result-exp (value-visit-operand! ls))) - (begin - (residualize-seq '() (list x ls) ctxt) - false-rec))]) - - (define-inline 3 (memp assp find) - [(pred ls) - (and (cp0-constant? null? (result-exp (value-visit-operand! ls))) - (begin - (residualize-seq '() (list pred ls) ctxt) - false-rec))]) - - (define-inline 2 (remq remv remove) - [(x ls) - (and (cp0-constant? null? (result-exp (value-visit-operand! ls))) - (begin - (residualize-seq '() (list x ls) ctxt) - null-rec))]) - - (define-inline 3 (remp filter) - [(pred ls) - (and (cp0-constant? null? (result-exp (value-visit-operand! ls))) - (begin - (residualize-seq '() (list pred ls) ctxt) - null-rec))]) - - (define-inline 2 apply - [(proc opnd1 . opnds) - (let ([opnds (cons opnd1 opnds)]) - (let ([last-opnd (car (last-pair opnds))]) - (cond - [(nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! last-opnd)) - [(quote ,d) (guard (list? d) (<= (length d) 1000)) (map build-quote d)] - [(immutable-list (,e* ...) ,e) e*] - [(call ,preinfo ,pr ,e* ...) (guard (eq? (primref-name pr) 'list)) e*] - [else #f]) => - (lambda (e*) - (let ([opnds (let f ([opnds opnds]) - (let ([rest (cdr opnds)]) - (if (null? rest) - '() - (cons (car opnds) (f (cdr opnds))))))]) - (let ([tproc (cp0-make-temp #f)] [t* (map (lambda (x) (cp0-make-temp #f)) opnds)]) - (with-extended-env ((env ids) (empty-env (cons tproc t*) (cons proc opnds))) - (letify (make-preinfo-lambda) ids ctxt (list last-opnd) - (non-result-exp (operand-value last-opnd) - (cp0-call (app-preinfo ctxt) (build-ref tproc) - (fold-right - (lambda (t opnd*) (cons (make-operand (build-ref t) env wd moi) opnd*)) - (map build-cooked-opnd e*) - t*) - (app-ctxt ctxt) env sc wd (app-name ctxt) moi)))))))] - [(nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! last-opnd)) - [(call ,preinfo ,pr ,e1 ,e2) (guard (eq? (primref-name pr) 'cons)) (list e1 e2)] - [(call ,preinfo ,pr ,e ,e* ...) (guard (memq (primref-name pr) '(list* cons*))) (cons e e*)] - [else #f]) => - (lambda (e*) - (let ([opnds (cons proc - (let f ([opnds opnds]) - (let ([rest (cdr opnds)]) - (if (null? rest) - '() - (cons (car opnds) (f (cdr opnds)))))))]) - (let ([t* (map (lambda (x) (cp0-make-temp #f)) opnds)]) - (with-extended-env ((env ids) (empty-env t* opnds)) - (letify (make-preinfo-lambda) ids ctxt (list last-opnd) - (non-result-exp (operand-value last-opnd) - (cp0-call (app-preinfo ctxt) (lookup-primref level 'apply) - (fold-right - (lambda (t opnd*) (cons (make-operand (build-ref t) env wd moi) opnd*)) - (map build-cooked-opnd e*) - t*) - (app-ctxt ctxt) env sc wd (app-name ctxt) moi)))))))] - [else - (let ([temp (cp0-make-temp #f)]) ; N.B.: temp is singly referenced - (with-extended-env ((env ids) (empty-env (list temp) (list proc))) - (let* ([new-ctxt (make-app opnds (app-ctxt ctxt) - (if (fx= level 3) 'apply3 'apply2) - (app-name ctxt) - (app-preinfo ctxt))] - [e (cp0 (build-ref temp) new-ctxt env sc wd #f moi)]) - (and (app-used new-ctxt) - (begin - (residualize-seq (app-used new-ctxt) (cons proc (app-unused new-ctxt)) ctxt) - e)))))])))]) - - (define-inline 2 not - [(e) - (let ([e-val (test-visit-operand! e)]) - (nanopass-case (Lsrc Expr) (result-exp e-val) - [(quote ,d) - (residualize-seq '() (list e) ctxt) - (if d false-rec true-rec)] - [else - (residualize-seq (list e) '() ctxt) - (make-if ctxt sc e-val false-rec true-rec)]))]) - - (define-inline 2 call-with-values - [(p-opnd c-opnd) - (let ((p-temp (cp0-make-temp #f)) (c-temp (cp0-make-temp #f))) - (with-extended-env ((env ids) (empty-env (list p-temp c-temp) (app-opnds ctxt))) - (let ((ctxt1 (make-app '() 'value 'call #f (app-preinfo ctxt)))) - (let ((*p-val (cp0 (build-ref p-temp) ctxt1 env sc wd #f moi))) - (cond - [(and (app-used ctxt1) - (let ([e (result-exp *p-val)]) - (nanopass-case (Lsrc Expr) e - ; in dire need of matching more than one pattern - [(quote ,d) (list e)] - [(ref ,maybe-src ,x) (list e)] - [(set! ,maybe-src ,x0 ,e0) (list e)] - [(case-lambda ,preinfo ,cl* ...) (list e)] - [,pr (list e)] - [(foreign (,conv* ...) ,name ,e0 (,arg-type* ...) ,result-type) (list e)] - [(fcallable (,conv* ...) ,e0 (,arg-type* ...) ,result-type) (list e)] - [(record-type ,rtd0 ,e0) (list e)] - [(record-cd ,rcd0 ,rtd-expr0 ,e0) (list e)] - [(immutable-list (,e0* ...) ,e0) (list e)] - [(record-ref ,rtd ,type ,index ,e0) (list e)] - [(record-set! ,rtd ,type ,index ,e1 ,e2) (list e)] - [(record ,rtd ,rtd-expr ,e* ...) (list e)] - [(call ,preinfo ,pr ,e* ...) - (guard (eq? (primref-name pr) 'values)) - e*] - [else #f]))) => - (lambda (args) - ; (with-values (values arg ...) c-temp) => (c-temp arg ...) - (letify (make-preinfo-lambda) ids ctxt - (non-result-exp *p-val - (cp0-call (app-preinfo ctxt) (build-ref c-temp) - (map build-cooked-opnd args) - (app-ctxt ctxt) env sc wd (app-name ctxt) moi))))] - [else - (call-with-values - (lambda () - (let ((e (value-visit-operand! c-opnd))) - (nanopass-case (Lsrc Expr) (result-exp e) - [(case-lambda ,preinfo ,cl* ...) - (values (result-exp e) '() (list c-opnd))] - [,pr (values (result-exp e) '() (list c-opnd))] - [else (values e (list c-opnd) '())]))) - (lambda (c-val used unused) - (if (app-used ctxt1) - (begin - (residualize-seq used (cons p-opnd unused) ctxt) - (non-result-exp *p-val - (build-primcall (app-preinfo ctxt) level 'call-with-values - (list - (build-lambda '() (result-exp *p-val)) - c-val)))) - (build-primcall (app-preinfo ctxt) level 'call-with-values - (list - (let ((e (value-visit-operand! p-opnd))) - (nanopass-case (Lsrc Expr) (result-exp e) - [(case-lambda ,preinfo ,cl* ...) - (residualize-seq used (cons p-opnd unused) ctxt) - (result-exp e)] - [,pr - (residualize-seq used (cons p-opnd unused) ctxt) - (result-exp e)] - [else - (residualize-seq (cons p-opnd used) unused ctxt) - e])) - c-val)))))])))))]) - - (define-inline 2 list - [() (begin - (residualize-seq '() '() ctxt) - null-rec)] - [args #f]) - - (define-inline 2 (cons* list* values append append!) - [(x) (let ((xval (value-visit-operand! x))) - (residualize-seq (list x) '() ctxt) - xval)] - [args #f]) - - (define-inline 2 vector - [() (begin - (residualize-seq '() '() ctxt) - empty-vector-rec)] - [args #f]) - - (define-inline 2 string - [() (begin - (residualize-seq '() '() ctxt) - empty-string-rec)] - [args #f]) - - (define-inline 2 bytevector - [() (begin - (residualize-seq '() '() ctxt) - empty-bytevector-rec)] - [args #f]) - - (define-inline 2 fxvector - [() (begin - (residualize-seq '() '() ctxt) - empty-fxvector-rec)] - [args #f]) - - (define-inline 2 (eq? eqv? equal?) - [(arg1 arg2) (handle-equality ctxt arg1 (list arg2))]) - - (define-inline 3 (bytevector=? enum-set=? bound-identifier=? free-identifier=? ftype-pointer=? literal-identifier=? time=?) - [(arg1 arg2) (handle-equality ctxt arg1 (list arg2))]) - - (define-inline 3 (char=? char-ci=? string=? string-ci=?) - [(arg . arg*) (handle-equality ctxt arg arg*)]) - - (define-inline 3 (boolean=? symbol=? r6rs:char=? r6rs:char-ci=? r6rs:string=? r6rs:string-ci=?) - [(arg1 arg2 . arg*) (handle-equality ctxt arg1 (cons arg2 arg*))]) - - (define-inline 3 (ash - bitwise-arithmetic-shift bitwise-arithmetic-shift-left - bitwise-arithmetic-shift-right) - [(x y) (handle-shift 3 ctxt x y)]) - - (define-inline 3 fxbit-field ; expose internal fx ops for partial optimization - [(?n ?start ?end) - (cp0 - (let ([n (cp0-make-temp #f)] - [start (cp0-make-temp #f)] - [end (cp0-make-temp #f)]) - (build-lambda (list n start end) - (build-primcall 3 'fxsra - (list - (build-primcall 3 'fxand - (list - (build-ref n) - (build-primcall 3 'fxnot - (list - (build-primcall 3 'fxsll - (list - `(quote -1) - (build-ref end))))))) - (build-ref start))))) - ctxt empty-env sc wd name moi)]) - - (let () - (define make-fold? - (lambda (op generic-op) - (lambda (val a) ; returns value of (op a val) or #f - (nanopass-case (Lsrc Expr) (result-exp val) - [(quote ,d) - (guard (c [#t #f]) - (if (eq? generic-op op) - (op a d) - (and (target-fixnum? d) - (let ([folded (generic-op a d)]) - (and (target-fixnum? folded) folded)))))] - [else #f])))) - (define (partial-fold-plus level orig-arg* ctxt prim op generic-op ident bottom?) - (define fold? (make-fold? op generic-op)) - (let loop ([arg* (reverse orig-arg*)] [a ident] [val* '()] [used '()] [unused '()]) - (if (null? arg*) - (cond - [(bottom? a) - (cond - [(or (fx= level 3) (null? val*)) - (residualize-seq '() orig-arg* ctxt) - `(quote ,a)] - [else - (residualize-seq used unused ctxt) - `(seq - ,(build-primcall (app-preinfo ctxt) level prim val*) - (quote ,a))])] - [else - (residualize-seq used unused ctxt) - (cond - [(null? val*) `(quote ,a)] - [(eqv? a ident) - (if (and (fx= level 3) (null? (cdr val*))) - (car val*) - (build-primcall (app-preinfo ctxt) level prim val*))] - [else - (build-primcall (app-preinfo ctxt) level prim (cons `(quote ,a) val*))])]) - (let* ([arg (car arg*)] [val (value-visit-operand! arg)]) - (cond - [(fold? val a) => - (lambda (a) (loop (cdr arg*) a val* used (cons arg unused)))] - [else (loop (cdr arg*) a (cons val val*) (cons arg used) unused)]))))) - - (define (partial-fold-minus level arg arg* ctxt prim op generic-op ident) - ; ident is such that (op ident x) == (op x) - (define fold? (make-fold? op generic-op)) - (define (finish a val* used unused) - (residualize-seq used unused ctxt) - (if (null? val*) - `(quote ,a) - (build-primcall (app-preinfo ctxt) level prim - (if (and (eqv? a ident) (null? (cdr val*))) - val* - (cons `(quote ,a) val*))))) - ; to maintain left-associative behavior, stop when we get to the first non-constant arg - (let ([val (value-visit-operand! arg)]) - (cond - [(nanopass-case (Lsrc Expr) (result-exp val) - ; (op obj ident) is not necessarily the same as obj, so return obj - [(quote ,d) (and (guard (c [#t #f]) (op d ident)) d)] - [else #f]) => - (lambda (a) - (let loop ([arg* arg*] [a a] [val* '()] [unused (list arg)]) - (if (null? arg*) - (finish a (reverse val*) '() unused) - (let* ([arg (car arg*)] [val (value-visit-operand! arg)]) - (cond - [(fold? val a) => (lambda (a) (loop (cdr arg*) a val* (cons arg unused)))] - [else (finish a (rappend val* (map value-visit-operand! arg*)) arg* unused)])))))] - [else #f]))) - - (define (partial-fold-negate level arg ctxt prim op generic-op ident) - (define fold? (make-fold? op generic-op)) - (let ([val (value-visit-operand! arg)]) - (cond - [(fold? val ident) => - (lambda (a) - (residualize-seq '() (list arg) ctxt) - `(quote ,a))] - [else #f]))) - - (define-syntax partial-folder - ; partial-fold-plus assumes arg* is nonempty - (syntax-rules (plus minus) - [(_ plus prim generic-op ident) - (partial-folder plus prim generic-op ident (lambda (x) #f))] - [(_ plus prim generic-op ident bottom?) - (begin - (define-inline 2 prim - ; (fl+) might should return -0.0, but we force it to return +0.0 per TSPL4 - [() (residualize-seq '() '() ctxt) `(quote ,(if (eqv? ident -0.0) +0.0 ident))] - [arg* (partial-fold-plus 2 arg* ctxt 'prim prim generic-op ident bottom?)]) - (define-inline 3 prim - ; (fl+) might should return -0.0, but we force it to return +0.0 per TSPL4 - [() (residualize-seq '() '() ctxt) `(quote ,(if (eqv? ident -0.0) +0.0 ident))] - [arg* (partial-fold-plus 3 arg* ctxt 'prim prim generic-op ident bottom?)]))] - [(_ minus prim generic-op ident) - (begin - (define-inline 2 prim - [(arg) (partial-fold-negate 2 arg ctxt 'prim prim generic-op ident)] - [(arg . arg*) (partial-fold-minus 2 arg arg* ctxt 'prim prim generic-op ident)]) - (define-inline 3 prim - [(arg) (partial-fold-negate 3 arg ctxt 'prim prim generic-op ident)] - [(arg . arg*) (partial-fold-minus 3 arg arg* ctxt 'prim prim generic-op ident)]))])) - - (define-syntax r6rs-fixnum-partial-folder - ; fx+ and fx* limited to exactly two args, fx- limited to one or two args - (syntax-rules (plus minus) - [(_ plus r6rs:prim prim generic-op ident) - (r6rs-fixnum-partial-folder plus r6rs:prim prim generic-op ident (lambda (x) #f))] - [(_ plus r6rs:prim prim generic-op ident bottom?) - (begin - (define-inline 2 r6rs:prim - [(arg1 arg2) (partial-fold-plus 2 (list arg1 arg2) ctxt 'prim prim generic-op ident bottom?)]) - (define-inline 3 r6rs:prim - [(arg1 arg2) (partial-fold-plus 3 (list arg1 arg2) ctxt 'prim prim generic-op ident bottom?)]))] - [(_ minus r6rs:prim prim generic-op ident) - (begin - (define-inline 2 r6rs:prim - [(arg) (partial-fold-negate 2 arg ctxt 'prim prim generic-op ident)] - [(arg1 arg2) - (partial-fold-minus 2 arg1 (list arg2) ctxt 'prim prim generic-op ident)]) - (define-inline 3 r6rs:prim - [(arg) (partial-fold-negate 3 arg ctxt 'prim prim generic-op ident)] - [(arg1 arg2) - (partial-fold-minus 3 arg1 (list arg2) ctxt 'prim prim generic-op ident)]))])) - - ; handling nans here using the support for handling exact zero in - ; the multiply case. maybe shouldn't bother with nans anyway. - (partial-folder plus + + 0 generic-nan?) - (partial-folder plus fx+ + 0) - (r6rs-fixnum-partial-folder plus r6rs:fx+ fx+ + 0) - (partial-folder plus fl+ fl+ -0.0 fl-nan?) - (partial-folder plus cfl+ cfl+ -0.0 cfl-nan?) - - (partial-folder plus * * 1 exact-zero?) ; exact zero trumps nan - (partial-folder plus fx* * 1 exact-zero?) - (r6rs-fixnum-partial-folder plus r6rs:fx* fx* * 1 exact-zero?) - (partial-folder plus fl* fl* 1.0 fl-nan?) - (partial-folder plus cfl* cfl* 1.0 cfl-nan?) - - ; not handling nans here since we don't have support for the exact - ; zero case in division. it would be nice to reduce (/ 0 x1 x2 ...) - ; to 0, but (/ 0 n) is only 0 if divisor turns out not to be 0. - (partial-folder minus - - 0) - (partial-folder minus fx- - 0) - (r6rs-fixnum-partial-folder minus r6rs:fx- fx- - 0) - (partial-folder minus fl- fl- -0.0) - (partial-folder minus cfl- cfl- -0.0) - - (partial-folder minus / / 1) - (partial-folder minus fx/ quotient 1) - (partial-folder minus fxquotient quotient 1) - (partial-folder minus fl/ fl/ 1.0) - (partial-folder minus cfl/ cfl/ 1.0) - - (partial-folder plus logior logior 0 exact-negone?) - (partial-folder plus logor logor 0 exact-negone?) - (partial-folder plus bitwise-ior bitwise-ior 0 exact-negone?) - (partial-folder plus fxlogior logor 0 exact-negone?) - (partial-folder plus fxior logor 0 exact-negone?) - (partial-folder plus fxlogor logor 0 exact-negone?) - (partial-folder plus logxor logxor 0) - (partial-folder plus bitwise-xor bitwise-xor 0) - (partial-folder plus fxlogxor logxor 0) - (partial-folder plus fxxor logxor 0) - (partial-folder plus logand logand -1 exact-zero?) - (partial-folder plus bitwise-and bitwise-and -1 exact-zero?) - (partial-folder plus fxlogand logand -1 exact-zero?) - (partial-folder plus fxand logand -1 exact-zero?) - ) - - (let () - (define $fold - (lambda (generic-op orig-opnd* pred* opred level ctxt handler) - (define cookie '(fig . newton)) - (and (okay-to-handle?) - (or (let loop ([opnd* orig-opnd*] [pred* pred*] [rval* '()]) - (if (null? opnd*) - (let ([val (guard (c [#t cookie]) (apply generic-op (reverse rval*)))]) - (and (not (eq? val cookie)) - (opred val) - (begin - (residualize-seq '() orig-opnd* ctxt) - `(quote ,val)))) - (let-values ([(pred pred*) (if (procedure? pred*) (values pred* pred*) (values (car pred*) (cdr pred*)))]) - (visit-and-maybe-extract* pred ([val (car opnd*)]) - (loop (cdr opnd*) pred* (cons val rval*)))))) - (apply handler level ctxt orig-opnd*))))) - (define null-handler (lambda args #f)) - (define-syntax fold - (lambda (x) - (syntax-case x () - [(_ (prim ipred ...) opred generic-op) #'(fold (prim ipred ...) opred generic-op null-handler)] - [(_ (prim ipred ...) opred generic-op handler) - (with-syntax ([(arg ...) (generate-temporaries #'(ipred ...))]) - #'(define-inline 2 prim - [(arg ...) - ($fold generic-op (list arg ...) (list ipred ...) opred level ctxt handler)]))] - [(_ (prim ipred ... . rpred) opred generic-op) #'(fold (prim ipred ... . rpred) opred generic-op null-handler)] - [(_ (prim ipred ... . rpred) opred generic-op handler) - (with-syntax ([(arg ...) (generate-temporaries #'(ipred ...))]) - #'(define-inline 2 prim - [(arg ... . rest) - ($fold generic-op (cons* arg ... rest) (cons* ipred ... rpred) opred level ctxt handler)]))]))) - - (define tfixnum? target-fixnum?) - (define u<=fxwidth? - (lambda (x) - (and (fixnum? x) - (fx<= 0 x (constant fixnum-bits))))) - (define u tfixnum? . tfixnum?) boolean? #2%>) - (fold (fx>= tfixnum? . tfixnum?) boolean? #2%>=) - (fold (fx? tfixnum? tfixnum? . tfixnum?) boolean? #2%>) - (fold (fx>=? tfixnum? tfixnum? . tfixnum?) boolean? #2%>=) - (fold ($fxu< tfixnum? tfixnum?) boolean? - (lambda (x y) - (if (#2%< x 0) - (and (#2%< y 0) (#2%< x y)) - (or (#2%< y 0) (#2%< x y)))) - (lambda (level ctxt x y) - (let ([xval (value-visit-operand! x)] - [yval (value-visit-operand! y)]) - (and (cp0-constant? (lambda (obj) (eqv? obj (constant most-positive-fixnum))) (result-exp xval)) - (begin - (residualize-seq (list y) (list x) ctxt) - (build-primcall (app-preinfo ctxt) level 'fx< (list yval `(quote 0)))))))) - - (fold (fxmax tfixnum? . tfixnum?) tfixnum? #2%max) - (fold (fxmin tfixnum? . tfixnum?) tfixnum? #2%min) - (fold (fxabs tfixnum?) tfixnum? #2%abs) - - (fold (fxdiv tfixnum? tfixnum?) tfixnum? #2%div) - (fold (fxmod tfixnum? tfixnum?) tfixnum? #2%mod) - (fold (fxmodulo tfixnum? tfixnum?) tfixnum? #2%modulo) - (fold (fxdiv0 tfixnum? tfixnum?) tfixnum? #2%div0) - (fold (fxmod0 tfixnum? tfixnum?) tfixnum? #2%mod0) - (fold (fxremainder tfixnum? tfixnum?) tfixnum? #2%remainder) - (fold ((fxnot fxlognot) tfixnum?) tfixnum? #2%bitwise-not) - (fold (fxlogtest tfixnum? tfixnum?) boolean? #2%logtest) - (fold (fxif tfixnum? tfixnum? tfixnum?) tfixnum? #2%bitwise-if) - (fold (fxbit-count tfixnum?) tfixnum? #2%bitwise-bit-count) - (fold (fxlength tfixnum?) tfixnum? #2%bitwise-length) - (fold (fxfirst-bit-set tfixnum?) tfixnum? #2%bitwise-first-bit-set) - (fold (fx1+ tfixnum?) tfixnum? #2%1+) - (fold (fx1- tfixnum?) tfixnum? #2%1-) - - (fold (fxbit-set? tfixnum? tfixnum?) boolean? #2%bitwise-bit-set?) - (fold (fxcopy-bit tfixnum? uflonum fixnum?) flonum? #2%inexact) - (fold (flonum->fixnum flonum?) target-fixnum? (lambda (x) (#2%truncate (#2%exact x)))) - - (fold (fxzero? tfixnum?) boolean? zero?) - (fold (fxnegative? tfixnum?) boolean? negative?) - (fold (fxpositive? tfixnum?) boolean? positive?) - (fold (fxeven? tfixnum?) boolean? even?) - (fold (fxodd? tfixnum?) boolean? odd?) - (fold (fxnonnegative? tfixnum?) boolean? nonnegative?) - (fold (fxnonpositive? tfixnum?) boolean? nonpositive?)) - - (let () - (define target-wchar? - (lambda (x) - (and (char? x) - (constant-case wchar-bits - [(16) (< (char->integer x) #x10000)] - [(32) #t])))) - ; NB: is this sufficiently tested by ftype.ms and record.ms? - (define-inline 2 $foreign-wchar? - [(x) - (and (okay-to-handle?) - (visit-and-maybe-extract* (lambda (x) #t) ([c x]) - (residualize-seq '() (list x) ctxt) - `(quote ,(target-wchar? c))))])) - - (let () - (define $fold-bytevector-native-ref - (lambda (native-ref generic-ref align x y ctxt) - (and (okay-to-handle?) - (visit-and-maybe-extract* bytevector? ([dx x]) - (visit-and-maybe-extract* (lambda (y) - (and (integer? y) - (exact? y) - (nonnegative? y) - (= (modulo y align) 0))) - ([dy y]) - (let ([val (guard (c [#t #f]) - (generic-ref dx dy (constant native-endianness)))]) - (and val - (begin - (residualize-seq '() (list x y) ctxt) - `(quote ,val))))))))) - (define-syntax fold-bytevector-native-ref - (syntax-rules () - [(_ native-ref generic-ref align) - (define-inline 2 native-ref - [(x y) ($fold-bytevector-native-ref native-ref generic-ref align x y ctxt)])])) - (fold-bytevector-native-ref bytevector-u16-native-ref bytevector-u16-ref 2) - (fold-bytevector-native-ref bytevector-s16-native-ref bytevector-s16-ref 2) - (fold-bytevector-native-ref bytevector-u32-native-ref bytevector-u32-ref 4) - (fold-bytevector-native-ref bytevector-s32-native-ref bytevector-s32-ref 4) - (fold-bytevector-native-ref bytevector-u64-native-ref bytevector-u64-ref 8) - (fold-bytevector-native-ref bytevector-s64-native-ref bytevector-s64-ref 8)) - - (define-inline 2 expt - [(x y) - (let ([xval (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! x)) - [(quote ,d) (and (or (fixnum? d) (flonum? d)) d)] - [else #f])] - [yval (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! y)) - [(quote ,d) (and (or (and (fixnum? d) (fx< -1000 d 1000)) (flonum? d)) d)] - [else #f])]) - (and xval - yval - (or (not (eq? xval 0)) (not (fixnum? yval)) (fx>= yval 0)) - (begin - (residualize-seq '() (list x y) ctxt) - `(quote ,(expt xval yval)))))]) - - (define-inline 2 procedure? - [(x) (nanopass-case (Lsrc Expr) (result-exp/indirect-ref (value-visit-operand! x)) - [(case-lambda ,preinfo ,cl ...) - (residualize-seq '() (list x) ctxt) - true-rec] - [,pr - (residualize-seq '() (list x) ctxt) - (if (all-set? (prim-mask proc) (primref-flags pr)) true-rec #f)] - [(quote ,d) - (residualize-seq '() (list x) ctxt) - (if (procedure? d) true-rec false-rec)] - [else #f])]) - - (define-inline 2 fixnum? - [(x) (visit-and-maybe-extract* (lambda (x) #t) ([dx x]) - (residualize-seq '() (list x) ctxt) - `(quote ,(target-fixnum? dx)))]) - - (define-inline 2 bignum? - [(x) (visit-and-maybe-extract* (lambda (x) #t) ([dx x]) - (residualize-seq '() (list x) ctxt) - `(quote ,(target-bignum? dx)))]) - - (let () - (define do-inline-carry-op - (lambda (x y z base-op ctxt) - (and (okay-to-handle?) - (visit-and-maybe-extract* target-fixnum? ([dx x] [dy y] [dz z]) - (residualize-seq '() (list x y z) ctxt) - (build-primcall 3 'values - (let ([s (base-op dx dy dz)]) - (list - `(quote ,(mod0 s (expt 2 (constant fixnum-bits)))) - `(quote ,(div0 s (expt 2 (constant fixnum-bits))))))))))) - (define-syntax define-inline-carry-op - (syntax-rules () - [(_ op base-op) - (define-inline 2 op - [(x y z) (do-inline-carry-op x y z base-op ctxt)])])) - (define-inline-carry-op fx+/carry +) - (define-inline-carry-op fx-/carry -) - (define-inline-carry-op fx*/carry (lambda (x y z) (+ (* x y) z)))) - - (define-inline 3 fxdiv-and-mod - [(x y) - (and likely-to-be-compiled? - (cp0-constant? (result-exp (value-visit-operand! y))) - (cp0 - (let ([tx (cp0-make-temp #t)] [ty (cp0-make-temp #t)]) - (let ([refx (build-ref tx)] [refy (build-ref ty)]) - (build-lambda (list tx ty) - (build-primcall 3 'values - (list - (build-primcall 3 'fxdiv (list refx refy)) - (build-primcall 3 'fxmod (list refx refy))))))) - ctxt empty-env sc wd name moi))]) - - (define-inline 2 $top-level-value - [(x) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! x)) - [(quote ,d) - (cond - [(and (symbol? d) (okay-to-handle?) - (assq ($target-machine) ($cte-optimization-info d))) => - (lambda (as) - (let ([opt (cdr as)]) - (nanopass-case (Lsrc Expr) opt - [(quote ,d) - (residualize-seq '() (list x) ctxt) - opt] - [,pr - (residualize-seq '() (list x) ctxt) - opt] - [(case-lambda ,preinfo ,cl* ...) - (context-case (app-ctxt ctxt) - [(test) (residualize-seq '() (list x) ctxt) true-rec] - ; reprocess to complete inlining done in the same cp0 pass and, more - ; importantly, to rewrite any prelexes so multiple call sites don't - ; result in multiple bindings for the same prelexes - [(app) (residualize-seq '() (list x) ctxt) - (cp0 opt (app-ctxt ctxt) empty-env sc wd (app-name ctxt) moi)] - [else #f])] - [else #f])))] - [else #f])] - [else #f])]) - - (define-inline 2 $set-top-level-value! - [(x y) ; sets y's name to x if we know what symbol x is - (let ([x (result-exp (value-visit-operand! x))]) - (nanopass-case (Lsrc Expr) x - [(quote ,d) - (when (symbol? d) (operand-name-set! y d)) - #f] - [else #f]))]) - - (let () - (define (get-prtd ?parent k) - (if ?parent - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?parent)) - [(record-type ,rtd ,e) - (and (not (record-type-sealed? rtd)) (k rtd))] - [(quote ,d) - (and (or (eq? d #f) - (and (record-type-descriptor? d) - (not (record-type-sealed? d)))) - (k d))] - [else #f]) - (k #f))) - (define (get-fields ?fields k) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?fields)) - [(quote ,d) (k d)] - [else #f])) - (define (get-sealed x) - (nanopass-case (Lsrc Expr) (if x (result-exp (value-visit-operand! x)) false-rec) - [(quote ,d) (values (if d #t #f) ctrtd-sealed-known)] - [else (values #f 0)])) - ; for opaque, it's a bit more complicated: - ; no parent (parent #t) (parent #f) (parent ??) - ; (child #t) #t #t #t #t - ; (child #f) #f #t #f ?? - ; (child ??) ?? #t ?? ?? - (define (get-opaque x prtd) - (if (and prtd (record-type-opaque? prtd)) - (values #t ctrtd-opaque-known) - (nanopass-case (Lsrc Expr) (if x (result-exp (value-visit-operand! x)) false-rec) - [(quote ,d) - (if d - (values #t ctrtd-opaque-known) - (if (and (not d) (or (not prtd) (and (record-type-opaque-known? prtd) (not (record-type-opaque? prtd))))) - (values #f ctrtd-opaque-known) - (values #f 0)))] - [else (values #f 0)]))) - (let () - (define (mrt ?parent ?name ?fields maybe-?sealed maybe-?opaque ctxt level prim primname opnd*) - (or (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?name)) - [(quote ,d) - (and (gensym? d) - (let ([objs (objs-if-constant (value-visit-operands! opnd*))]) - (and objs - (let ([rtd (guard (c [#t #f]) (apply prim objs))]) - (and rtd - (begin - (residualize-seq '() opnd* ctxt) - `(quote ,rtd)))))))] - [else #f]) - (get-prtd ?parent - (lambda (prtd) - (get-fields ?fields - (lambda (fields) - (let-values ([(sealed? sealed-flag) (get-sealed maybe-?sealed)] - [(opaque? opaque-flag) (get-opaque maybe-?opaque prtd)]) - (cond - [(guard (c [#t #f]) - ($make-record-type base-ctrtd prtd "tmp" fields - sealed? opaque? (fxlogor sealed-flag opaque-flag))) => - (lambda (ctrtd) - (residualize-seq opnd* '() ctxt) - `(record-type ,ctrtd - ,(build-primcall (app-preinfo ctxt) level primname - (value-visit-operands! opnd*))))] - [else #f])))))))) - - (define-inline 2 make-record-type - [(?name ?fields) - (mrt #f ?name ?fields #f #f ctxt level make-record-type 'make-record-type - (list ?name ?fields))] - [(?parent ?name ?fields) - (mrt ?parent ?name ?fields #f #f ctxt level make-record-type 'make-record-type - (list ?parent ?name ?fields))]) - - (define-inline 2 $make-record-type - [(?base-id ?parent ?name ?fields ?sealed ?opaque . ?extras) - (mrt ?parent ?name ?fields ?sealed ?opaque ctxt level $make-record-type '$make-record-type - (list* ?base-id ?parent ?name ?fields ?sealed ?opaque ?extras))])) - (let () - (define (mrtd ?parent ?uid ?fields ?sealed ?opaque ctxt level prim primname opnd*) - (or (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?uid)) - [(quote ,d) - (and d - (let ([objs (objs-if-constant (value-visit-operands! opnd*))]) - (and objs - (let ([rtd (guard (c [#t #f]) (apply prim objs))]) - (and rtd - (begin - (residualize-seq '() opnd* ctxt) - `(quote ,rtd)))))))] - [else #f]) - (get-prtd ?parent - (lambda (prtd) - (get-fields ?fields - (lambda (fields) - (let-values ([(sealed? sealed-flag) (get-sealed ?sealed)] - [(opaque? opaque-flag) (get-opaque ?opaque prtd)]) - (cond - [(guard (c [#t #f]) - ($make-record-type-descriptor base-ctrtd 'tmp prtd #f - sealed? opaque? fields 'cp0 (fxlogor sealed-flag opaque-flag))) => - (lambda (rtd) - (residualize-seq opnd* '() ctxt) - `(record-type ,rtd - ; can't use level 3 unconditionally because we're missing checks for - ; ?base-rtd, ?name, ?uid, ?who, and ?extras - ,(build-primcall (app-preinfo ctxt) level primname - (value-visit-operands! opnd*))))] - [else #f])))))))) - - (define-inline 2 make-record-type-descriptor - [(?name ?parent ?uid ?sealed ?opaque ?fields) - (mrtd ?parent ?uid ?fields ?sealed ?opaque ctxt level - make-record-type-descriptor 'make-record-type-descriptor - (list ?name ?parent ?uid ?sealed ?opaque ?fields))]) - - (define-inline 2 $make-record-type-descriptor - [(?base-rtd ?name ?parent ?uid ?sealed ?opaque ?fields ?who . ?extras) - (mrtd ?parent ?uid ?fields ?sealed ?opaque ctxt level - $make-record-type-descriptor '$make-record-type-descriptor - (list* ?base-rtd ?name ?parent ?uid ?sealed ?opaque ?fields ?who ?extras))]))) - (let () - ; if you update this, also update duplicate in record.ss - (define-record-type rcd - (fields (immutable rtd) (immutable prcd) (immutable protocol)) - (nongenerative #{rcd qh0yzh5qyrxmz2l-a}) - (sealed #t)) - - (define-record-type ctrcd - (fields (immutable rtd) (immutable ctprcd) (immutable protocol-expr)) - (nongenerative) - (sealed #t)) - (define (rcd->ctrcd rcd) - (make-ctrcd (rcd-rtd rcd) - (let ([prcd (rcd-prcd rcd)]) (and prcd (rcd->ctrcd prcd))) - `(quote ,(rcd-protocol rcd)))) - - (define finish - (lambda (ctxt sc wd moi expr) - (and expr - ; in app context, keep the inlining ball rolling. - (context-case (app-ctxt ctxt) - [(app) (cp0 expr (app-ctxt ctxt) empty-env sc wd (app-name ctxt) moi)] - [else expr])))) - - (let () - (define (get-rtd ?rtd k) - (let ([expr (result-exp (value-visit-operand! ?rtd))]) - (nanopass-case (Lsrc Expr) expr - [(quote ,d) - (and (record-type-descriptor? d) - (eqv? (rtd-pm d) -1) ; all ptrs - (k d expr))] - [(record-type ,rtd (ref ,maybe-src ,x)) - (and (eqv? (rtd-pm rtd) -1) ; all ptrs - (k rtd `(ref ,maybe-src ,x)))] - [else #f]))) - (define (get-prcd ?prcd rtd k) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?prcd)) - [(record-cd ,rcd ,rtd-expr ,e) - (and (eq? (ctrcd-rtd rcd) (record-type-parent rtd)) - (nanopass-case (Lsrc Expr) (ctrcd-protocol-expr rcd) - [(ref ,maybe-src ,x) #t] - [(quote ,d) (or (eq? d #f) (procedure? d))] - [else #f]) - (k rcd))] - [(quote ,d) - (if (eq? d #f) - (k #f) - (and (record-constructor-descriptor? d) - (eq? (rcd-rtd d) (record-type-parent rtd)) - (k (rcd->ctrcd d))))] - [else #f])) - ; record-cd form contains: - ; - compile-time rcd - ; - expression to access run-time rtd (quote or ref) - ; - expression to create run-time rcd (primcall) - ; compile-time rcd contains: - ; - compile- or run-time rtd - ; - compile-time parent rcd or #f - ; - protocol expression (quote or ref) - (define (mrcd ?rtd ?prcd ?protocol ctxt sc wd name moi level prim primname opnd*) - (or (let ([objs (objs-if-constant (value-visit-operands! opnd*))]) - (and objs - (let ([rcd (guard (c [#t #f]) (apply prim objs))]) - (and rcd - (begin - (residualize-seq '() opnd* ctxt) - `(quote ,rcd)))))) - (get-rtd ?rtd - (lambda (rtd rtd-expr) - (get-prcd ?prcd rtd - (lambda (pctrcd) - (define (opnd-lambda? opnd) - (and opnd - (nanopass-case (Lsrc Expr) (if (operand-value opnd) - (result-exp (operand-value opnd)) - (operand-exp opnd)) - [(case-lambda ,preinfo ,cl* ...) #t] - [(seq (profile ,src) (case-lambda ,preinfo ,cl* ...)) #t] - [else #f]))) - (let* ([whole-protocol-expr (value-visit-operand! ?protocol)] - [result-protocol-expr (result-exp whole-protocol-expr)]) - (cond - [(nanopass-case (Lsrc Expr) result-protocol-expr - [(quote ,d) (and (or (eq? d #f) (procedure? d)) 3)] - [(ref ,maybe-src ,x) - (and (not (prelex-was-assigned x)) - (if (opnd-lambda? (prelex-operand x)) 3 level))] - [else #f]) => - (lambda (level) - (residualize-seq opnd* '() ctxt) - `(record-cd - ,(make-ctrcd rtd pctrcd result-protocol-expr) - ,rtd-expr - ,(build-primcall (app-preinfo ctxt) level primname - (value-visit-operands! opnd*))))] - [(nanopass-case (Lsrc Expr) result-protocol-expr - [(case-lambda ,preinfo ,cl* ...) #t] - [else #f]) - ; if the protocol expression is a lambda expression, we - ; pull it out into an enclosing let, which can then be - ; assimilated outward, by value-visit-operand!, into - ; the form binding a variable to the rcd, if any, making - ; it visible and available for inlining wherever the rcd - ; is used. - (residualize-seq opnd* '() ctxt) - (let ([t (cp0-make-temp #t)]) - (build-let (list t) (list whole-protocol-expr) - `(record-cd - ,(make-ctrcd rtd pctrcd (build-ref t)) - ,rtd-expr - ,(build-primcall (app-preinfo ctxt) 3 primname - (map - (lambda (opnd) (if (eq? opnd ?protocol) (build-ref t) (value-visit-operand! opnd))) - opnd*)))))] - [else #f])))))))) - - (define-inline 2 make-record-constructor-descriptor - [(?rtd ?prcd ?protocol) - (mrcd ?rtd ?prcd ?protocol ctxt sc wd name moi level - make-record-constructor-descriptor 'make-record-constructor-descriptor - (list ?rtd ?prcd ?protocol))]) - - (define-inline 2 $make-record-constructor-descriptor - [(?rtd ?prcd ?protocol ?who) - (mrcd ?rtd ?prcd ?protocol ctxt sc wd name moi level - $make-record-constructor-descriptor '$make-record-constructor-descriptor - (list ?rtd ?prcd ?protocol ?who))])) - - (let () - (define (get-rtd ?rtd k1 k2) - (let ([expr (result-exp (value-visit-operand! ?rtd))]) - (nanopass-case (Lsrc Expr) expr - [(quote ,d) (and (record-type-descriptor? d) (k1 d expr))] - [(record-type ,rtd ,e) - (nanopass-case (Lsrc Expr) e - [(ref ,maybe-src ,x) (k1 rtd e)] - [else (k2 rtd e)])] - [else #f]))) - (define-inline 2 record-predicate - [(?rtd) - (and likely-to-be-compiled? - (get-rtd ?rtd - ; k1: no let needed - (lambda (rtd rtd-expr) - (residualize-seq '() (list ?rtd) ctxt) - (finish ctxt sc wd moi - (let ([t (cp0-make-temp #f)]) - (build-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) (list t) - (build-primcall 3 - (if (record-type-sealed? rtd) '$sealed-record? 'record?) - (list (build-ref t) rtd-expr)))))) - ; k2: let needed - (lambda (rtd rtd-expr) - (residualize-seq (list ?rtd) '() ctxt) - (finish ctxt sc wd moi - (let ([rtd-t (cp0-make-temp #f)] [t (cp0-make-temp #f)]) - (build-let (list rtd-t) (list (operand-value ?rtd)) - (build-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) (list t) - (build-primcall 3 - (if (record-type-sealed? rtd) '$sealed-record? 'record?) - (list (build-ref t) (build-ref rtd-t))))))))))])) - - (let () - (define type->pred - (lambda (who real-type val-t) - (define-syntax pred - (lambda (x) - (syntax-case x () - [(_ type bytes pred) - (if (memq (datum type) '(scheme-object boolean)) - #'($oops who "unexpected type ~s" 'type) - #'(build-primcall 3 'pred - (list (build-ref val-t))))]))) - (record-datatype cases real-type pred - ($oops who "unrecognized type ~s" real-type)))) - - (let () - (define (go safe? rtd rtd-e ctxt) - (let* ([fld* (rtd-flds rtd)] - [t* (map (lambda (x) (cp0-make-temp #t)) fld*)] - [check* (if safe? - (fold-right - (lambda (fld t check*) - (let* ([type (fld-type fld)] - [real-type (filter-foreign-type type)]) - (if (memq real-type '(scheme-object boolean)) - check* - (cons - `(if ,(type->pred 'record-constructor real-type t) - ,void-rec - ,(build-primcall 3 'assertion-violationf - (list `(moi) - `(quote ,(format "invalid value ~~s for foreign type ~s" type)) - (build-ref t)))) - check*)))) - '() fld* t*) - '())]) - (build-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) t* - (let ([expr `(record ,rtd ,rtd-e ,(map build-ref t*) ...)]) - (if (null? check*) - expr - (make-seq 'value (make-seq* 'effect check*) expr)))))) - - (let () - ; When the record type is a base type, r6rs:record-constructor produces: - ; (prot ; protocol - ; (lambda (X1 ... Xn) ; n = # fields - ; (record rtd X1 ... Xn))) - ; This presents no problems for the inliner. When the record type is a not - ; a base type (no parent), however, it produces: - ; (cprot ; child protocol - ; (lambda pp-args ; number of pp-args is unknown, hence rest interface ... - ; (lambda (C1 ... Cc) ; c = #child fields - ; (apply ; ... and apply - ; (pprot - ; (lambda (P1 ... Pp) ; p = #parent fields - ; (record rtd P1 ... Pp C1 ... Cc))) - ; pp-args)))) - ; with the inner part replicated for the grandparent, great-grandparent, etc. - ; - ; We could try to analyze pprot to figure out how many arguments the - ; procedure returned by pprot takes. We might not be able to do so, and it - ; might turn out it's a case-lambda with several interfaces. Even if we do - ; determine the exact number(s) of arguments, the (lambda pp-args ---) - ; procedure must still accept any number of arguments, since an - ; argument-count error signaled by the (lambda pp-args ---) procedure would - ; come too early. Similarly, we could try to figure out how many arguments - ; cprot passes to the (lambda pp-args ---) procedure, but this would also be - ; difficult and possibly not helpful. Instead, we mark pp-args as - ; containing an immutable value. If (as is typical) the call to (lambda - ; pp-args procedure) becomes evident during inlining, the operand of pp-args - ; becomes an "immutable list" record (in find-call-lambda-clause). If (as - ; again is typical) the apply of the procedure returned by pprot also - ; becomes evident during inlining, it is expanded as usual into a series of - ; car/cdr calls, which are folded when car and cdr see that the argument is - ; an immutable list record. - (define (try-rcd level ?rcd ctxt sc wd name moi) - (define (get-rcd ?rcd k) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?rcd)) - [(record-cd ,rcd ,rtd-expr ,e) (k rcd rtd-expr)] - [(quote ,d) - (and (record-constructor-descriptor? d) - (k (rcd->ctrcd d) `(quote ,(rcd-rtd d))))] - [else #f])) - (get-rcd ?rcd - (lambda (ctrcd rtd-e) - ; Convert call to r6rs:record-constructor into a call to a lambda - ; expression that ignores its argument...this causes the code we - ; generate to be processed before it is set up as a potential - ; operand value for inlining. In particular, if the protocol - ; expr is a variable bound to a procedure, this allows the protocol - ; call we generate to be inlined, exposing the lambda expression - ; within it for use in inlining calls to the resulting constructor. - (cp0 - (build-lambda (list (make-prelex*)) ; unreferenced temp - (let ([rtd (ctrcd-rtd ctrcd)] - [protocol-expr (ctrcd-protocol-expr ctrcd)]) - (if (cp0-constant? (lambda (x) (eq? x #f)) protocol-expr) - (go (< level 3) rtd rtd-e ctxt) - `(call ,(app-preinfo ctxt) ,protocol-expr - ,(cond - [(record-type-parent rtd) => - (lambda (prtd) - (let f ([ctprcd (ctrcd-ctprcd ctrcd)] [crtd rtd] [prtd prtd] [vars '()]) - (let ([pp-args (cp0-make-temp #f)] - [new-vars (map (lambda (x) (cp0-make-temp #f)) - (vector->list (record-type-field-names crtd)))]) - (set-prelex-immutable-value! pp-args #t) - `(case-lambda ,(make-preinfo-lambda) - (clause (,pp-args) -1 - ,(build-lambda new-vars - (let ([vars (append new-vars vars)]) - (build-primcall level 'apply - (list - (cond - [(and ctprcd - (let ([protocol-expr (ctrcd-protocol-expr ctprcd)]) - (and (not (cp0-constant? - (lambda (x) (eq? x #f)) - protocol-expr)) - protocol-expr))) => - (lambda (protocol-expr) - `(call ,(app-preinfo ctxt) ,protocol-expr - ,(cond - [(rtd-parent prtd) => - (lambda (pprtd) - (f (ctrcd-ctprcd ctprcd) prtd pprtd vars))] - [else - (let ([new-vars (map (lambda (x) (cp0-make-temp #f)) - (csv7:record-type-field-names prtd))]) - (build-lambda new-vars - `(call ,(app-preinfo ctxt) ,(go (< level 3) rtd rtd-e ctxt) - ,(map build-ref (append new-vars vars)) - ...)))])))] - [else - (let ([new-vars (map (lambda (x) (cp0-make-temp #f)) - (csv7:record-type-field-names prtd))]) - (build-lambda new-vars - `(call ,(app-preinfo ctxt) ,(go (< level 3) rtd rtd-e ctxt) - ,(map build-ref (append new-vars vars)) ...)))]) - (build-ref pp-args))))))))))] - [else (go (< level 3) rtd rtd-e ctxt)]))))) - ctxt empty-env sc wd name moi)))) - - (define-inline 2 record-constructor - [(?rtd/rcd) - (and likely-to-be-compiled? - (cond - [(let ([x (result-exp (value-visit-operand! ?rtd/rcd))]) - (nanopass-case (Lsrc Expr) x - [(quote ,d) (and (record-type-descriptor? d) (cons d x))] - [(record-type ,rtd (ref ,maybe-src ,x)) (cons rtd `(ref ,maybe-src ,x))] - [else #f])) => - (lambda (rtd.rtd-e) - (residualize-seq '() (list ?rtd/rcd) ctxt) - (finish ctxt sc wd moi (go (< level 3) (car rtd.rtd-e) (cdr rtd.rtd-e) ctxt)))] - [(nanopass-case (Lsrc Expr) (result-exp (operand-value ?rtd/rcd)) - [(record-type ,rtd ,e) rtd] - [else #f]) => - (lambda (rtd) - (residualize-seq (list ?rtd/rcd) '() ctxt) - (let ([rtd-t (cp0-make-temp #f)]) - (build-let (list rtd-t) (list (operand-value ?rtd/rcd)) - (finish ctxt sc wd moi (go (< level 3) rtd (build-ref rtd-t) ctxt)))))] - [else (try-rcd level ?rtd/rcd ctxt sc wd name moi)]))]) - - (define-inline 2 r6rs:record-constructor - [(?rcd) - (and likely-to-be-compiled? - (try-rcd level ?rcd ctxt sc wd name moi))]))) - - (let () - (define (find-fld ?field rtd-e rtd k) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?field)) - [(quote ,d) - (cond - [(symbol? d) - ; reverse order to check child's fields first - (let loop ([flds (reverse (rtd-flds rtd))] [index (length (rtd-flds rtd))]) - (let ([index (fx- index 1)]) - (and (not (null? flds)) - (let ([fld (car flds)]) - (if (eq? d (fld-name fld)) - (k rtd-e rtd fld index) - (loop (cdr flds) index))))))] - [(fixnum? d) - (let ((flds (rtd-flds rtd))) - (and ($fxu< d (length flds)) - (k rtd-e rtd (list-ref flds d) d)))] - [else #f])] - [else #f])) - - (define (r6rs:find-fld ?field rtd-e rtd k) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?field)) - [(quote ,d) - (let ([flds (rtd-flds rtd)] [prtd (rtd-parent rtd)]) - (let ([index (if prtd (+ d (length (rtd-flds prtd))) d)]) - (and ($fxu< index (length flds)) - (k rtd-e rtd (list-ref flds index) index))))] - [else #f])) - - (define (find-rtd-and-field ?rtd ?field find-fld k) - (let ([x (result-exp (value-visit-operand! ?rtd))]) - (nanopass-case (Lsrc Expr) x - [(quote ,d) - (and (record-type-descriptor? d) (find-fld ?field x d k))] - [(record-type ,rtd ,e) - (find-fld ?field e rtd k)] - [else #f]))) - - (let () - (define (rfa ?rtd ?field level ctxt find-fld) - (and likely-to-be-compiled? - (find-rtd-and-field ?rtd ?field find-fld - (lambda (rtd-e rtd fld index) - ; assuming all fields are accessible - (let ([rec-t (cp0-make-temp #t)]) - (let ([expr `(record-ref ,rtd ,(fld-type fld) ,index (ref #f ,rec-t))]) - (cond - [(fx= level 3) - (residualize-seq '() (list ?rtd ?field) ctxt) - (build-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) (list rec-t) expr)] - [(nanopass-case (Lsrc Expr) rtd-e - [(quote ,d) #t] - [(ref ,maybe-src ,x) #t] - [else #f]) - (residualize-seq '() (list ?rtd ?field) ctxt) - (build-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) (list rec-t) - `(seq - (if ,(build-primcall 3 'record? - (list (build-ref rec-t) rtd-e)) - ,void-rec - ,(build-primcall 3 '$record-oops - (list (let ([name (app-name ctxt)]) - (if name `(quote ,name) `(moi))) - (build-ref rec-t) - rtd-e))) - ,expr))] - [else - (let ([rtd-t (cp0-make-temp #t)]) - (residualize-seq (list ?rtd) (list ?field) ctxt) - (build-let (list rtd-t) (list (operand-value ?rtd)) - (build-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) (list rec-t) - `(seq - (if ,(build-primcall 3 'record? - (list (build-ref rec-t) (build-ref rtd-t))) - ,void-rec - ,(build-primcall 3 '$record-oops - (list (let ([name (app-name ctxt)]) - (if name `(quote ,name) `(moi))) - (build-ref rec-t) - (build-ref rtd-t)))) - ,expr))))]))))))) - (define-inline 2 csv7:record-field-accessor - [(?rtd ?field) (finish ctxt sc wd moi (rfa ?rtd ?field level ctxt find-fld))]) - (define-inline 2 record-accessor - [(?rtd ?field) (finish ctxt sc wd moi (rfa ?rtd ?field level ctxt r6rs:find-fld))])) - - (let () - (define (rfm ?rtd ?field level ctxt who find-fld) - (and likely-to-be-compiled? - (find-rtd-and-field ?rtd ?field find-fld - (lambda (rtd-e rtd fld index) - (and (fld-mutable? fld) - (let* ([type (fld-type fld)] - [real-type (filter-foreign-type type)] - [rec-t (cp0-make-temp #t)] - [val-t (cp0-make-temp #t)]) - (let ([expr `(record-set! ,rtd ,type ,index (ref #f ,rec-t) (ref #f ,val-t))] - [pred (and (not (memq real-type '(scheme-object boolean))) - (type->pred who real-type val-t))]) - (cond - [(fx= level 3) - (residualize-seq '() (list ?rtd ?field) ctxt) - (build-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) - (list rec-t val-t) - expr)] - [(nanopass-case (Lsrc Expr) rtd-e - [(quote ,d) #t] - [(ref ,maybe-src ,x) #t] - [else #f]) - (residualize-seq '() (list ?rtd ?field) ctxt) - (build-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) - (list rec-t val-t) - (make-seq 'value - `(if ,(build-primcall 3 'record? - (list (build-ref rec-t) rtd-e)) - ,void-rec - ,(build-primcall 3 '$record-oops - (list (let ([name (app-name ctxt)]) - (if name `(quote ,name) `(moi))) - (build-ref rec-t) - rtd-e))) - (if pred - (make-seq 'value - `(if ,pred ,void-rec - ,(build-primcall 3 'assertion-violationf - (list (let ([name (app-name ctxt)]) - (if name `(quote ,name) `(moi))) - `(quote ,(format "invalid value ~~s for foreign type ~s" type)) - (build-ref val-t)))) - expr) - expr)))] - [else - (let ([rtd-t (cp0-make-temp #t)]) - (residualize-seq (list ?rtd) (list ?field) ctxt) - (build-let (list rtd-t) (list (operand-value ?rtd)) - (build-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) - (list rec-t val-t) - (make-seq 'value - `(if ,(build-primcall 3 'record? - (list (build-ref rec-t) (build-ref rtd-t))) - ,void-rec - ,(build-primcall 3 '$record-oops - (list (let ([name (app-name ctxt)]) - (if name `(quote ,name) `(moi))) - (build-ref rec-t) - (build-ref rtd-t)))) - (if pred - (make-seq 'value - `(if ,pred ,void-rec - ,(build-primcall 3 'assertion-violationf - (list (let ([name (app-name ctxt)]) - (if name `(quote ,name) `(moi))) - `(quote ,(format "invalid value ~~s for foreign type ~s" type)) - (build-ref val-t)))) - expr) - expr)))))])))))))) - (define-inline 2 csv7:record-field-mutator - [(?rtd ?field) (finish ctxt sc wd moi (rfm ?rtd ?field level ctxt 'record-field-mutator find-fld))]) - (define-inline 2 record-mutator - [(?rtd ?field) (finish ctxt sc wd moi (rfm ?rtd ?field level ctxt 'record-mutator r6rs:find-fld))])) - - (define-inline 2 csv7:record-field-accessible? - [(?rtd ?field) - ; always true, but first verify that rtd & field are valid to avoid suppressing run-time errors - (find-rtd-and-field ?rtd ?field find-fld - (lambda (rtd-e rtd fld index) - (residualize-seq '() (list ?rtd ?field) ctxt) - true-rec))]) - - (let () - (define (rfm? ?rtd ?field ctxt find-fld) - (find-rtd-and-field ?rtd ?field find-fld - (lambda (rtd-e rtd fld index) - (residualize-seq '() (list ?rtd ?field) ctxt) - `(quote ,(fld-mutable? fld))))) - (define-inline 2 csv7:record-field-mutable? - [(?rtd ?field) (rfm? ?rtd ?field ctxt find-fld)]) - (define-inline 2 record-field-mutable? - [(?rtd ?field) (rfm? ?rtd ?field ctxt r6rs:find-fld)])))) - ) - - (define-inline 2 (csv7:record-type-descriptor record-rtd) - [(?record) - (let ([x (value-visit-operand! ?record)]) - (nanopass-case (Lsrc Expr) (result-exp/indirect-ref x) - ; could handle record-type forms if ctrtd recorded rtdrtd (a ctrtd's rtd is always base-ctrtd) - [(record ,rtd ,rtd-expr ,e* ...) - (and (not (record-type-opaque? rtd)) - (if (ctrtd? rtd) - (begin - (residualize-seq (list ?record) '() ctxt) - `(record-type ,rtd - ,(build-primcall (app-preinfo ctxt) level prim-name - (list x)))) - (begin - (residualize-seq '() (list ?record) ctxt) - `(quote ,rtd))))] - [(quote ,d) - (and (record? d) - (begin - (residualize-seq '() (list ?record) ctxt) - `(quote ,(record-rtd d))))] - [else #f]))]) - - (define-inline 2 record-type-descriptor? - [(?x) - (cond - [(nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?x)) - [(record-type ,rtd ,e) #t] - [(quote ,d) (record-type-descriptor? d)] - [else #f]) - (residualize-seq '() (list ?x) ctxt) - true-rec] - [else #f])]) - - (define-inline 2 record-constructor-descriptor? - [(?x) - (cond - [(nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?x)) - [(record-cd ,rcd ,rtd-expr ,e) #t] - [(quote ,d) (record-constructor-descriptor? d)] - [else #f]) - (residualize-seq '() (list ?x) ctxt) - true-rec] - [else #f])]) - - (define-inline 2 record-type-sealed? - [(?rtd) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?rtd)) - [(record-type ,rtd ,e) - (and (record-type-sealed-known? rtd) - (begin - (residualize-seq '() (list ?rtd) ctxt) - (if (record-type-sealed? rtd) true-rec false-rec)))] - [(quote ,d) - (and (record-type-descriptor? d) - (begin - (residualize-seq '() (list ?rtd) ctxt) - `(quote ,(record-type-sealed? d))))] - [else #f])]) - - (define-inline 2 record-type-opaque? - [(?rtd) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?rtd)) - [(record-type ,rtd ,e) - (and (record-type-opaque-known? rtd) - (begin - (residualize-seq '() (list ?rtd) ctxt) - (if (record-type-opaque? rtd) true-rec false-rec)))] - [(quote ,d) - (and (record-type-descriptor? d) - (begin - (residualize-seq '() (list ?rtd) ctxt) - `(quote ,(record-type-opaque? d))))] - [else #f])]) - - (let () - (define definitely-not-a-record? - (lambda (xres) - (nanopass-case (Lsrc Expr) xres - [(case-lambda ,preinfo ,cl ...) #t] - [,pr (all-set? (prim-mask proc) (primref-flags pr))] - [(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) #t] - [(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type) #t] - [(record-set! ,rtd ,type ,index ,e1 ,e2) #t] - [(immutable-list (,e* ...) ,e) #t] - [else #f]))) - (define one-arg-case - (lambda (?x ctxt) - (let ([xres (result-exp/indirect-ref (value-visit-operand! ?x))]) - (nanopass-case (Lsrc Expr) xres - [(quote ,d) - (residualize-seq '() (list ?x) ctxt) - (if (record? d) true-rec false-rec)] - ; could handle record-type forms if ctrtd recorded rtdrtd so we can check opacity (a ctrtd's rtd is always base-ctrtd) - [(record ,rtd ,rtd-expr ,e* ...) - (and (record-type-opaque-known? rtd) - (begin - (residualize-seq '() (list ?x) ctxt) - (if (record-type-opaque? rtd) false-rec true-rec)))] - [else (and (definitely-not-a-record? xres) - (begin - (residualize-seq '() (list ?x) ctxt) - false-rec))])))) - (define-inline 2 r6rs:record? - [(?x) (one-arg-case ?x ctxt)]) - (define-inline 2 record? - [(?x) (one-arg-case ?x ctxt)] - [(?x ?rtd) - (let ([rtdval (value-visit-operand! ?rtd)]) - (define abandon-ship - (lambda (xval xres maybe-rtd) - (if (definitely-not-a-record? xres) - (begin - (residualize-seq '() (list ?x ?rtd) ctxt) - false-rec) - (and maybe-rtd - (begin - (residualize-seq (list ?x ?rtd) '() ctxt) - (build-primcall (app-preinfo ctxt) 3 - (if (record-type-sealed? maybe-rtd) - '$sealed-record? - 'record?) - (list xval rtdval))))))) - (define obviously-incompatible? - (lambda (instance-rtd rtd) - (let f ([ls1 (rtd-flds instance-rtd)] [ls2 (rtd-flds rtd)]) - (if (null? ls2) - (if (record-type-parent instance-rtd) - ; could work harder here, though it gets trickier (so not obvious)... - #f - ; instance has no parent, so rtds are compatible only if they are the same modulo incomplete info if one or both are ctrtds - (or (not (null? ls1)) - (and (record-type-parent rtd) #t) - (and (and (record-type-sealed-known? rtd) (record-type-sealed-known? instance-rtd)) - (not (eq? (record-type-sealed? instance-rtd) (record-type-sealed? rtd)))) - (and (and (record-type-opaque-known? rtd) (record-type-opaque-known? instance-rtd)) - (not (eq? (record-type-opaque? instance-rtd) (record-type-opaque? rtd)))))) - (or (null? ls1) - (not (equal? (car ls1) (car ls2))) - (f (cdr ls1) (cdr ls2))))))) - (nanopass-case (Lsrc Expr) (result-exp rtdval) - [(quote ,d0) - (and (record-type-descriptor? d0) - (let ([xval (value-visit-operand! ?x)]) - (let ([xres (result-exp/indirect-ref xval)]) - (nanopass-case (Lsrc Expr) xres - [(quote ,d1) - ; could also return #f here and let folding happen - (residualize-seq '() (list ?x ?rtd) ctxt) - (if (record? d1 d0) true-rec false-rec)] - ; could handle record-type forms if ctrtd recorded rtdrtd (a ctrtd's rtd is always base-ctrtd) - [(record ,rtd ,rtd-expr ,e* ...) - (guard (let f ([rtd rtd]) - (or (eq? rtd d0) - (let ([rtd (record-type-parent rtd)]) - (and rtd (f rtd)))))) - (residualize-seq '() (list ?x ?rtd) ctxt) - true-rec] - [else (abandon-ship xval xres d0)]))))] - [(record-type ,rtd ,e) - (cond - [(nanopass-case (Lsrc Expr) (result-exp/indirect-ref (value-visit-operand! ?x)) - [(record ,rtd2 ,rtd-expr ,e* ...) - (let f ([rtd2 rtd2]) - (or (eq? rtd2 rtd) - (let ([rtd2 (record-type-parent rtd2)]) - (and rtd2 (f rtd2)))))] - [else #f]) - (residualize-seq '() (list ?x ?rtd) ctxt) - true-rec] - [(nanopass-case (Lsrc Expr) (result-exp/indirect-ref (value-visit-operand! ?x)) - [(quote ,d1) - (and (record? d1) (obviously-incompatible? (record-rtd d1) rtd))] - ; could handle record-type forms if ctrtd recorded rtdrtd (a ctrtd's rtd is always base-ctrtd) - [(record ,rtd2 ,rtd-expr ,e* ...) - (obviously-incompatible? rtd2 rtd)] - [else #f]) - (residualize-seq '() (list ?x ?rtd) ctxt) - false-rec] - [else - (let ([xval (value-visit-operand! ?x)]) - (abandon-ship xval (result-exp/indirect-ref xval) rtd))])] - [else - (and (fx= level 3) - (let ([xval (value-visit-operand! ?x)]) - (abandon-ship xval (result-exp/indirect-ref xval) #f)))]))])) - - (define-inline 2 csv7:record-type-field-names - [(?rtd) - (cond - [(nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?rtd)) - [(record-type ,rtd ,e) rtd] - [(quote ,d) (and (record-type-descriptor? d) d)] - [else #f]) => - (lambda (rtd) - (residualize-seq '() (list ?rtd) ctxt) - `(quote ,(csv7:record-type-field-names rtd)))] - [else #f])]) - - (define-inline 2 record-type-field-names - [(?rtd) - (cond - [(nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?rtd)) - [(record-type ,rtd ,e) rtd] - [(quote ,d) (and (record-type-descriptor? d) d)] - [else #f]) => - (lambda (rtd) - (residualize-seq '() (list ?rtd) ctxt) - `(quote ,(record-type-field-names rtd)))] - [else #f])]) - - (define-inline 2 csv7:record-type-field-decls - [(?rtd) - (cond - [(nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?rtd)) - [(record-type ,rtd ,e) rtd] - [(quote ,d) (and (record-type-descriptor? d) d)] - [else #f]) => - (lambda (rtd) - (residualize-seq '() (list ?rtd) ctxt) - `(quote ,(csv7:record-type-field-decls rtd)))] - [else #f])]) - - (define-inline 2 csv7:record-type-name - ; don't look for record-type case, since rtd may be a temporary - ; rtd cons'd up by cp0 - [(?rtd) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?rtd)) - [(quote ,d) - (and (record-type-descriptor? d) - (begin - (residualize-seq '() (list ?rtd) ctxt) - `(quote ,(csv7:record-type-name d))))] - [else #f])]) - - (define-inline 2 record-type-name - ; don't look for record-type case, since rtd may be a temporary - ; rtd cons'd up by cp0 - [(?rtd) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?rtd)) - [(quote ,d) - (and (record-type-descriptor? d) - (begin - (residualize-seq '() (list ?rtd) ctxt) - `(quote ,(record-type-name d))))] - [else #f])]) - - (define-inline 2 record-type-parent - ; don't look for record-type case, since parent may be a temporary - ; rtd cons'd up by cp0 - [(?rtd) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?rtd)) - [(quote ,d) - (and (record-type-descriptor? d) - (begin - (residualize-seq '() (list ?rtd) ctxt) - `(quote ,(record-type-parent d))))] - [else #f])]) - - (define-inline 2 (csv7:record-type-symbol record-type-uid) - ; don't look for record-type case, since rtd may be a temporary - ; rtd cons'd up by cp0 - [(?rtd) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?rtd)) - [(quote ,d) - (and (record-type-descriptor? d) - (begin - (residualize-seq '() (list ?rtd) ctxt) - `(quote ,(record-type-uid d))))] - [else #f])]) - - (define-inline 2 $record - [(?rtd . ?e*) - (let ([rtd-expr (value-visit-operand! ?rtd)]) - (nanopass-case (Lsrc Expr) (result-exp rtd-expr) - [(quote ,d) - (and (record-type-descriptor? d) - (if (andmap (lambda (fld) (not (fld-mutable? fld))) (rtd-flds d)) - (let ([e* (objs-if-constant (value-visit-operands! ?e*))]) - (and e* - (begin - (residualize-seq '() (cons ?rtd ?e*) ctxt) - `(quote ,(apply $record d e*))))) - (begin - (residualize-seq (cons ?rtd ?e*) '() ctxt) - `(record ,d ,rtd-expr ,(map value-visit-operand! ?e*) ...))))] - [(record-type ,rtd ,e) - (begin - (residualize-seq (cons ?rtd ?e*) '() ctxt) - `(record ,rtd ,rtd-expr ,(map value-visit-operand! ?e*) ...))] - [else #f]))]) - - (let () - (define null-rec? - (lambda (?ls) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?ls)) - [(quote ,d) (null? d)] - [(call ,preinfo ,e ,e* ...) - ; check also for `(list)`. It should have been reduced to `(quote ())` before, - ; but cp0 isn't guaranteed to reach a fixed point. - (and (primref? e) (eq? (primref-name e) 'list) (null? e*))] - [else #f]))) - (define inline-lists - (lambda (?p ?ls ?ls* lvl map? ctxt sc wd name moi) - ; (map/for-each proc (list a11 a12 ... a1m) (list a21 a22 ... a2m) ... (list an1 an2 ... anm)) => - ; (let ([p proc]) - ; (if (procedure? p) - ; (void) - ; ($oops 'map/for-each "~s is not a procedure" p)) - ; (let ([t11 a11] ... [t1m a1m]) - ; ... - ; (let ([tn1 an1] ... [tnm anm]) - ; (list/begin (p t11 ... tn1) - ; (p t12 ... tn2) - ; ... - ; (p t1m ... tnm))))) - (let loop ([ls* (cons ?ls ?ls*)] [e** '()] [all-quoted? #t]) - (if (null? ls*) - (and (apply = (map length e**)) - (or (not all-quoted?) (fx<= (length (car e**)) 4)) - (let ([p (cp0-make-temp (or (fx= lvl 2) (fx> (length (car e**)) 1)))] - [temp** (map (lambda (e*) - (map (lambda (x) (cp0-make-temp #f)) e*)) - e**)]) - (residualize-seq (list* ?p ?ls ?ls*) '() ctxt) - (build-let (list p) (list (value-visit-operand! ?p)) - (let ([main - (let f ([t** temp**] [e** (reverse e**)] [ls* (cons ?ls ?ls*)]) - (if (null? t**) - (let ([results - (let ([preinfo (app-preinfo ctxt)]) - (let g ([t** temp**]) - (if (null? (car t**)) - '() - (cons `(call ,preinfo (ref #f ,p) - ,(map (lambda (t*) (build-ref (car t*))) t**) ...) - (g (map cdr t**))))))]) - (if (and map? (not (eq? (app-ctxt ctxt) 'effect))) - (if (null? results) - null-rec - (build-primcall lvl 'list results)) - (if (null? results) - void-rec - (make-seq* (app-ctxt ctxt) results)))) - (non-result-exp (value-visit-operand! (car ls*)) - (build-let (car t**) (car e**) - (f (cdr t**) (cdr e**) (cdr ls*))))))]) - (if (fx= lvl 2) - (make-seq (app-ctxt ctxt) - `(if ,(build-primcall 2 'procedure? (list `(ref #f ,p))) - ,void-rec - ,(build-primcall 3 '$oops (list `(quote ,(if map? 'map 'for-each)) - `(quote "~s is not a procedure") - `(ref #f ,p)))) - main) - main))))) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! (car ls*))) - [(quote ,d) - (and (list? d) (loop (cdr ls*) (cons (map (lambda (x) `(quote ,x)) d) e**) all-quoted?))] - [(call ,preinfo ,e ,e* ...) - (and (primref? e) (eq? (primref-name e) 'list) (loop (cdr ls*) (cons e* e**) #f))] - [else #f]))))) - (define-inline 2 map - [(?p ?ls . ?ls*) - (inline-lists ?p ?ls ?ls* 2 #t ctxt sc wd name moi)]) - (define-inline 3 map - [(?p ?ls . ?ls*) - (cond - [(ormap null-rec? (cons ?ls ?ls*)) - (residualize-seq '() (list* ?p ?ls ?ls*) ctxt) - null-rec] - ; could treat map in effect context as for-each, but don't because (our) - ; map is guaranteed (even at optimization level 3) not to get sick if an - ; input list is mutated, while for-each is not. - [(and (eq? (app-ctxt ctxt) 'effect) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?p)) - [,pr (let ([flags (primref-flags pr)]) - (and (if (all-set? (prim-mask unsafe) flags) - (all-set? (prim-mask discard) flags) - (all-set? (prim-mask (or discard unrestricted)) flags)) - (arity-okay? (primref-arity pr) (fx+ (length ?ls*) 1))))] - [else #f])) - ; discard effect-free calls to map in effect context - (residualize-seq '() (list* ?p ?ls ?ls*) ctxt) - void-rec] - [(inline-lists ?p ?ls ?ls* 3 #t ctxt sc wd name moi)] - [(ormap (lambda (?ls) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?ls)) - [(quote ,d) - (and (list? d) (let ([n (length d)]) (and (fx<= n 4) n)))] - [(call ,preinfo ,e ,e* ...) - (and (primref? e) (eq? (primref-name e) 'list) (let ([n (length e*)]) (and (fx<= n 4) n)))] - [else #f])) - (cons ?ls ?ls*)) => - (lambda (n) - (safe-assert (not (= n 0))) ; guaranteed before we get here - ; (map proc e1 ... (begin e2 ... '(a b c d)) e3 ...) => - ; ((lambda (p ls ...) - ; ; do all cdrs first to avoid mutation sickness - ; (let ([t1 (cdr ls)] ...) - ; (let ([t2 (cdr t1)] ...) - ; (let ([t3 (cdr t2)] ...) - ; (list (p (car ls) ...) - ; (p (car t1) ...) - ; (p (car t2) ...) - ; (p (car t3) ...)))))) - ; proc e1 ... (begin e2 ... '(a b c d)) e3 ...) - (cp0 - (let ([p (cp0-make-temp (fx> n 1))] - [ls* (cons (cp0-make-temp #t) - (map (lambda (x) (cp0-make-temp #t)) ?ls*))]) - (build-lambda (cons p ls*) - (let f ([n n] [ls* ls*] [ropnd* '()]) - (if (fx= n 1) - (let ([opnd* - (reverse - (cons - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car - (list (build-ref x)))) - ls*) ...) - ropnd*))]) - (if (eq? ctxt 'effect) - (make-seq* ctxt opnd*) - (build-primcall 3 'list opnd*))) - (let ([tls* (map (lambda (x) (cp0-make-temp #t)) ls*)]) - (build-let tls* - (map (lambda (x) - (build-primcall 3 'cdr - (list (build-ref x)))) - ls*) - (f (fx- n 1) tls* - (cons `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car (list (build-ref x)))) - ls*) ...) - ropnd*)))))))) - ctxt empty-env sc wd name moi))] - [else #f])]) - - (define-inline 2 for-each - [(?p ?ls . ?ls*) - (inline-lists ?p ?ls ?ls* 2 #f ctxt sc wd name moi)]) - (define-inline 3 for-each - [(?p ?ls . ?ls*) - (cond - [(ormap null-rec? (cons ?ls ?ls*)) - ; (for-each proc e1 ... (begin e2 ... '()) e3 ...) => - ; (begin e1 ... (begin e2 ... '()) e3 ... (void)) - (begin - (residualize-seq '() (list* ?p ?ls ?ls*) ctxt) - void-rec)] - [(nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?p)) - [,pr (let ([flags (primref-flags pr)]) - (and (if (all-set? (prim-mask unsafe) flags) - (all-set? (prim-mask discard) flags) - (all-set? (prim-mask (or discard unrestricted)) flags)) - (arity-okay? (primref-arity pr) (fx+ (length ?ls*) 1))))] - [else #f]) - (residualize-seq '() (list* ?p ?ls ?ls*) ctxt) - void-rec] - [(inline-lists ?p ?ls ?ls* 3 #f ctxt sc wd name moi)] - [(ormap (lambda (?ls) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?ls)) - [(quote ,d) - (and (list? d) (let ([n (length d)]) (and (fx<= n 4) n)))] - [(call ,preinfo ,e ,e* ...) - (and (primref? e) (eq? (primref-name e) 'list) (let ([n (length e*)]) (and (fx<= n 4) n)))] - [else #f])) - (cons ?ls ?ls*)) => - (lambda (n) - (safe-assert (not (= n 0))) ; guaranteed before we get here - ; (for-each proc e1 ... (begin e2 ... '(a b c d)) e3 ...) - ; ((lambda (p ls ...) - ; (proc (car ls) ...) - ; (let ([t1 (cdr ls)] ...) - ; (proc (car t1) ...) - ; (let ([t2 (cdr t1)] ...) - ; (proc (car t2) ...) - ; (proc (cadr t2) ...)))) - ; proc e1 ... (begin e2 ... '(a b c d)) e3 ...) - (cp0 - (let ([p (cp0-make-temp (fx> n 1))] - [ls* (cons (cp0-make-temp #t) - (map (lambda (x) (cp0-make-temp #t)) ?ls*))]) - (build-lambda (cons p ls*) - (cond - [(fx= n 1) - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car (list (build-ref x)))) - ls*) ...)] - [else - (let f ([n n] [ls* ls*]) - (if (fx= n 2) - (make-seq 'value - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car (list (build-ref x)))) - ls*) ...) - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'cadr (list (build-ref x)))) - ls*) ...)) - (make-seq 'value - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car (list (build-ref x)))) - ls*) ...) - (let ([tls* (map (lambda (x) (cp0-make-temp #t)) ls*)]) - (build-let tls* - (map (lambda (x) - (build-primcall 3 'cdr (list (build-ref x)))) - ls*) - (f (fx- n 1) tls*))))))]))) - ctxt empty-env sc wd name moi))] - [else - (and likely-to-be-compiled? - (cp0 - (let ([?ls* (cons ?ls ?ls*)]) - (let ([p (cp0-make-temp #t)] - [r (cp0-make-temp #t)] - [do (cp0-make-temp #t)] - [tls* (map (lambda (x) (cp0-make-temp #t)) ?ls*)] - [ls* (map (lambda (x) (cp0-make-temp #t)) ?ls*)]) - (build-lambda (cons p tls*) - `(if ,(build-primcall 3 'null? - (list (build-ref (car tls*)))) - ,void-rec - ,(build-named-let do ls* - (map build-ref tls*) - (build-let (list r) - (list (build-primcall 3 'cdr (list (build-ref (car ls*))))) - `(if ,(build-primcall 3 'null? (list (build-ref r))) - (call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car (list (build-ref x)))) - ls*) ...) - ,(make-seq 'value - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car (list (build-ref x)))) - ls*) ...) - `(call ,(make-preinfo) (ref #f ,do) (ref #f ,r) - ,(map (lambda (x) - (build-primcall 3 'cdr (list (build-ref x)))) - (cdr ls*)) ...))))))))) - ctxt empty-env sc wd name moi))])]) - ) - - (define-inline 3 vector-map - [(?p ?v . ?v*) - (cond - [(eq? (app-ctxt ctxt) 'effect) - ; treat vector-map in effect context as vector-for-each - (cp0 (lookup-primref 3 'vector-for-each) ctxt empty-env sc wd name moi)] - [(ormap (lambda (?v) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?v)) - [(quote ,d) - (and (vector? d) - (let ([n (vector-length d)]) (and (fx<= n 4) n)))] - [else #f])) - (cons ?v ?v*)) => - (lambda (n) - (cond - [(fx= n 0) - ; (vector-map proc e1 ... (begin e2 ... '#()) e3 ...) => - ; (begin proc e1 ... (begin e2 ...'#()) e3 ... '#()) - (residualize-seq '() (list* ?p ?v ?v*) ctxt) - `(quote #())] - [else - ; (vector-map proc (begin e1 ... '#(a b c d)) e2 ...) - ; ((lambda (p v1 v2 ...) - ; (vector (proc 'a (vector-ref v2 0) ...) - ; (proc 'b (vector-ref v2 1) ...) - ; (proc 'c (vector-ref v2 2) ...) - ; (proc 'd (vector-ref v2 3) ...))) - ; proc (begin e1 ... '#(a b c d)) e2 ...) - (cp0 - (let ([p (cp0-make-temp (fx> n 1))] - [v* (cons (cp0-make-temp #t) - (map (lambda (x) (cp0-make-temp #t)) ?v*))]) - (build-lambda (cons p v*) - (build-primcall 3 'vector - (map (lambda (i) - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'vector-ref - (list (build-ref x) `(quote ,i)))) - v*) ...)) - (iota n))))) - ctxt empty-env sc wd name moi)]))] - [else #f])]) - - (define-inline 3 vector-for-each - [(?p ?v . ?v*) - (cond - [(nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?p)) - [,pr (all-set? (prim-mask discard) (primref-flags pr))] - [else #f]) - (residualize-seq '() (list* ?p ?v ?v*) ctxt) - void-rec] - [(ormap (lambda (?v) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?v)) - [(quote ,d) - (and (vector? d) - (let ([n (vector-length d)]) (and (fx<= n 4) n)))] - [else #f])) - (cons ?v ?v*)) => - (lambda (n) - (cond - [(fx= n 0) - ; (for-each proc (begin e1 ... '()) e2 ...) => - ; (begin (begin e1 ... '()) e2 ... (void)) - (residualize-seq '() (list* ?p ?v ?v*) ctxt) - void-rec] - [else - ; (for-each proc (begin e1 ... '#(a b c d)) e2 ...) - ; ((lambda (p ls1 ls2 ...) - ; (proc 'a (vector-ref ls2 0) ...) - ; (proc 'b (vector-ref ls2 1) ...) - ; (proc 'c (vector-ref ls2 2) ...) - ; (proc 'd (vector-ref ls2 3) ...)) - ; proc (begin e1 ... '(a b c d)) e2 ...) - (cp0 - (let ([p (cp0-make-temp (fx> n 1))] - [v* (cons (cp0-make-temp #t) - (map (lambda (x) (cp0-make-temp #t)) ?v*))]) - (build-lambda (cons p v*) - (make-seq* 'value - (map (lambda (i) - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'vector-ref - (list (build-ref x) `(quote ,i)))) - v*) ...)) - (iota n))))) - ctxt empty-env sc wd name moi)]))] - [else - (and likely-to-be-compiled? - (cp0 - (let ([p (cp0-make-temp #t)] - [n (cp0-make-temp #t)] - [i (cp0-make-temp #t)] - [j (cp0-make-temp #t)] - [do (cp0-make-temp #t)] - [v (cp0-make-temp #t)] - [v* (map (lambda (x) (cp0-make-temp #f)) ?v*)]) - (build-lambda (cons* p v v*) - (build-let (list n) (list (build-primcall 3 'vector-length (list (build-ref v)))) - `(if ,(build-primcall 3 'fx= (list (build-ref n) `(quote 0))) - ,void-rec - ,(build-named-let do (list i) (list `(quote 0)) - (build-let (list j) (list (build-primcall 3 'fx1+ (list (build-ref i)))) - `(if ,(build-primcall 3 'fx= (list (build-ref j) (build-ref n))) - (call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'vector-ref - (list (build-ref x) (build-ref i)))) - (cons v v*)) ...) - ,(make-seq 'value - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'vector-ref - (list (build-ref x) (build-ref i)))) - (cons v v*)) ...) - `(call ,(make-preinfo) (ref #f ,do) (ref #f ,j)))))))))) - ctxt empty-env sc wd name moi))])]) - - (define-inline 3 string-for-each ; should combine with vector-for-each - [(?p ?s . ?s*) - (cond - [(nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?p)) - [,pr (all-set? (prim-mask discard) (primref-flags pr))] - [else #f]) - (residualize-seq '() (list* ?p ?s ?s*) ctxt) - void-rec] - [(ormap (lambda (?s) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?s)) - [(quote ,d) - (and (string? d) - (let ([n (string-length d)]) (and (fx<= n 4) n)))] - [else #f])) - (cons ?s ?s*)) => - (lambda (n) - (cond - [(fx= n 0) - ; (for-each proc (begin e1 ... '()) e2 ...) => - ; (begin (begin e1 ... '()) e2 ... (void)) - (residualize-seq '() (list* ?p ?s ?s*) ctxt) - void-rec] - [else - ; (for-each proc (begin e1 ... '#(a b c d)) e2 ...) - ; ((lambda (p ls1 ls2 ...) - ; (proc 'a (string-ref ls2 0) ...) - ; (proc 'b (string-ref ls2 1) ...) - ; (proc 'c (string-ref ls2 2) ...) - ; (proc 'd (string-ref ls2 3) ...)) - ; proc (begin e1 ... '(a b c d)) e2 ...) - (cp0 - (let ([p (cp0-make-temp (fx> n 1))] - [s* (cons (cp0-make-temp #t) - (map (lambda (x) (cp0-make-temp #t)) ?s*))]) - (build-lambda (cons p s*) - (make-seq* 'value - (map (lambda (i) - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'string-ref - (list (build-ref x) `(quote ,i)))) - s*) ...)) - (iota n))))) - ctxt empty-env sc wd name moi)]))] - [else - (and likely-to-be-compiled? - (cp0 - (let ([p (cp0-make-temp #t)] - [n (cp0-make-temp #t)] - [i (cp0-make-temp #t)] - [j (cp0-make-temp #t)] - [do (cp0-make-temp #t)] - [s (cp0-make-temp #t)] - [s* (map (lambda (x) (cp0-make-temp #f)) ?s*)]) - (build-lambda (cons* p s s*) - (build-let (list n) (list (build-primcall 3 'string-length (list (build-ref s)))) - `(if ,(build-primcall 3 'fx= (list (build-ref n) `(quote 0))) - ,void-rec - ,(build-named-let do (list i) (list `(quote 0)) - (build-let (list j) (list (build-primcall 3 'fx1+ (list (build-ref i)))) - `(if ,(build-primcall 3 'fx= (list (build-ref j) (build-ref n))) - (call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'string-ref - (list (build-ref x) (build-ref i)))) - (cons s s*)) ...) - ,(make-seq 'value - `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'string-ref - (list (build-ref x) (build-ref i)))) - (cons s s*)) ...) - `(call ,(make-preinfo) (ref #f ,do) (ref #f ,j)))))))))) - ctxt empty-env sc wd name moi))])]) - - (define-inline 3 fold-right - [(?combine ?nil ?ls . ?ls*) - (and (ormap - (lambda (?ls) (cp0-constant? null? (result-exp (value-visit-operand! ?ls)))) - (cons ?ls ?ls*)) - (let ([nilval (value-visit-operand! ?nil)]) - (residualize-seq (list ?nil) (list* ?combine ?ls ?ls*) ctxt) - nilval))]) - - (define-inline 3 fold-left - [(?combine ?nil ?ls . ?ls*) - (if (ormap - (lambda (?ls) (cp0-constant? null? (result-exp (value-visit-operand! ?ls)))) - (cons ?ls ?ls*)) - (let ([nilval (value-visit-operand! ?nil)]) - (residualize-seq (list ?nil) (list* ?combine ?ls ?ls*) ctxt) - nilval) - (and likely-to-be-compiled? - (cp0 - (let ([?ls* (cons ?ls ?ls*)]) - (let ([p (cp0-make-temp #t)] - [nil (cp0-make-temp #t)] - [tls* (map (lambda (x) (cp0-make-temp #t)) ?ls*)] - [do (cp0-make-temp #t)] - [acc (cp0-make-temp #t)] - [ls* (map (lambda (x) (cp0-make-temp #t)) ?ls*)] - [r (cp0-make-temp #t)] - [carls* (map (lambda (x) (cp0-make-temp #t)) ?ls*)]) - (build-lambda (cons* p nil tls*) - `(if ,(build-primcall 3 'null? (list (build-ref (car tls*)))) - (ref #f ,nil) - ,(build-named-let do (cons acc ls*) - (map build-ref (cons nil tls*)) - (build-let (cons r carls*) - (cons - (build-primcall 3 'cdr (list (build-ref (car ls*)))) - (map (lambda (x) (build-primcall 3 'car (list (build-ref x)))) ls*)) - `(if ,(build-primcall 3 'null? (list (build-ref r))) - (call ,(app-preinfo ctxt) (ref #f ,p) - (ref #f ,acc) - ,(map build-ref carls*) - ...) - (call ,(make-preinfo) (ref #f ,do) - (call ,(app-preinfo ctxt) (ref #f ,p) - (ref #f ,acc) - ,(map build-ref carls*) - ...) - (ref #f ,r) - ,(map (lambda (x) (build-primcall 3 'cdr (list (build-ref x)))) (cdr ls*)) - ...)))))))) - ctxt empty-env sc wd name moi)))]) - - (define-inline 3 (andmap for-all) - [(?p ?ls . ?ls*) - (if (ormap - (lambda (?ls) (cp0-constant? null? (result-exp (value-visit-operand! ?ls)))) - (cons ?ls ?ls*)) - (begin - (residualize-seq '() (list* ?p ?ls ?ls*) ctxt) - true-rec) - (and likely-to-be-compiled? - (cp0 - (let ([?ls* (cons ?ls ?ls*)]) - (let ([p (cp0-make-temp #t)] - [r (cp0-make-temp #t)] - [do (cp0-make-temp #t)] - [tls* (map (lambda (x) (cp0-make-temp #t)) ?ls*)] - [ls* (map (lambda (x) (cp0-make-temp #t)) ?ls*)]) - (build-lambda (cons p tls*) - `(if ,(build-primcall 3 'null? - (list (build-ref (car tls*)))) - ,true-rec - ,(build-named-let do ls* - (map build-ref tls*) - (build-let (list r) - (list (build-primcall 3 'cdr - (list (build-ref (car ls*))))) - `(if ,(build-primcall 3 'null? - (list (build-ref r))) - (call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car - (list (build-ref x)))) - ls*) ...) - (if (call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car - (list (build-ref x)))) - ls*) ...) - (call ,(make-preinfo) (ref #f ,do) (ref #f ,r) - ,(map (lambda (x) - (build-primcall 3 'cdr - (list (build-ref x)))) - (cdr ls*)) ...) - ,false-rec)))))))) - ctxt empty-env sc wd name moi)))]) - - (define-inline 3 (ormap exists) - [(?p ?ls . ?ls*) - (if (ormap - (lambda (?ls) (cp0-constant? null? (result-exp (value-visit-operand! ?ls)))) - (cons ?ls ?ls*)) - (begin - (residualize-seq '() (list* ?p ?ls ?ls*) ctxt) - false-rec) - (and likely-to-be-compiled? - (cp0 - (let ([?ls* (cons ?ls ?ls*)]) - (let ([p (cp0-make-temp #t)] - [r (cp0-make-temp #t)] - [t (cp0-make-temp #t)] - [do (cp0-make-temp #t)] - [tls* (map (lambda (x) (cp0-make-temp #t)) ?ls*)] - [ls* (map (lambda (x) (cp0-make-temp #t)) ?ls*)]) - (build-lambda (cons p tls*) - `(if ,(build-primcall 3 'null? - (list (build-ref (car tls*)))) - ,false-rec - ,(build-named-let do ls* - (map build-ref tls*) - (build-let (list r) - (list (build-primcall 3 'cdr - (list (build-ref (car ls*))))) - `(if ,(build-primcall 3 'null? - (list (build-ref r))) - (call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car - (list (build-ref x)))) - ls*) ...) - ,(build-let (list t) - (list `(call ,(app-preinfo ctxt) (ref #f ,p) - ,(map (lambda (x) - (build-primcall 3 'car - (list (build-ref x)))) - ls*) ...)) - `(if (ref #f ,t) - (ref #f ,t) - (call ,(make-preinfo) (ref #f ,do) (ref #f ,r) - ,(map (lambda (x) - (build-primcall 3 'cdr - (list (build-ref x)))) - (cdr ls*)) ...)))))))))) - ctxt empty-env sc wd name moi)))]) - - (define-inline 2 car - [(?x) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?x)) - [(immutable-list (,e* ...) ,e) - (and (not (null? e*)) - (begin - (residualize-seq '() (list ?x) ctxt) - (car e*)))] - [(call ,preinfo ,pr ,e1 ,e2) - (guard (eq? (primref-name pr) 'cons)) - (residualize-seq (list ?x) '() ctxt) - (non-result-exp (operand-value ?x) - (make-seq (app-ctxt ctxt) e2 e1))] - [(call ,preinfo ,pr ,e* ...) - (guard (memq (primref-name pr) '(list list* cons*)) (not (null? e*))) - (residualize-seq (list ?x) '() ctxt) - (non-result-exp (operand-value ?x) - (fold-right - (lambda (e1 e2) (make-seq (app-ctxt ctxt) e1 e2)) - (car e*) - (cdr e*)))] - [else #f])]) - - (define-inline 2 cdr - [(?x) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?x)) - [(immutable-list (,e* ...) ,e) - (and (not (null? e*)) - (begin - (residualize-seq '() (list ?x) ctxt) - `(immutable-list (,(cdr e*) ...) - ,(build-primcall (app-preinfo ctxt) 3 'cdr - (list e)))))] - [(call ,preinfo ,pr ,e1 ,e2) - (guard (eq? (primref-name pr) 'cons)) - (residualize-seq (list ?x) '() ctxt) - (non-result-exp (operand-value ?x) - (make-seq (app-ctxt ctxt) e1 e2))] - [(call ,preinfo ,pr ,e* ...) - (guard (eq? (primref-name pr) 'list) (not (null? e*))) - (residualize-seq (list ?x) '() ctxt) - (non-result-exp (operand-value ?x) - (make-seq (app-ctxt ctxt) (car e*) - (build-call (app-preinfo ctxt) pr (cdr e*))))] - [(call ,preinfo ,pr ,e* ...) - (guard (memq (primref-name pr) '(list* cons*)) (>= (length e*) 2)) - (residualize-seq (list ?x) '() ctxt) - (non-result-exp (operand-value ?x) - (make-seq (app-ctxt ctxt) (car e*) - (build-call (app-preinfo ctxt) pr (cdr e*))))] - [else #f])]) - - (let () - (define doref - (lambda (ctxt ?x ?i e* d edok?) - (let ([e (let f ([e* e*] [d d] [ed #f]) - (if (null? e*) - ed - (if (fx= d 0) - (let ([ed (car e*)]) - (and (edok? (result-exp ed)) (f (cdr e*) (fx- d 1) ed))) - (let ([e (f (cdr e*) (fx- d 1) ed)]) - (and e (make-seq (app-ctxt ctxt) (car e*) e))))))]) - (and e (begin - (residualize-seq (list ?x ?i) '() ctxt) - (non-result-exp (operand-value ?i) ; do first ... - (non-result-exp (operand-value ?x) ; ... so we keep ?x related side effects together - e))))))) - - (define tryref - (lambda (ctxt ?x ?i seqprim maybe-pred) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?x)) - [(call ,preinfo ,pr ,e* ...) - (guard (eq? (primref-name pr) seqprim)) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?i)) - [(quote ,d) - (guard (fixnum? d) (#%$fxu< d (length e*))) - (doref ctxt ?x ?i e* d - (if (and maybe-pred (not (all-set? (prim-mask unsafe) (primref-flags pr)))) - (lambda (x) (cp0-constant? maybe-pred x)) - true))] - [else #f])] - [else #f]))) - - (define true (lambda (x) #t)) - - (define-inline 2 vector-ref - [(?x ?i) (tryref ctxt ?x ?i 'vector #f)]) - - (define-inline 2 string-ref - [(?x ?i) (tryref ctxt ?x ?i 'string char?)]) - - (define-inline 2 fxvector-ref - [(?x ?i) (tryref ctxt ?x ?i 'fxvector target-fixnum?)]) - - ; skipping bytevector-u8-ref and bytevector-s8-ref, which generally need to adjust the result. - - (define-inline 2 list-ref - [(?x ?i) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?x)) - [(call ,preinfo ,pr ,e* ...) - (guard (memq (primref-name pr) '(list list* cons*))) - (nanopass-case (Lsrc Expr) (result-exp (value-visit-operand! ?i)) - [(quote ,d) - (guard (fixnum? d) - (and (fx>= d 0) - (let ([n (length e*)]) - (if (eq? pr 'list) (fx< d n) (fx< d (fx- n 1)))))) - (doref ctxt ?x ?i e* d true)] - [else #f])] - [else #f])])) - - (let () - (define maybe-add-procedure-check - (lambda (?p level who p e) - (define (opnd-proc? opnd) - (nanopass-case (Lsrc Expr) (result-exp/indirect-ref (value-visit-operand! opnd)) - [(case-lambda ,preinfo ,cl ...) #t] - [,pr (all-set? (prim-mask proc) (primref-flags pr))] - [(quote ,d) (procedure? d)] - [else #f])) - (if (or (fx= level 3) (opnd-proc? ?p)) - e - `(seq - (if ,(build-primcall 3 'procedure? (list (build-ref p))) - ,void-rec - ,(build-primcall 2 '$oops - (list - `(quote ,who) - `(quote "~s is not a procedure") - (build-ref p)))) - ,e)))) - - (let () - (define mp - (lambda (ctxt empty-env sc wd name moi ?p level) - (and likely-to-be-compiled? - (cp0 - (let ([x (cp0-make-temp #f)] [v (cp0-make-temp #f)]) - (set-prelex-assigned! x #t) - (if ?p - (let ([orig-x (cp0-make-temp #f)] [p (cp0-make-temp #t)]) - (build-lambda (list orig-x p) - (maybe-add-procedure-check ?p level "make-parameter" p - (build-let (list x) (list `(call ,(make-preinfo) (ref #f ,p) (ref #f ,orig-x))) - (build-case-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) - (list - (list '() (build-ref x)) - (list (list v) `(set! #f ,x (call ,(make-preinfo) (ref #f ,p) (ref #f ,v)))))))))) - (build-lambda (list x) - (build-case-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) - (list - (list '() (build-ref x)) - (list (list v) `(set! #f ,x (ref #f ,v)))))))) - ctxt empty-env sc wd name moi)))) - (define-inline 2 make-parameter - [(?x) (mp ctxt empty-env sc wd name moi #f 2)] - [(?x ?p) (mp ctxt empty-env sc wd name moi ?p 2)]) - (define-inline 3 make-parameter - [(?x) (mp ctxt empty-env sc wd name moi #f 3)] - [(?x ?p) (mp ctxt empty-env sc wd name moi ?p 3)])) - - (when-feature pthreads - (let () - (define (mtp-ref x) - (build-primcall 3 'vector-ref - (list - (build-primcall 3 '$tc-field - (list - `(quote parameters) - (build-primcall 3 '$tc '()))) - (build-primcall 3 'car - (list (build-ref x)))))) - (define (mtp-set x e) - (build-primcall 3 '$set-thread-parameter! - (list (build-ref x) e))) - (define mtp - (lambda (ctxt empty-env sc wd name moi ?p level) - (and likely-to-be-compiled? - (cp0 - (let ([orig-x (cp0-make-temp #f)] [x (cp0-make-temp #t)] [v (cp0-make-temp #f)]) - (if ?p - (let ([p (cp0-make-temp #t)]) - (build-lambda (list orig-x p) - (maybe-add-procedure-check ?p level "make-thread-parameter" p - (build-let (list x) - (list (build-primcall 3 '$allocate-thread-parameter - (list `(call ,(make-preinfo) (ref #f ,p) (ref #f ,orig-x))))) - (build-case-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) - (list - (list '() (mtp-ref x)) - (list (list v) (mtp-set x `(call ,(make-preinfo) (ref #f ,p) (ref #f ,v)))))))))) - (build-lambda (list orig-x) - (build-let (list x) - (list (build-primcall 3 '$allocate-thread-parameter - (list (build-ref orig-x)))) - (build-case-lambda (preinfo-call->preinfo-lambda (app-preinfo ctxt)) - (list - (list '() (mtp-ref x)) - (list (list v) (mtp-set x (build-ref v))))))))) - ctxt empty-env sc wd name moi)))) - (define-inline 2 make-thread-parameter - [(?x) (mtp ctxt empty-env sc wd name moi #f 2)] - [(?x ?p) (mtp ctxt empty-env sc wd name moi ?p 2)]) - (define-inline 3 make-thread-parameter - [(?x) (mtp ctxt empty-env sc wd name moi #f 3)] - [(?x ?p) (mtp ctxt empty-env sc wd name moi ?p 3)])))) - - (let () - (define inline-make-guardian - (lambda (ctxt empty-env sc wd name moi formal* make-setter-clauses) - (and likely-to-be-compiled? - (cp0 - (let* ([tc (cp0-make-temp #t)] [ref-tc (build-ref tc)]) - ; if the free variables of the closure created for a guardian changes, the code - ; for unregister-guardian in prims.ss might also need to be updated - (build-lambda formal* - (build-let (list tc) - (list (let* ([x (cp0-make-temp #t)] [ref-x (build-ref x)]) - (let ([zero `(quote 0)]) - (build-let (list x) (list (build-primcall 3 'cons (list zero zero))) - (build-primcall 3 'cons (list ref-x ref-x)))))) - (build-case-lambda (let ([preinfo (app-preinfo ctxt)]) - (make-preinfo-lambda (preinfo-src preinfo) (preinfo-sexpr preinfo) #f #f - (constant code-flag-guardian))) - (cons - (list '() - (let* ([x (cp0-make-temp #t)] [ref-x (build-ref x)]) - (let ([y (cp0-make-temp #f)]) - (build-let (list x) (list (build-primcall 3 'car (list ref-tc))) - `(if ,(build-primcall 3 'eq? - (list ref-x - (build-primcall 3 'cdr (list ref-tc)))) - ,false-rec - ,(build-let (list y) (list (build-primcall 3 'car (list ref-x))) - `(seq - (seq - (seq - ,(build-primcall 3 'set-car! (list ref-tc - (build-primcall 3 'cdr (list ref-x)))) - ,(build-primcall 3 'set-car! (list ref-x false-rec))) - ,(build-primcall 3 'set-cdr! (list ref-x false-rec))) - (ref #f ,y)))))))) - (make-setter-clauses ref-tc)))))) - ctxt empty-env sc wd name moi)))) - - (define-inline 2 make-guardian - [() (inline-make-guardian ctxt empty-env sc wd name moi '() - (lambda (ref-tc) - (list - (let* ([obj (cp0-make-temp #t)] [ref-obj (build-ref obj)]) - (list (list obj) - (build-primcall 3 '$install-guardian - (list ref-obj ref-obj ref-tc)))) - (let ([obj (cp0-make-temp #f)] [rep (cp0-make-temp #f)]) - (list (list obj rep) - (build-primcall 3 '$install-guardian - (list (build-ref obj) (build-ref rep) ref-tc)))))))]) - - (define-inline 2 $make-ftype-guardian - [(?ftd) - (let ([ftd (cp0-make-temp #f)]) - (inline-make-guardian ctxt empty-env sc wd name moi - (list ftd) - (lambda (ref-tc) - (list - (let* ([obj (cp0-make-temp #t)] [ref-obj (build-ref obj)]) - (list (list obj) - (let ([e (build-primcall 3 '$install-ftype-guardian - (list ref-obj ref-tc))]) - (if (fx= level 3) - e - (let ([ref-ftd (build-ref ftd)]) - `(seq - (if ,(build-primcall 3 'record? (list ref-obj ref-ftd)) - ,void-rec - ,(build-primcall 3 '$ftype-guardian-oops (list ref-ftd ref-obj))) - ,e))))))))))]))) - ) ; with-output-language - - (define-pass cp0 : Lsrc (ir ctxt env sc wd name moi) -> Lsrc () - (Expr : Expr (ir ctxt env sc wd name moi) -> Expr () - [(quote ,d) ir] - [(ref ,maybe-src ,x) - (context-case ctxt - [(effect) void-rec] - [else - (let ((new-id (lookup x env))) - (when (eq? new-id x) - ; id is a free variable of a lambda we're attempting to integrate, - ; so we conservatively set it multiply-referenced in case we try to - ; integrate the lambda more than once. - (set-prelex-multiply-referenced! new-id #t)) - (let ((opnd (prelex-operand new-id))) - ; a scorer in place of an operand means that we've found a - ; recursive reference that we're not permitted to residualize - (if (scorer? opnd) - (bug-out! opnd) - (if (and opnd (not (inner-cyclic? opnd))) - (cond - [(and (app? ctxt) - ; find a lambda expression starting with (operand-exp opnd) and - ; following along through singly referenced unassigned variable - ; references---a sort of source-level copy propagation. we should - ; traverse a chain of references at most once here since we only - ; propagate along singly referenced identifiers - (let loop ((new-id new-id) (opnd opnd)) - (and (not (operand-value opnd)) - (not (prelex-was-assigned new-id)) - (not (prelex-was-multiply-referenced new-id)) - (nanopass-case (Lsrc Expr) (operand-exp opnd) - [(case-lambda ,preinfo ,cl* ...) opnd] - [(ref ,maybe-src ,x) - (let ((new-rhs-id (lookup x (operand-env opnd)))) - (and (not (eq? new-rhs-id x)) - (let ((opnd (prelex-operand new-rhs-id))) - (and (operand? opnd) - (loop new-rhs-id opnd)))))] - [else #f])))) => - (lambda (x-opnd) - ; yea-raw, singly referenced id with rhs a lambda - ; skip value-visit operand and, therefore, don't alert the watchdog - (with-values (find-lambda-clause (operand-exp x-opnd) ctxt) - (case-lambda - [(ids body) - (let ((sc (new-scorer))) - (let ((e (cp0-let - (nanopass-case (Lsrc Expr) (operand-exp x-opnd) - [(case-lambda ,preinfo ,cl* ...) preinfo]) - ids body ctxt (operand-env x-opnd) sc (operand-wd x-opnd) name moi))) - (operand-singly-referenced-score-set! x-opnd (scorer-score sc)) - e))] - [() - ; had been visiting x-opnd, leaving intermediate - ; opnds in chain unvisited - (value-visit-operand! opnd) - ; could call copy here, as below, but this - ; leads to more misleading incorrect argument - ; count errors - #;(copy maybe-src new-id opnd ctxt sc wd) - (residualize-ref maybe-src new-id sc)])))] - [else - (value-visit-operand! opnd) - (if (prelex-was-assigned new-id) - (residualize-ref maybe-src new-id sc) - (copy maybe-src new-id opnd ctxt sc wd name moi))]) - (residualize-ref maybe-src new-id sc)))))])] - [(seq ,[cp0 : e1 'effect env sc wd #f moi -> e1] ,e2) - (make-seq ctxt e1 (cp0 e2 ctxt env sc wd name moi))] - [(if ,[cp0 : e1 'test env sc wd #f moi -> e1] ,e2 ,e3) - (nanopass-case (Lsrc Expr) (result-exp e1) - [(quote ,d) - (make-seq ctxt e1 (cp0 (if d e2 e3) ctxt env sc wd name moi))] - [else - (let ((noappctxt (if (app? ctxt) 'value ctxt))) - (let ([e2 (cp0 e2 noappctxt env sc wd name moi)] - [e3 (cp0 e3 noappctxt env sc wd name moi)]) - (make-if ctxt sc e1 e2 e3)))])] - [(set! ,maybe-src ,x ,e) - (let ((new-id (lookup x env))) - (if (prelex-was-referenced new-id) - (begin - (bump sc 1) - (let ((e (cp0 e 'value env sc wd (prelex-name x) moi))) - (set-prelex-assigned! new-id #t) - `(set! ,maybe-src ,new-id ,e))) - (make-seq ctxt (cp0 e 'effect env sc wd (prelex-name x) moi) void-rec)))] - [(call ,preinfo ,e ,e* ...) - (let () - (define lift-let - (lambda (e args) - (nanopass-case (Lsrc Expr) e - [(case-lambda ,preinfo0 (clause (,x* ...) ,interface ,body)) - (guard (fx= interface (length args))) - (let loop ([ids x*] [args args] [new-ids '()] [new-args '()] [xids '()] [xargs '()]) - (if (null? ids) - (if (null? xids) - (values - (build-lambda preinfo0 (reverse new-ids) body) - (reverse new-args)) - (values - (build-lambda preinfo0 (reverse xids) - (build-let (reverse new-ids) (reverse new-args) body)) - (reverse xargs))) - (nanopass-case (Lsrc Expr) (car args) - [(call ,preinfo1 - (case-lambda ,preinfo2 - (clause (,x2* ...) ,interface2 - (case-lambda ,preinfo3 ,cl3* ...))) - ,e1* ...) - (guard (fx= (length e1*) 1) (fx= interface2 1) - (not (prelex-assigned (car x*)))) - (loop (cdr ids) (cdr args) (cons (car ids) new-ids) - (cons `(case-lambda ,preinfo3 ,cl3* ...) new-args) (cons (car x2*) xids) - (cons (car e1*) xargs))] - [else (loop (cdr ids) - (cdr args) - (cons (car ids) new-ids) - (cons (car args) new-args) - xids xargs)])))] - [else (values e args)]))) - (let-values ([(e args) (lift-let e e*)]) - (cp0-call preinfo e (build-operands args env wd moi) ctxt env sc wd name moi)))] - [(case-lambda ,preinfo ,cl* ...) - (when (and (symbol? name) - ;; Avoid replacing a name from an optimized-away `let` pattern: - (not (preinfo-lambda-name preinfo))) - (preinfo-lambda-name-set! preinfo - (let ([x ($symbol-name name)]) - (if (pair? x) (cdr x) x)))) - (context-case ctxt - [(value) - (bump sc 1) - `(case-lambda ,preinfo - ,(let f ([cl* cl*] [mask 0]) - (if (null? cl*) - '() - (nanopass-case (Lsrc CaseLambdaClause) (car cl*) - [(clause (,x* ...) ,interface ,body) - (let ([new-mask (logor mask (if (fx< interface 0) (ash -1 (fx- -1 interface)) (ash 1 interface)))]) - (if (= new-mask mask) - (f (cdr cl*) new-mask) - (cons - (with-extended-env ((env x*) (env x* #f)) - `(clause (,x* ...) ,interface ,(cp0 body 'value env sc wd #f name))) - (f (cdr cl*) new-mask))))]))) - ...)] - [(effect) void-rec] - [(test) true-rec] - [(app) - (with-values (find-lambda-clause ir ctxt) - (case-lambda - [(ids body) - ; looking for or pattern first - (or (and (fx= (length ids) 1) - (nanopass-case (Lsrc Expr) body - [(if (ref ,maybe-src1 ,x1) (ref ,maybe-src2 ,x2) ,e3) - (guard (let ([id (car ids)]) (and (eq? x1 id) (eq? x2 id)))) - (let () - (define (finish e1) - (define (do-e3) - (with-extended-env ((env ids) (env ids (list (make-operand false-rec env wd moi)))) - (let ([e3 (cp0 e3 (app-ctxt ctxt) env sc wd (app-name ctxt) moi)]) - (if (or (prelex-referenced (car ids)) (prelex-assigned (car ids))) - (build-let ids (list false-rec) e3) - e3)))) - (nanopass-case (Lsrc Expr) (result-exp e1) - [(quote ,d) - (residualize-seq '() (app-opnds ctxt) ctxt) - (if d true-rec (do-e3))] - [else - ; converting (let ([x e1]) (if x x e3)) => (if e1 #t (let ([x #f]) e3)) - ; i.e., handling or pattern. - (residualize-seq (app-opnds ctxt) '() ctxt) - (make-if ctxt sc e1 - true-rec - (do-e3))])) - (if (eq? (app-ctxt ctxt) 'value) - (let ([e1 (value-visit-operand! (car (app-opnds ctxt)))]) - (and (boolean-valued? e1) (finish e1))) - (and (eq? (app-ctxt ctxt) 'test) - (finish (test-visit-operand! (car (app-opnds ctxt)))))))] - [else #f])) - (cp0-let preinfo ids body ctxt env sc wd name moi))] - [() (cp0 ir 'value env sc wd name moi)]))])] - [(letrec ([,x* ,e*] ...) ,body) - (cp0-rec-let #f x* e* body ctxt env sc wd name moi)] - [(letrec* ([,x* ,e*] ...) ,body) - (cp0-rec-let #t x* e* body ctxt env sc wd name moi)] - [,pr (context-case ctxt - [(value) (bump sc 1) pr] - [(effect) void-rec] - [(test) - (if (all-set? (prim-mask proc) (primref-flags pr)) - true-rec - (begin (bump sc 1) pr))] - [(app) (fold-primref pr ctxt sc wd name moi)])] - [(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) - (context-case ctxt - [(value app) (bump sc 1) `(foreign (,conv* ...) ,name ,(cp0 e 'value env sc wd #f moi) (,arg-type* ...) ,result-type)] - [(effect test) (cp0 `(seq ,e ,true-rec) ctxt env sc wd #f moi)])] - [(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type) - (context-case ctxt - [(value app) (bump sc 1) `(fcallable (,conv* ...) ,(cp0 e 'value env sc wd #f moi) (,arg-type* ...) ,result-type)] - [(effect) (cp0 e 'effect env sc wd #f moi)] - [(test) (make-seq ctxt (cp0 e 'effect env sc wd #f moi) true-rec)])] - [(record ,rtd ,rtd-expr ,e* ...) - (context-case ctxt - [(value app) - (let ([rtd-expr (cp0 rtd-expr 'value env sc wd #f moi)] - [e* (map (lambda (e) (cp0 e 'value env sc wd #f moi)) e*)]) - (or (nanopass-case (Lsrc Expr) (result-exp rtd-expr) - [(quote ,d) - (and (record-type-descriptor? d) - (andmap (lambda (fld) - (and (not (fld-mutable? fld)) - (eq? (filter-foreign-type (fld-type fld)) 'scheme-object))) - (rtd-flds d)) - (let ([d* (objs-if-constant e*)]) - (and d* - (make-seq ctxt - (make-seq* 'effect (cons rtd-expr e*)) - `(quote ,(apply $record d d*))))))] - [else #f]) - `(record ,rtd ,rtd-expr ,e* ...)))] - [(effect) - (make-seq* ctxt - (cons - (cp0 rtd-expr 'effect env sc wd #f moi) - (map (lambda (e) (cp0 e 'effect env sc wd #f moi)) e*)))] - [(test) - (make-seq ctxt - (make-seq* 'effect - (cons - (cp0 rtd-expr 'effect env sc wd #f moi) - (map (lambda (e) (cp0 e 'effect env sc wd #f moi)) e*))) - true-rec)])] - [(record-ref ,rtd ,type ,index ,e0) - (context-case ctxt - [(effect) (cp0 e0 'effect env sc wd name moi)] - [else - (let ([e0 (cp0 e0 'value env sc wd name moi)]) - (or (nanopass-case (Lsrc Expr) (result-exp e0) - [(quote ,d) - (and (record? d rtd) - (make-seq ctxt e0 `(quote ,((csv7:record-field-accessor rtd index) d))))] - [(record ,rtd1 ,rtd-expr ,e* ...) - (let loop ([e* e*] [re* '()] [index index]) - (and (not (null? e*)) - (if (fx= index 0) - (let ([e (car e*)] [e* (rappend re* (cdr e*))]) - (non-result-exp e0 - (if (null? e*) - e - (make-seq ctxt (make-seq* 'effect e*) e)))) - (loop (cdr e*) (cons (car e*) re*) (fx- index 1)))))] - [else #f]) - (nanopass-case (Lsrc Expr) (result-exp/indirect-ref e0) - [(record ,rtd1 ,rtd-expr ,e* ...) - (and (> (length e*) index) - (not (fld-mutable? (list-ref (rtd-flds rtd) index))) - (let ([e (list-ref e* index)]) - (and (nanopass-case (Lsrc Expr) e - [(quote ,d) #t] - [(ref ,maybe-src ,x) (not (prelex-assigned x))] - [,pr (all-set? (prim-mask proc) (primref-flags pr))] - [else #f]) - ; recur to cp0 to get inlining, folding, etc. - (non-result-exp e0 (cp0 e ctxt env sc wd name moi)))))] - [else #f]) - (begin (bump sc 1) `(record-ref ,rtd ,type ,index ,e0))))])] - [(record-set! ,rtd ,type ,index ,[cp0 : e1 'value env sc wd #f moi -> e1] ,[cp0 : e2 'value env sc wd #f moi -> e2]) - `(record-set! ,rtd ,type ,index ,e1 ,e2)] - [(record-type ,rtd ,e) (cp0 e ctxt env sc wd name moi)] - [(record-cd ,rcd ,rtd-expr ,e) (cp0 e ctxt env sc wd name moi)] - [(immutable-list (,[cp0 : e* 'value env sc wd #f moi -> e*] ...) ,[cp0 : e ctxt env sc wd name moi -> e]) - `(immutable-list (,e* ...) ,e)] - [(moi) (if moi `(quote ,moi) ir)] - [(pariah) ir] - [(cte-optimization-loc ,box ,[cp0 : e ctxt env sc wd name moi -> e]) - (when (enable-cross-library-optimization) - (let () - (define update-box! - (lambda (box e) - (set-box! box - (cons - (cons ($target-machine) e) - (remp (lambda (as) (eq? (car as) ($target-machine))) (unbox box)))))) - (nanopass-case (Lsrc Expr) e - [(quote ,d) (and (okay-to-copy? d) (update-box! box e))] - [,pr (update-box! box pr)] - [(ref ,maybe-src ,x) - (and (not (prelex-was-assigned x)) - (let ([rhs (result-exp (operand-value (prelex-operand x)))]) - (nanopass-case (Lsrc Expr) rhs - [(case-lambda ,preinfo ,cl* ...) - (when (andmap externally-inlinable? cl*) - (update-box! box rhs))] - [else #f])))] - [else (void)]))) - `(cte-optimization-loc ,box ,e)] - [(cpvalid-defer ,e) (sorry! who "cpvalid leaked a cpvalid-defer form ~s" ir)] - [(profile ,src) ir] - [else ($oops who "unrecognized record ~s" ir)]) - (begin - (bump wd 1) - (Expr ir ctxt env sc wd name moi))) - - (rec $cp0 - (case-lambda - [(x) ($cp0 x #t)] - [(x ltbc?) - (fluid-let ([likely-to-be-compiled? ltbc?] - [opending-list '()] - [cp0-info-hashtable (make-weak-eq-hashtable)]) - (cp0 x 'value empty-env (new-scorer) (new-watchdog) #f #f))])))) - -; check to make sure all required handlers were seen, after expansion of the -; expression above has been completed -(let-syntax ([a (lambda (x) - (for-each - (lambda (sym) - (let ([flags ($sgetprop sym '*flags* 0)]) - (when (all-set? (prim-mask cp02) flags) - (if (getprop sym 'cp02 #f) - (remprop sym 'cp02) - ($oops #f "no cp02 handler for ~s" sym))) - (when (all-set? (prim-mask cp03) flags) - (if (getprop sym 'cp03 #f) - (remprop sym 'cp03) - ($oops #f "no cp03 handler for ~s" sym))))) - (oblist)) - #'(void))]) - a) diff --git a/ta6ob/s/cp0.ta6ob b/ta6ob/s/cp0.ta6ob deleted file mode 100644 index 906463a..0000000 Binary files a/ta6ob/s/cp0.ta6ob and /dev/null differ diff --git a/ta6ob/s/cpcheck.ss b/ta6ob/s/cpcheck.ss deleted file mode 100644 index 1ed58cf..0000000 --- a/ta6ob/s/cpcheck.ss +++ /dev/null @@ -1,210 +0,0 @@ -;;; cpcheck.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; cpcheck checks argument counts in calls to primitives and user-defined -;;; procedures, where it can recognize them. by running it after cp0, we -;;; catch more potentially incorrect calls, including calls to the record -;;; constructors and accessors constructed by cp0. running it after cp0 can -;;; also lead to bogus warnings on rare occasions, as in: -;;; -;;; (define (f b) -;;; (define h (lambda (b f) (if b (f 1) (f 1 2)))) -;;; (if b -;;; (h b (lambda (x) x)) -;;; (h b (lambda (x y) y)))) -;;; -;;; where the calls (f 1) and (f 1 2) will be identified as having possible -;;; incorrect argument counts. it seems like a reasonable tradeoff. - -(define $cpcheck -(let () - (import (nanopass)) - (include "base-lang.ss") - - (define rtd-flds (csv7:record-field-accessor #!base-rtd 'flds)) - (define rtd-size (csv7:record-field-accessor #!base-rtd 'size)) - - (define maybe-remake-rtd - (lambda (rtd) - (if (eq? ($target-machine) (machine-type)) - rtd - ($remake-rtd rtd (let () (include "layout.ss") compute-field-offsets))))) - - (define record-field-offset - (lambda (rtd index) - (let ([rtd (maybe-remake-rtd rtd)]) - (fld-byte (list-ref (rtd-flds rtd) index))))) - - (define-pass cpcheck : Lsrc (ir) -> Lsrc () - (definitions - (define-record-type call-context - (nongenerative) - (sealed #t) - (fields cnt (mutable err)) - (protocol - (lambda (new) - (lambda (cnt) (new cnt #f))))) - - (define check! - (lambda (ctxt interface*) - (define interface-okay? - (lambda (interface* cnt) - (ormap - (lambda (interface) - (if (fx< interface 0) - (fx>= cnt (lognot interface)) - (fx= cnt interface))) - interface*))) - (when ctxt - (unless (interface-okay? interface* (call-context-cnt ctxt)) - (call-context-err-set! ctxt #t))))) - - (define record-lambda! - (lambda (id val) - (unless (prelex-assigned id) - (nanopass-case (Lsrc Expr) val - [(case-lambda ,preinfo (clause (,x** ...) ,interface* ,body*) ...) - (prelex-operand-set! id interface*)] - [else (void)])))) - - (define-syntax with-record-lambda - (syntax-rules () - [(_ ids vals body) - (begin - (for-each record-lambda! ids vals) - (let ([x body]) - (for-each (lambda (id) (prelex-operand-set! id #f)) ids) - x))])) - - (with-output-language (Lsrc Expr) - (define build-sequence - (lambda (x* body) - (fold-left (lambda (body x) `(seq ,x ,body)) body x*))) - - (define argcnt-error - (lambda (preinfo f args) - (let ([call (parameterize ([print-gensym #f] [print-level 3] [print-length 6]) - (format "~s" (preinfo-sexpr preinfo)))]) - `(seq ,f - ,(build-sequence args - (cond - [(preinfo-src preinfo) => - (lambda (src) - ($source-warning 'compile src #t - "possible incorrect argument count in call ~a" - call) - `(call ,preinfo - ,(lookup-primref 2 '$source-violation) - (quote #f) - (quote ,src) - (quote #t) - (quote "incorrect argument count in call ~a") - (quote ,call)))] - [else - `(call ,preinfo - ,(lookup-primref 2 '$oops) - (quote #f) - (quote "incorrect argument count in call ~a") - (quote ,call))])))))))) - (Expr : Expr (ir [ctxt #f]) -> Expr () - [(quote ,d) ir] - [(ref ,maybe-src ,x) - (cond - [(prelex-operand x) => - (lambda (interface*) - (and (list? interface*) - (check! ctxt interface*)))]) - `(ref ,maybe-src ,x)] - [(set! ,maybe-src ,x ,[e #f -> e]) `(set! ,maybe-src ,x ,e)] - [(seq ,[e1 #f -> e1] ,[e2]) `(seq ,e1 ,e2)] - [(if ,[e1 #f -> e1] ,[e2 #f -> e2] ,[e3 #f -> e3]) `(if ,e1 ,e2 ,e3)] - [(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) - (check! ctxt (list (length arg-type*))) - `(foreign (,conv* ...) ,name ,(Expr e #f) (,arg-type* ...) ,result-type)] - [(fcallable (,conv* ...) ,[e #f -> e] (,arg-type* ...) ,result-type) - `(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type)] - [(call ,preinfo0 - (case-lambda ,preinfo1 - (clause (,x* ...) ,interface ,body) - ,cl* ...) - ,[e* #f -> e*] ...) - (guard (fx= (length e*) interface)) - `(call ,preinfo0 - (case-lambda ,preinfo1 - (clause (,x* ...) ,interface - ,(with-record-lambda x* e* (Expr body ctxt)))) - ,e* ...)] - [(call ,preinfo ,e ,[e* #f -> e*] ...) - (let ([sexpr (preinfo-sexpr preinfo)]) - (define ugly-gensym? ; gensym w/no pretty name - (lambda (x) - (and (gensym? x) - (let ([name ($symbol-name x)]) - (or (not (pair? name)) (not (cdr name))))))) - (if (and sexpr (and (pair? sexpr) (not (ugly-gensym? (car sexpr))))) - (let ([ctxt (make-call-context (length e*))]) - (let ([e (Expr e ctxt)]) - (if (call-context-err ctxt) - (argcnt-error preinfo e e*) - `(call ,preinfo ,e ,e* ...)))) - `(call ,preinfo ,(Expr e #f) ,e* ...)))] - [(case-lambda ,preinfo (clause (,x** ...) ,interface* ,[body* #f -> body*]) ...) - (check! ctxt interface*) - `(case-lambda ,preinfo (clause (,x** ...) ,interface* ,body*) ...)] - [(letrec ([,x* ,e*] ...) ,body) - (with-record-lambda x* e* - `(letrec ([,x* ,(map (lambda (e) (Expr e #f)) e*)] ...) - ,(Expr body ctxt)))] - [,pr (let ([arity (primref-arity pr)]) (when arity (check! ctxt arity))) pr] - [(record-ref ,rtd ,type ,index ,[e #f -> e]) - `(call ,(make-preinfo) ,(lookup-primref 3 '$object-ref) - (quote ,type) ,e (quote ,(record-field-offset rtd index)))] - [(record-set! ,rtd ,type ,index ,[e1 #f -> e1] ,[e2 #f -> e2]) - `(call ,(make-preinfo) ,(lookup-primref 3 '$object-set!) - (quote ,type) ,e1 (quote ,(record-field-offset rtd index)) ,e2)] - [(record ,rtd ,[rtd-expr #f -> rtd-expr] ,[e* #f -> e*] ...) - (let ([rtd (maybe-remake-rtd rtd)]) - (let ([fld* (rtd-flds rtd)] [rec-t (make-prelex*)]) - (safe-assert (fx= (length e*) (length fld*))) - (let ([filler* (fold-right - (lambda (fld e filler*) - (let ([type (fld-type fld)]) - (if (eq? (filter-foreign-type type) 'scheme-object) - filler* - (cons - `(call ,(make-preinfo) ,(lookup-primref 3 '$object-set!) - (quote ,type) (ref #f ,rec-t) (quote ,(fld-byte fld)) ,e) - filler*)))) - '() fld* e*)]) - (if (null? filler*) - `(call ,(make-preinfo) ,(lookup-primref 3 '$record) ,rtd-expr ,e* ...) - (begin - (set-prelex-referenced! rec-t #t) - (set-prelex-multiply-referenced! rec-t #t) - `(call ,(make-preinfo) - (case-lambda ,(make-preinfo-lambda) - (clause (,rec-t) 1 ,(build-sequence filler* `(ref #f ,rec-t)))) - (call ,(make-preinfo) ,(lookup-primref 3 '$record) ,rtd-expr - ,(map (lambda (arg) (cond [(eqv? arg 0) `(quote 0)] [else arg])) - (make-record-call-args fld* (rtd-size rtd) e*)) - ...)))))))] - [(cte-optimization-loc ,box ,[e #f -> e]) e] - [(immutable-list (,e* ...) ,[e]) e] - [(moi) ir] - [(pariah) ir] - [(profile ,src) ir] - [else (sorry! who "unhandled record ~s" ir)])) - - (lambda (x) (cpcheck x)))) diff --git a/ta6ob/s/cpcheck.ta6ob b/ta6ob/s/cpcheck.ta6ob deleted file mode 100644 index 18f4e17..0000000 Binary files a/ta6ob/s/cpcheck.ta6ob and /dev/null differ diff --git a/ta6ob/s/cpcommonize.ss b/ta6ob/s/cpcommonize.ss deleted file mode 100644 index 6fe0431..0000000 --- a/ta6ob/s/cpcommonize.ss +++ /dev/null @@ -1,579 +0,0 @@ -;;; cpcommonize.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(begin -(define-who commonization-level - ($make-thread-parameter - 0 - (lambda (x) - (unless (and (fixnum? x) (<= 0 x 9)) - ($oops who "invalid level ~s" x)) - x))) - -(define $cpcommonize - (let () - (import (nanopass)) - (include "base-lang.ss") - - (define-record-type binding - (nongenerative) - (sealed #t) - (fields x (mutable e) size helper-box (mutable helper-b) (mutable helper-arg*)) - (protocol - (lambda (new) - (lambda (x e size helper-box) - (new x e size helper-box #f #f))))) - - (define-language Lcommonize1 (extends Lsrc) - (terminals - (+ (fixnum (size)))) - (Expr (e body rtd-expr) - (- (letrec ([x* e*] ...) body)) - (+ (letrec ([x* e* size] ...) body)))) - - (define-language Lcommonize2 (extends Lcommonize1) - (terminals - (- (fixnum (size))) - (+ (binding (b helper-b)))) - (Expr (e body rtd-expr) - (- (letrec ([x* e* size] ...) body)) - (+ (letrec (helper-b* ...) (b* ...) body)))) - - (define-syntax iffalse - (syntax-rules () - [(_ e1 e2) e1 #;(or e1 (begin e2 #f))])) - - (define-syntax iftrue - (syntax-rules () - [(_ e1 e2) e1 #;(let ([t e1]) (and t (begin e2 t)))])) - - (define Lcommonize1-lambda? - (lambda (e) - (nanopass-case (Lcommonize1 Expr) e - [(case-lambda ,preinfo ,cl* ...) #t] - [else #f]))) - - (define-pass cpcommonize0 : Lsrc (ir) -> Lcommonize1 () - (Expr : Expr (ir) -> Expr (1) - [(set! ,maybe-src ,x ,[e size]) - (values `(set! ,maybe-src ,x ,e) (fx+ 1 size))] - [(seq ,[e1 size1] ,[e2 size2]) - (values `(seq ,e1 ,e2) (fx+ size1 size2))] - [(if ,[e1 size1] ,[e2 size2] ,[e3 size3]) - (values `(if ,e1 ,e2 ,e3) (fx+ size1 size2 size3))] - [(foreign (,conv* ...) ,name ,[e size] (,arg-type* ...) ,result-type) - (values `(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) (fx+ 1 size))] - [(fcallable (,conv* ...) ,[e size] (,arg-type* ...) ,result-type) - (values `(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type) (fx+ 1 size))] - ; ($top-level-value 'x) adds just 1 to the size - [(call ,preinfo ,pr (quote ,d)) - (guard (eq? (primref-name pr) '$top-level-value)) - (values `(call ,preinfo ,pr (quote ,d)) 1)] - ; (let ([x* e*] ...) body) splits into letrec binding unassigned variables to lambdas plus a let for the remaining bindings - [(call ,preinfo1 (case-lambda ,preinfo2 (clause (,x* ...) ,interface ,[body size])) ,[e* -> e* size*] ...) - (guard (fx= (length e*) interface)) - (define-record-type fudge (nongenerative) (sealed #t) (fields x e size)) - (let-values ([(lb* ob*) (partition - (lambda (b) - (and (not (prelex-assigned (fudge-x b))) - (Lcommonize1-lambda? (fudge-e b)))) - (map make-fudge x* e* size*))]) - (values - (let ([body (if (null? ob*) - body - `(call ,preinfo1 - (case-lambda ,preinfo2 - (clause (,(map fudge-x ob*) ...) ,(length ob*) ,body)) - ,(map fudge-e ob*) ...))]) - (if (null? lb*) - body - `(letrec ([,(map fudge-x lb*) ,(map fudge-e lb*) ,(map fudge-size lb*)] ...) ,body))) - (apply fx+ size size*)))] - [(call ,preinfo ,[e size] ,[e* size*] ...) - (values `(call ,preinfo ,e ,e* ...) (apply fx+ size size*))] - [(case-lambda ,preinfo (clause (,x** ...) ,interface* ,[body* size*]) ...) - (values `(case-lambda ,preinfo (clause (,x** ...) ,interface* ,body*) ...) (apply fx+ 1 size*))] - [(letrec ([,x* ,[e* size*]] ...) ,[body size]) - (values `(letrec ([,x* ,e* ,size*] ...) ,body) (apply fx+ size size*))] - [(record-ref ,rtd ,type ,index ,[e size]) - (values `(record-ref ,rtd ,type ,index ,e) (fx+ size 1))] - [(record-set! ,rtd ,type ,index ,[e1 size1] ,[e2 size2]) - (values `(record-set! ,rtd ,type ,index ,e1 ,e2) (fx+ size1 size2 1))] - [(record ,rtd ,[rtd-expr size] ,[e* size*] ...) - (values `(record ,rtd ,rtd-expr ,e* ...) (apply fx+ size size*))] - [(cte-optimization-loc ,box ,[e size]) - (values `(cte-optimization-loc ,box ,e) size)] - [(immutable-list (,[e* size*] ...) ,[e size]) - (values `(immutable-list (,e* ...) ,e) (apply fx+ size size*))] - [(quote ,d) (values `(quote ,d) 1)] - [(ref ,maybe-src ,x) (values `(ref ,maybe-src ,x) 1)] - [,pr (values pr 1)] - [(moi) (values `(moi) 1)] - [(pariah) (values `(pariah) 0)] - [(profile ,src) (values `(profile ,src) 0)] - [else (sorry! who "unhandled record ~s" ir)]) - (let-values ([(e size) (Expr ir)]) e)) - - (define-pass cpcommonize1 : Lcommonize1 (ir worthwhile-size) -> Lcommonize2 () - (definitions - (define worthwhile-size? - (lambda (expr-size) - (fx>= expr-size worthwhile-size))) - (define worthwhile-ratio? - (lambda (expr-size subst-count) - (or (fx= subst-count 0) - (fx>= (div expr-size subst-count) 4)))) - (define-record-type subst - (nongenerative) - (sealed #t) - (fields t e1 e2)) - (define-record-type frob - (nongenerative) - (sealed #t) - (fields subst* e b)) - (define ht (make-hashtable values fx=)) - (define make-sym - (lambda x* - (string->symbol (apply string-append (map (lambda (x) (if (prelex? x) (symbol->string (prelex-name x)) x)) x*))))) - (define same-preinfo? - (lambda (p1 p2) - ; ignore differences in src and sexpr - #t)) - (define same-preinfo-lambda? - (lambda (p1 p2) - ; ignore differences src, sexpr, and name - (eq? (preinfo-lambda-libspec p1) (preinfo-lambda-libspec p2)))) - (define-who same-type? - (lambda (ty1 ty2) - (nanopass-case (Ltype Type) ty1 - [(fp-integer ,bits1) - (nanopass-case (Ltype Type) ty2 - [(fp-integer ,bits2) (= bits1 bits2)] - [else #f])] - [(fp-unsigned ,bits1) - (nanopass-case (Ltype Type) ty2 - [(fp-unsigned ,bits2) (= bits1 bits2)] - [else #f])] - [(fp-void) - (nanopass-case (Ltype Type) ty2 - [(fp-void) #t] - [else #f])] - [(fp-scheme-object) - (nanopass-case (Ltype Type) ty2 - [(fp-scheme-object) #t] - [else #f])] - [(fp-u8*) - (nanopass-case (Ltype Type) ty2 - [(fp-u8*) #t] - [else #f])] - [(fp-u16*) - (nanopass-case (Ltype Type) ty2 - [(fp-u16*) #t] - [else #f])] - [(fp-u32*) - (nanopass-case (Ltype Type) ty2 - [(fp-u32*) #t] - [else #f])] - [(fp-fixnum) - (nanopass-case (Ltype Type) ty2 - [(fp-fixnum) #t] - [else #f])] - [(fp-double-float) - (nanopass-case (Ltype Type) ty2 - [(fp-double-float) #t] - [else #f])] - [(fp-single-float) - (nanopass-case (Ltype Type) ty2 - [(fp-single-float) #t] - [else #f])] - [(fp-ftd ,ftd1) - (nanopass-case (Ltype Type) ty2 - [(fp-ftd ,ftd2) (eq? ftd1 ftd2)] - [else #f])] - [else (sorry! who "unhandled foreign type ~s" ty1)]))) - (define okay-to-subst? - (lambda (e) - (define free? - (lambda (x) - (and (not (prelex-operand x)) #t))) - (nanopass-case (Lcommonize1 Expr) e - [(ref ,maybe-src1 ,x1) (and (not (prelex-assigned x1)) (free? x1))] - [(quote ,d) #t] - [,pr (all-set? (prim-mask proc) (primref-flags pr))] - [else #f]))) - (define constant-equal? - (lambda (x y) - (define record-equal? - (lambda (x y e?) - (let ([rtd ($record-type-descriptor x)]) - (and (eq? ($record-type-descriptor y) rtd) - (let f ([field-name* (csv7:record-type-field-names rtd)] [i 0]) - (or (null? field-name*) - (and (let ([accessor (csv7:record-field-accessor rtd i)]) - (e? (accessor x) (accessor y))) - (f (cdr field-name*) (fx+ i 1))))))))) - (parameterize ([default-record-equal-procedure record-equal?]) - ; equal? should be okay since even mutable constants aren't supposed to be mutated - (equal? x y)))) - (define same? - (lambda (e1 e2) - (nanopass-case (Lcommonize1 Expr) e1 - [(ref ,maybe-src1 ,x1) - (nanopass-case (Lcommonize1 Expr) e2 - [(ref ,maybe-src2 ,x2) - (or (eq? x1 x2) - (eq? (prelex-operand x1) x2))] - [else #f])] - [(quote ,d1) - (nanopass-case (Lcommonize1 Expr) e2 - [(quote ,d2) (constant-equal? d1 d2)] - [else #f])] - [,pr1 - (nanopass-case (Lcommonize1 Expr) e2 - [,pr2 (eq? pr1 pr2)] - [else #f])] - [(moi) - (nanopass-case (Lcommonize1 Expr) e2 - [(moi) #t] - [else #f])] - [(pariah) - (nanopass-case (Lcommonize1 Expr) e2 - [(pariah) #t] - [else #f])] - [(profile ,src1) - (nanopass-case (Lcommonize1 Expr) e2 - [(profile ,src2) (eq? src1 src2)] - [else #f])] - [(call ,preinfo1 ,pr1 (quote ,d1)) - (guard (eq? (primref-name pr1) '$top-level-value)) - (nanopass-case (Lcommonize1 Expr) e2 - [(call ,preinfo2 ,pr2 (quote ,d2)) - (guard (eq? (primref-name pr2) '$top-level-value)) - (and (same-preinfo? preinfo1 preinfo2) (eq? d1 d2))] - [else #f])] - [else #f]))) - (define-who unify - (lambda (e1 e2) - (module (with-env) - (define $with-env - (lambda (x1* x2* th) - (dynamic-wind - (lambda () (map (lambda (x1 x2) (prelex-operand-set! x1 x2) (prelex-operand-set! x2 #t)) x1* x2*)) - th - (lambda () (map (lambda (x1 x2) (prelex-operand-set! x1 #f) (prelex-operand-set! x2 #f)) x1* x2*))))) - (define-syntax with-env - (syntax-rules () - [(_ x1* x2* e) ($with-env x1* x2* (lambda () e))]))) - (call/cc - (lambda (return) - (let ([subst* '()]) - (define lookup-subst - (lambda (e1 e2) - (define same-subst? - (lambda (x) - (and (same? (subst-e1 x) e1) (same? (subst-e2 x) e2)))) - (cond - [(find same-subst? subst*) => - (lambda (subst) - (let ([t (subst-t subst)]) - (set-prelex-multiply-referenced! t #t) - t))] - [else #f]))) - (let ([e (with-output-language (Lcommonize1 Expr) - (let () - (define fclause - (lambda (cl1 cl2) - (nanopass-case (Lcommonize1 CaseLambdaClause) cl1 - [(clause (,x1* ...) ,interface1 ,body1) - (nanopass-case (Lcommonize1 CaseLambdaClause) cl2 - [(clause (,x2* ...) ,interface2 ,body2) - (if (fx= interface1 interface2) - (with-env x1* x2* - (with-output-language (Lcommonize1 CaseLambdaClause) - `(clause (,x1* ...) ,interface1 ,(f body1 body2)))) - (return (iffalse #f (printf "lambda interfaces don't match\n")) '()))])]))) - (define f - (case-lambda - [(e1 e2) (f e1 e2 #f)] - [(e1 e2 call-position?) - (or (cond - [(same? e1 e2) e1] - [(and (not call-position?) (okay-to-subst? e1) (okay-to-subst? e2)) - `(ref #f ,(or (lookup-subst e1 e2) - (let ([t (make-prelex*)]) - (set-prelex-referenced! t #t) - (set! subst* (cons (make-subst t e1 e2) subst*)) - t)))] - [else - (nanopass-case (Lcommonize1 Expr) e1 - [(ref ,maybe-src1 ,x1) #f] - [(quote ,d) #f] - [,pr #f] - [(moi) #f] - [(profile ,src1) #f] - ; reject non-same top-level-value calls with constant symbol so they - ; don't end up being abstracted over the symbol in the residual code - [(call ,preinfo ,pr (quote ,d)) - (guard (eq? (primref-name pr) '$top-level-value)) - #f] - ; don't allow abstraction of first (type) argument to $object-ref, foreign-ref, etc., - ; since they can't be inlined without a constant type. - ; ditto for $tc-field's first (field) argument. - ; there are many other primitives we don't catch here for which the compiler generates - ; more efficient code when certain arguments are constant. - [(call ,preinfo1 ,pr1 (quote ,d1) ,e1* ...) - (guard (memq (primref-name pr1) '($object-ref $swap-object-ref $object-set foreign-ref foreign-set! $tc-field))) - (nanopass-case (Lcommonize1 Expr) e2 - [(call ,preinfo2 ,pr2 (quote ,d2) ,e2* ...) - (guard (eq? pr2 pr1) (eq? d1 d2)) - (and (same-preinfo? preinfo1 preinfo2) - (fx= (length e1*) (length e2*)) - `(call ,preinfo1 ,pr1 (quote ,d1) ,(map f e1* e2*) ...))] - [else #f])] - [(call ,preinfo1 ,e1 ,e1* ...) - (nanopass-case (Lcommonize1 Expr) e2 - [(call ,preinfo2 ,e2 ,e2* ...) - (and (fx= (length e1*) (length e2*)) - (same-preinfo? preinfo1 preinfo2) - `(call ,preinfo1 ,(f e1 e2 #t) ,(map f e1* e2*) ...))] - [else #f])] - [(if ,e10 ,e11 ,e12) - (nanopass-case (Lcommonize1 Expr) e2 - [(if ,e20 ,e21 ,e22) - `(if ,(f e10 e20) ,(f e11 e21) ,(f e12 e22))] - [else #f])] - [(case-lambda ,preinfo1 ,cl1* ...) - (nanopass-case (Lcommonize1 Expr) e2 - [(case-lambda ,preinfo2 ,cl2* ...) - (and (fx= (length cl1*) (length cl2*)) - (same-preinfo-lambda? preinfo1 preinfo2) - `(case-lambda ,preinfo1 ,(map fclause cl1* cl2*) ...))] - [else #f])] - [(seq ,e11 ,e12) - (nanopass-case (Lcommonize1 Expr) e2 - [(seq ,e21 ,e22) `(seq ,(f e11 e21) ,(f e12 e22))] - [else #f])] - [(set! ,maybe-src1 ,x1 ,e1) - (nanopass-case (Lcommonize1 Expr) e2 - [(set! ,maybe-src2 ,x2 ,e2) - (and (eq? x1 x2) - `(set! ,maybe-src1 ,x1 ,(f e1 e2)))] - [else #f])] - [(letrec ([,x1* ,e1* ,size1*] ...) ,body1) - (nanopass-case (Lcommonize1 Expr) e2 - [(letrec ([,x2* ,e2* ,size2*] ...) ,body2) - (and (fx= (length x2*) (length x1*)) - (andmap fx= size1* size2*) - (with-env x1* x2* - `(letrec ([,x1* ,(map f e1* e2*) ,size1*] ...) ,(f body1 body2))))] - [else #f])] - [(foreign (,conv1* ...) ,name1 ,e1 (,arg-type1* ...) ,result-type1) - (nanopass-case (Lcommonize1 Expr) e2 - [(foreign (,conv2* ...) ,name2 ,e2 (,arg-type2* ...) ,result-type2) - (and (equal? conv1* conv2*) - (equal? name1 name2) - (fx= (length arg-type1*) (length arg-type2*)) - (andmap same-type? arg-type1* arg-type2*) - (same-type? result-type1 result-type2) - `(foreign (,conv1* ...) ,name1 ,(f e1 e2) (,arg-type1* ...) ,result-type1))] - [else #f])] - [(fcallable (,conv1* ...) ,e1 (,arg-type1* ...) ,result-type1) - (nanopass-case (Lcommonize1 Expr) e2 - [(fcallable (,conv2* ...) ,e2 (,arg-type2* ...) ,result-type2) - (and (equal? conv1* conv2*) - (fx= (length arg-type1*) (length arg-type2*)) - (andmap same-type? arg-type1* arg-type2*) - (same-type? result-type1 result-type2) - `(fcallable (,conv1* ...) ,(f e1 e2) (,arg-type1* ...) ,result-type1))] - [else #f])] - [(cte-optimization-loc ,box1 ,e1) - (nanopass-case (Lcommonize1 Expr) e2 - [(cte-optimization-loc ,box2 ,e2) - (and (eq? box1 box2) - `(cte-optimization-loc ,box1 ,(f e1 e2)))] - [else #f])] - [else (sorry! who "unhandled record ~s" e1)])]) - (return (iffalse #f (parameterize ([print-level 3] [print-length 5]) (printf "unify failed for ~s and ~s (call-position ~s)\n" e1 e2 call-position?))) '()))])) - (f e1 e2)))]) - (values e subst*))))))) - (define sort-substs - ; reestablish original argument order for substituted variables where possible - ; so the arguments to an abstracted procedure aren't shuffled around in the - ; call to the generated helper. - (lambda (subst0* x1* x2*) - (define (this? x x*) (and (not (null? x*)) (eq? x (car x*)))) - (define (next x*) (if (null? x*) x* (cdr x*))) - (let-values ([(new-subst* subst*) (let f ([x1* x1*] [x2* x2*] [subst* subst0*] [n (length subst0*)]) - (cond - [(fx= n 0) (values '() subst*)] - [(find (lambda (subst) - (define (is-this-arg? e x*) - (nanopass-case (Lcommonize1 Expr) e - [(ref ,maybe-src ,x) (this? x x*)] - [else #f])) - (or (is-this-arg? (subst-e1 subst) x1*) - (is-this-arg? (subst-e2 subst) x2*))) - subst*) => - (lambda (subst) - (let-values ([(new-subst* subst*) (f (next x1*) (next x2*) (remq subst subst*) (fx- n 1))]) - (values (cons subst new-subst*) subst*)))] - [else - (let-values ([(new-subst* subst*) (f (next x1*) (next x2*) subst* (fx- n 1))]) - (values (cons (car subst*) new-subst*) (cdr subst*)))]))]) - (safe-assert (null? subst*)) - (safe-assert (fx= (length new-subst*) (length subst0*))) - new-subst*))) - (define find-match - (lambda (b1 ht) - (and (iffalse (worthwhile-size? (binding-size b1)) (printf "skipping b1: under worthwhile size ~s ~s\n" (binding-size b1) worthwhile-size)) - (ormap (lambda (b2) - (iffalse #f (printf "checking ~s & ~s:" (prelex-name (binding-x b1)) (prelex-name (binding-x b2)))) - (nanopass-case (Lcommonize1 Expr) (binding-e b1) - ; NB: restricting to one clause for now...handling multiple - ; NB: clauses should be straightforward with a helper per - ; NB: common clause. - [(case-lambda ,preinfo1 (clause (,x1* ...) ,interface1 ,body1)) - ; NB: no rest interface for now. should be straightforward - (guard (fxnonnegative? interface1)) - (and - (nanopass-case (Lcommonize1 Expr) (binding-e b2) - [(case-lambda ,preinfo2 (clause (,x2* ...) ,interface2 ,body2)) - (guard (fxnonnegative? interface2)) - (let-values ([(e subst*) (unify body1 body2)]) - (and e - (iffalse (worthwhile-ratio? (binding-size b1) (length subst*)) (printf " no, not worthwhile ratio ~s ~s\n" (binding-size b1) (length subst*))) - (let ([subst* (sort-substs subst* x1* x2*)]) - (iffalse #f (printf " yes\n")) - (make-frob subst* e b2))))] - [else (iffalse #f (printf " no, b2 does not meet lambda restrictions\n"))]))] - [else (iffalse #f (printf " no, b1 does not meet lambda restrictions\n"))])) - (hashtable-ref ht (binding-size b1) '()))))) - (define record-helper! - (lambda (b next e*) - (binding-helper-b-set! b next) - (binding-helper-arg*-set! b e*))) - (define build-helper - (lambda (t t* body size helper-box) - (make-binding t - (with-output-language (Lcommonize1 Expr) - `(case-lambda ,(make-preinfo-lambda) (clause (,t* ...) ,(length t*) ,body))) - size - helper-box))) - (define commonize-letrec - (lambda (x* e* size* body) ; e* and body have not been processed - (define (prune-and-process! b) - (let ([b* (remq b (hashtable-ref ht (binding-size b) '()))]) - (if (null? b*) - (hashtable-delete! ht (binding-size b)) - (hashtable-set! ht (binding-size b) b*))) - (unless (binding-helper-b b) (binding-e-set! b (Expr (binding-e b))))) - (if (null? x*) - body - (let ([helper-box (box '())]) - (let ([b* (map (lambda (x e size) (make-binding x e size helper-box)) x* e* size*)]) - (let ([body (let f ([b* b*]) - (if (null? b*) - (Expr body) - (let ([b (car b*)]) - (let ([frob (find-match b ht)]) - (if frob - (let* ([outer-b (frob-b frob)] - [helper-box (binding-helper-box outer-b)] - [helper-b (let ([t (make-prelex* (make-sym (binding-x b) "&" (binding-x outer-b)))]) - (build-helper t (map subst-t (frob-subst* frob)) (frob-e frob) (binding-size outer-b) helper-box))]) - (set-box! helper-box (cons helper-b (unbox helper-box))) - (record-helper! b helper-b (map subst-e1 (frob-subst* frob))) - (record-helper! outer-b helper-b (map subst-e2 (frob-subst* frob))) - (hashtable-update! ht (binding-size outer-b) (lambda (b*) (cons helper-b (remq outer-b b*))) '()) - (f (cdr b*))) - (begin - (hashtable-update! ht (binding-size b) (lambda (b*) (cons b b*)) '()) - (let ([body (f (cdr b*))]) - (prune-and-process! b) - body)))))))]) - (let ([helper-b* (unbox helper-box)]) - (for-each prune-and-process! helper-b*) - (with-output-language (Lcommonize2 Expr) - `(letrec (,helper-b* ...) (,b* ...) ,body)))))))))) - (Expr : Expr (ir) -> Expr () - [(letrec ([,x* ,e* ,size*] ...) ,body) - ; only unassigned lambda bindings post-cpletrec - (safe-assert (andmap (lambda (x) (not (prelex-assigned x))) x*)) - (safe-assert (andmap (lambda (e) (Lcommonize1-lambda? e)) e*)) - (commonize-letrec x* e* size* body)] - [(letrec* ([,x* ,e*] ...) ,body) - ; no letrec* run post-cpletrec - (assert #f)])) - - (define-pass cpcommonize2 : Lcommonize2 (ir) -> Lsrc () - (definitions - (define build-caller - (lambda (e helper-b helper-arg*) - (define-who Arg - (lambda (e) - (with-output-language (Lsrc Expr) - (nanopass-case (Lcommonize1 Expr) e - [(ref ,maybe-src ,x) `(ref ,maybe-src ,x)] - [(quote ,d) `(quote ,d)] - [else (sorry! who "unexpected helper arg ~s" e)])))) - (define propagate - (lambda (alist) - (lambda (e) - (nanopass-case (Lsrc Expr) e - [(ref ,maybe-src ,x) - (cond - [(assq x alist) => cdr] - [else e])] - [else e])))) - (nanopass-case (Lcommonize1 Expr) e - [(case-lambda ,preinfo (clause (,x* ...) ,interface ,body)) - (with-output-language (Lsrc Expr) - `(case-lambda ,preinfo - (clause (,x* ...) ,interface - ,(let loop ([helper-b helper-b] [e* (map Arg helper-arg*)]) - (if (binding-helper-b helper-b) - (nanopass-case (Lcommonize1 Expr) (binding-e helper-b) - [(case-lambda ,preinfo (clause (,x* ...) ,interface ,body)) - (loop (binding-helper-b helper-b) (map (propagate (map cons x* e*)) (map Arg (binding-helper-arg* helper-b))))]) - `(call ,(make-preinfo) - ,(let ([t (binding-x helper-b)]) - (if (prelex-referenced t) - (set-prelex-multiply-referenced! t #t) - (set-prelex-referenced! t #t)) - `(ref #f ,t)) - ,e* ...))))))]))) - (define maybe-build-caller - (lambda (b) - (let ([helper-b (binding-helper-b b)] [e (binding-e b)]) - (if helper-b - (build-caller e helper-b (binding-helper-arg* b)) - (Expr e)))))) - (Expr : Expr (ir) -> Expr () - [(letrec (,helper-b* ...) (,b* ...) ,[body]) - (let loop ([rb* (reverse helper-b*)] [x* (map binding-x b*)] [e* (map maybe-build-caller b*)]) - (if (null? rb*) - `(letrec ([,x* ,e*] ...) ,body) - (let ([b (car rb*)] [rb* (cdr rb*)]) - (if (prelex-referenced (binding-x b)) - (loop rb* (cons (binding-x b) x*) (cons (maybe-build-caller b) e*)) - (loop rb* x* e*)))))])) - - (lambda (x) - (let ([level (commonization-level)]) - (if (fx= level 0) - x - (let ([worthwhile-size (expt 2 (fx- 10 level))]) - (cpcommonize2 (cpcommonize1 (cpcommonize0 x) worthwhile-size)))))))) -) diff --git a/ta6ob/s/cpcommonize.ta6ob b/ta6ob/s/cpcommonize.ta6ob deleted file mode 100644 index 2443675..0000000 Binary files a/ta6ob/s/cpcommonize.ta6ob and /dev/null differ diff --git a/ta6ob/s/cpletrec.ss b/ta6ob/s/cpletrec.ss deleted file mode 100644 index 5231fff..0000000 --- a/ta6ob/s/cpletrec.ss +++ /dev/null @@ -1,392 +0,0 @@ -;;; cpletrec.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -#| -Notes: - - cpletrec does not consider a record-ref form or call to a restricted - primitive, like car, to be pure even at optimize-level 3 because it's - possible it will be moved ahead of an explicit test within a sequence - of letrec* bindings. -|# - -#| -Handling letrec and letrec* - - call cpletrec on each rhs recursively to determine the new rhs, - whether it's pure, and which of the lhs variables are free in it - - call cpletrec on the body - - build a graph. For letrec, create a link from b1 to b2 iff b2 is free - in b1. for letrec*, also create a link from b1 to b2 if neither is - pure and b1 originally appeared before b2. - - determine the strongly connected components of the graph, partially - sorted so that SCC1 comes before SCC2 if there exists a binding b2 - in SCC2 that has a link to a binding b1 in SCC1. - - process each SCC as a separate set of letrec/letrec* bindings: - - for letrec*, sort the bindings of the SCC by their original relative - positions. for letrec, any order will do. - - if SCC contains a single binding b where LHS(b) is not assigned - and RHS(b) is a lambda expression, bind using pure letrec, - - otherwise, if SCC contains a single binding b where LHS(b) is - not free in RHS(b), bind using let - - otherwise, partition into lambda bindings lb ... and complex - bindings cb ... where a binding b is lambda iff LHS(b) is not - assigned and RHS(b) is a lambda expression. Generate: - (let ([LHS(cb) (void)] ...) - (letrec ([LHS(lb) RHS(cb)] ...) - (set! LHS(cb) RHS(cb)) ... - body)) - - assimilate nested pure letrec forms -|# - -(define $cpletrec -(let () - (import (nanopass)) - (include "base-lang.ss") - - (define rtd-flds (csv7:record-field-accessor #!base-rtd 'flds)) - - (define-pass lift-profile-forms : Lsrc (ir) -> Lsrc () - (definitions - (with-output-language (Lsrc Expr) - (define lift-profile-forms - ; pull out profile forms from simple subforms so the profile - ; forms won't interfere with downstream optimizations - (lambda (e* k) - (define extract-profile - (lambda (e profile*) - (define profile? - (lambda (e) - (nanopass-case (Lsrc Expr) e - [(profile ,src) #t] - [(seq ,e1 ,e2) (and (profile? e1) (profile? e2))] - [else #f]))) - (define simple? - (lambda (e) - (nanopass-case (Lsrc Expr) e - [(quote ,d) #t] - [(ref ,maybe-src ,x) #t] - [,pr #t] - [(call ,preinfo ,pr ,e*) (eq? (primref-name pr) '$top-level-value)] - [(case-lambda ,preinfo ,cl* ...) #t] - [else #f]))) - (nanopass-case (Lsrc Expr) e - [(seq ,e1 ,e2) - (guard (and (profile? e1) (simple? e2))) - (values e2 (cons e1 profile*))] - [else (values e profile*)]))) - (let f ([e* e*] [re* '()] [profile* '()]) - (if (null? e*) - (fold-left (lambda (e profile) `(seq ,profile ,e)) - (k (reverse re*)) - profile*) - (let-values ([(e profile*) (extract-profile (car e*) profile*)]) - (f (cdr e*) (cons e re*) profile*)))))))) - (Expr : Expr (ir) -> Expr () - [(call ,preinfo ,[e] ,[e*] ...) - (lift-profile-forms (cons e e*) - (lambda (e*) - `(call ,preinfo ,(car e*) ,(cdr e*) ...)))] - [(letrec ([,x* ,[e*]] ...) ,[body]) - (lift-profile-forms e* - (lambda (e*) - `(letrec ([,x* ,e*] ...) ,body)))] - [(letrec* ([,x* ,[e*]] ...) ,[body]) - (lift-profile-forms e* - (lambda (e*) - `(letrec* ([,x* ,e*] ...) ,body)))])) - - (define-pass cpletrec : Lsrc (ir) -> Lsrc () - (definitions - (define with-initialized-ids - (lambda (old-id* proc) - (let ([new-id* (map (lambda (old-id) - (let ([new-id (make-prelex - (prelex-name old-id) - (let ([flags (prelex-flags old-id)]) - (fxlogor - (fxlogand flags (constant prelex-sticky-mask)) - (fxsll (fxlogand flags (constant prelex-is-mask)) - (constant prelex-was-flags-offset)))) - (prelex-source old-id) - #f)]) - (prelex-operand-set! old-id new-id) - new-id)) - old-id*)]) - (let-values ([v* (proc new-id*)]) - (for-each (lambda (old-id) (prelex-operand-set! old-id #f)) old-id*) - (apply values v*))))) - (define (Expr* e*) - (if (null? e*) - (values '() #t) - (let-values ([(e e-pure?) (Expr (car e*))] - [(e* e*-pure?) (Expr* (cdr e*))]) - (values (cons e e*) (and e-pure? e*-pure?))))) - (with-output-language (Lsrc Expr) - (define build-seq - (lambda (e* body) - (fold-right (lambda (e body) `(seq ,e ,body)) body e*))) - (define build-let - (lambda (call-preinfo lambda-preinfo lhs* rhs* body) - (if (null? lhs*) - body - (let ([interface (length lhs*)]) - `(call ,call-preinfo - (case-lambda ,lambda-preinfo - (clause (,lhs* ...) ,interface ,body)) - ,rhs* ...))))) - (module (cpletrec-letrec) - (define-record-type binding - (fields (immutable lhs) (immutable pos) (mutable rhs) (mutable pure?) (mutable recursive?)) - (nongenerative) - (protocol - (lambda (new) - (lambda (lhs pos) - (new lhs pos #f #f #f))))) - (define-record-type node ; isolate stuff needed for compute-sccs! - (parent binding) - (fields (mutable link*) (mutable root) (mutable done)) - (nongenerative) - (sealed #t) - (protocol - (lambda (make-new) - (lambda (lhs pos) - ((make-new lhs pos) '() #f #f))))) - (define (lambda? x) - (nanopass-case (Lsrc Expr) x - [(case-lambda ,preinfo ,cl* ...) #t] - [else #f])) - (define (cpletrec-bindings *? lhs* rhs*) - (let ([all-b* (map make-node lhs* (enumerate lhs*))]) - (let loop ([b* all-b*] [rhs* rhs*] [last-nonpure #f]) - (unless (null? b*) - (let ([b (car b*)] [rhs (car rhs*)]) - (for-each (lambda (lhs) (set-prelex-seen! lhs #f)) lhs*) - (let-values ([(rhs pure?) (Expr rhs)]) - (binding-rhs-set! b rhs) - (binding-pure?-set! b pure?) - (binding-recursive?-set! b (prelex-seen (binding-lhs b))) - (let ([free* (filter (lambda (b) (prelex-seen (binding-lhs b))) all-b*)]) - (if (or pure? (not *?)) - (begin - (node-link*-set! b free*) - (loop (cdr b*) (cdr rhs*) last-nonpure)) - (begin - (node-link*-set! b - (if (and last-nonpure (not (memq last-nonpure free*))) - (cons last-nonpure free*) - free*)) - (loop (cdr b*) (cdr rhs*) b)))))))) - all-b*)) - (define (compute-sccs v*) ; Tarjan's algorithm - (define scc* '()) - (define (compute-sccs v) - (define index 0) - (define stack '()) - (define (tarjan v) - (let ([v-index index]) - (node-root-set! v v-index) - (set! stack (cons v stack)) - (set! index (fx+ index 1)) - (for-each - (lambda (v^) - (unless (node-done v^) - (unless (node-root v^) (tarjan v^)) - (node-root-set! v (fxmin (node-root v) (node-root v^))))) - (node-link* v)) - (when (fx= (node-root v) v-index) - (set! scc* - (cons - (let f ([ls stack]) - (let ([v^ (car ls)]) - (node-done-set! v^ #t) - (cons v^ (if (eq? v^ v) - (begin (set! stack (cdr ls)) '()) - (f (cdr ls)))))) - scc*))))) - (tarjan v)) - (for-each (lambda (v) (unless (node-done v) (compute-sccs v))) v*) - (reverse scc*)) - (define (grisly-letrec lb* cb* body) - (let ([rclhs* (fold-right (lambda (b lhs*) - (let ([lhs (binding-lhs b)]) - (if (prelex-referenced/assigned lhs) - (cons lhs lhs*) - lhs*))) - '() cb*)]) - (build-let (make-preinfo) (make-preinfo-lambda) rclhs* (map (lambda (x) `(quote ,(void))) rclhs*) - (build-letrec (map binding-lhs lb*) (map binding-rhs lb*) - (fold-right (lambda (b body) - (let ([lhs (binding-lhs b)] [rhs (binding-rhs b)]) - `(seq - ,(if (prelex-referenced lhs) - (begin - (set-prelex-assigned! lhs #t) - `(set! #f ,lhs ,rhs)) - rhs) - ,body))) - body cb*))))) - (define build-letrec - (lambda (lhs* rhs* body) - (if (null? lhs*) - ; dropping source here; could attach to body or add source record - body - (nanopass-case (Lsrc Expr) body - ; assimilate nested letrecs - [(letrec ([,x* ,e*] ...) ,body) - `(letrec ([,(append lhs* x*) ,(append rhs* e*)] ...) ,body)] - [else `(letrec ([,lhs* ,rhs*] ...) ,body)])))) - (define (expand-letrec b* body) - (if (null? (cdr b*)) - (let* ([b (car b*)] [lhs (binding-lhs b)] [rhs (binding-rhs b)]) - (cond - [(and (not (prelex-referenced/assigned lhs)) (binding-pure? b)) body] - [(and (not (prelex-assigned lhs)) (lambda? rhs)) - (build-letrec (list lhs) (list rhs) body)] - [(not (memq b (node-link* b))) - (build-let (make-preinfo) (make-preinfo-lambda) (list lhs) (list rhs) body)] - [else (grisly-letrec '() b* body)])) - (let-values ([(lb* cb*) (partition - (lambda (b) - (and (not (prelex-assigned (binding-lhs b))) - (lambda? (binding-rhs b)))) - b*)]) - (grisly-letrec lb* cb* body)))) - (define (cpletrec-letrec *? lhs* rhs* body) - (let ([b* (cpletrec-bindings *? lhs* rhs*)]) - (let-values ([(body body-pure?) (Expr body)]) - (values - (let f ([scc* (compute-sccs b*)]) - (if (null? scc*) - body - (expand-letrec - (if *? - (sort - (lambda (b1 b2) (fx< (binding-pos b1) (binding-pos b2))) - (car scc*)) - (car scc*)) - (f (cdr scc*))))) - (and body-pure? (andmap binding-pure? b*))))))))) - (Expr : Expr (ir) -> Expr (#t) - [(ref ,maybe-src ,x) - (let ([x (prelex-operand x)]) - (safe-assert (prelex? x)) - (safe-assert (prelex-was-referenced x)) - (when (prelex-referenced x) - (safe-assert (prelex-was-multiply-referenced x)) - (set-prelex-multiply-referenced! x #t)) - (set-prelex-seen/referenced! x #t) - (values `(ref ,maybe-src ,x) (not (prelex-was-assigned x))))] - [(quote ,d) (values ir #t)] - [(call ,preinfo0 (case-lambda ,preinfo1 (clause (,x* ...) ,interface ,body)) ,e* ...) - (guard (fx= (length e*) interface)) - (with-initialized-ids x* - (lambda (x*) - (let-values ([(body body-pure?) (Expr body)]) - (let-values ([(pre* lhs* rhs* pure?) - (let f ([x* x*] [e* e*]) - (if (null? x*) - (values '() '() '() #t) - (let ([x (car x*)]) - (let-values ([(e e-pure?) (Expr (car e*))] - [(pre* lhs* rhs* pure?) (f (cdr x*) (cdr e*))]) - (if (prelex-referenced/assigned x) - (values pre* (cons x lhs*) (cons e rhs*) (and e-pure? pure?)) - (values (if e-pure? pre* (cons e pre*)) - lhs* rhs* (and e-pure? pure?)))))))]) - (values - (build-seq pre* (build-let preinfo0 preinfo1 lhs* rhs* body)) - (and body-pure? pure?))))))] - [(call ,preinfo ,pr ,e* ...) - (let () - (define (arity-okay? arity n) - (or (not arity) - (ormap (lambda (a) - (or (fx= n a) - (and (fx< a 0) (fx>= n (fx- -1 a))))) - arity))) - (let-values ([(e* pure?) (Expr* e*)]) - (values - `(call ,preinfo ,pr ,e* ...) - (and pure? - (all-set? (prim-mask (or proc pure unrestricted discard)) (primref-flags pr)) - (arity-okay? (primref-arity pr) (length e*))))))] - [(call ,preinfo ,[e pure?] ,[e* pure?*] ...) - (values `(call ,preinfo ,e ,e* ...) #f)] - [(if ,[e0 e0-pure?] ,[e1 e1-pure?] ,[e2 e2-pure?]) - (values `(if ,e0 ,e1 ,e2) (and e0-pure? e1-pure? e2-pure?))] - [(case-lambda ,preinfo ,[cl*] ...) - (values `(case-lambda ,preinfo ,cl* ...) #t)] - [(seq ,[e1 e1-pure?] ,[e2 e2-pure?]) - (values `(seq ,e1 ,e2) (and e1-pure? e2-pure?))] - [(set! ,maybe-src ,x ,[e pure?]) - (let ([x (prelex-operand x)]) - (safe-assert (prelex? x)) - (safe-assert (prelex-was-assigned x)) - ; NB: cpletrec-letrec assumes assignments to unreferenced ids are dropped - (if (prelex-was-referenced x) - (begin - (set-prelex-seen/assigned! x #t) - (values `(set! ,maybe-src ,x ,e) #f)) - (if pure? (values `(quote ,(void)) #t) (values `(seq ,e (quote ,(void))) #f))))] - [(letrec ([,x* ,e*] ...) ,body) - (with-initialized-ids x* - (lambda (x*) - (cpletrec-letrec #f x* e* body)))] - [(letrec* ([,x* ,e*] ...) ,body) - (with-initialized-ids x* - (lambda (x*) - (cpletrec-letrec #t x* e* body)))] - [(foreign (,conv* ...) ,name ,[e pure?] (,arg-type* ...) ,result-type) - (values `(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) - (and (fx= (optimize-level) 3) pure?))] - [(fcallable (,conv* ...) ,[e pure?] (,arg-type* ...) ,result-type) - (values `(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type) - (and (fx= (optimize-level) 3) pure?))] - [(record-ref ,rtd ,type ,index ,[e pure?]) - (values `(record-ref ,rtd ,type ,index ,e) #f)] - [(record-set! ,rtd ,type ,index ,[e1 pure1?] ,[e2 pure2?]) - (values `(record-set! ,rtd ,type ,index ,e1 ,e2) #f)] - [(record ,rtd ,[rtd-expr rtd-pure?] ,e* ...) - (let-values ([(e* pure?) (Expr* e*)]) - (values - `(record ,rtd ,rtd-expr ,e* ...) - (and (and rtd-pure? pure?) - (andmap - (lambda (fld) - (and (not (fld-mutable? fld)) - (eq? (filter-foreign-type (fld-type fld)) 'scheme-object))) - (rtd-flds rtd)))))] - [(record-type ,rtd ,e) (Expr e)] - [(record-cd ,rcd ,rtd-expr ,e) (Expr e)] - [(immutable-list (,[e* pure?*] ...) ,[e pure?]) - (values `(immutable-list (,e* ...) ,e) pure?)] - [,pr (values pr #t)] - [(moi) (values ir #t)] - [(pariah) (values ir #t)] - [(cte-optimization-loc ,box ,[e pure?]) - (values `(cte-optimization-loc ,box ,e) pure?)] - [(profile ,src) (values ir #f)] - [else (sorry! who "unhandled record ~s" ir)]) - (CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause () - [(clause (,x* ...) ,interface ,body) - (with-initialized-ids x* - (lambda (x*) - (let-values ([(body pure?) (Expr body)]) - `(clause (,x* ...) ,interface ,body))))]) - (let-values ([(ir pure?) (Expr ir)]) ir)) - -(lambda (x) - (let ([x (if (eq? ($compile-profile) 'source) (lift-profile-forms x) x)]) - (cpletrec x))) -)) diff --git a/ta6ob/s/cpletrec.ta6ob b/ta6ob/s/cpletrec.ta6ob deleted file mode 100644 index becbec1..0000000 Binary files a/ta6ob/s/cpletrec.ta6ob and /dev/null differ diff --git a/ta6ob/s/cpnanopass.ss b/ta6ob/s/cpnanopass.ss deleted file mode 100644 index 90eee4b..0000000 --- a/ta6ob/s/cpnanopass.ss +++ /dev/null @@ -1,16127 +0,0 @@ -;;; cpnanopass.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(let () - (include "np-languages.ss") - - (define track-dynamic-closure-counts ($make-thread-parameter #f (lambda (x) (and x #t)))) - - (define track-static-closure-counts - ($make-thread-parameter - #f - (lambda (x) - (include "types.ss") - (cond - [(or (not x) (static-closure-info? x)) x] - [(eq? x #t) (make-static-closure-info)] - [else ($oops '$trace-static-closure-counts "~s is not a static-closure-info record or #f" x)])))) - - (module () - (include "types.ss") - - (set-who! $dynamic-closure-counts - (lambda () - (vector - (profile-counter-count #{raw-ref-count bhowt6w0coxl0s2y-1}) - (profile-counter-count #{raw-create-count bhowt6w0coxl0s2y-2}) - (profile-counter-count #{raw-alloc-count bhowt6w0coxl0s2y-3}) - (profile-counter-count #{ref-count bhowt6w0coxl0s2y-4}) - (profile-counter-count #{pair-create-count bhowt6w0coxl0s2y-5}) - (profile-counter-count #{vector-create-count bhowt6w0coxl0s2y-6}) - (profile-counter-count #{vector-alloc-count bhowt6w0coxl0s2y-8}) - (profile-counter-count #{padded-vector-alloc-count bhowt6w0coxl0s2y-11}) - (profile-counter-count #{closure-create-count bhowt6w0coxl0s2y-7}) - (profile-counter-count #{closure-alloc-count bhowt6w0coxl0s2y-9}) - (profile-counter-count #{padded-closure-alloc-count bhowt6w0coxl0s2y-10})))) - - (set-who! $clear-dynamic-closure-counts - (lambda () - (profile-counter-count-set! #{raw-ref-count bhowt6w0coxl0s2y-1} 0) - (profile-counter-count-set! #{raw-create-count bhowt6w0coxl0s2y-2} 0) - (profile-counter-count-set! #{raw-alloc-count bhowt6w0coxl0s2y-3} 0) - (profile-counter-count-set! #{ref-count bhowt6w0coxl0s2y-4} 0) - (profile-counter-count-set! #{pair-create-count bhowt6w0coxl0s2y-5} 0) - (profile-counter-count-set! #{vector-create-count bhowt6w0coxl0s2y-6} 0) - (profile-counter-count-set! #{vector-alloc-count bhowt6w0coxl0s2y-8} 0) - (profile-counter-count-set! #{padded-vector-alloc-count bhowt6w0coxl0s2y-11} 0) - (profile-counter-count-set! #{closure-create-count bhowt6w0coxl0s2y-7} 0) - (profile-counter-count-set! #{closure-alloc-count bhowt6w0coxl0s2y-9} 0) - (profile-counter-count-set! #{padded-closure-alloc-count bhowt6w0coxl0s2y-10} 0)))) - - (define-syntax traceit - (syntax-rules (x) - [(_ name) (set! name (let ([t name]) (trace-lambda name args (apply t args))))])) - - (define-syntax architecture - (let ([fn (format "~a.ss" (constant architecture))]) - (with-source-path 'architecture fn - (lambda (fn) - (let* ([p ($open-file-input-port 'include fn)] - [sfd ($source-file-descriptor fn p)] - [p (transcoded-port p (current-transcoder))]) - (let ([do-read ($make-read p sfd 0)]) - (let* ([regs (do-read)] [inst (do-read)] [asm (do-read)]) - (when (eof-object? asm) ($oops #f "too few expressions in ~a" fn)) - (unless (eof-object? (do-read)) ($oops #f "too many expressions in ~a" fn)) - (close-input-port p) - (lambda (x) - (syntax-case x (registers instructions assembler) - [(k registers) (datum->syntax #'k regs)] - [(k instructions) (datum->syntax #'k inst)] - [(k assembler) (datum->syntax #'k asm)]))))))))) - - ; version in cmacros uses keyword as template and should - ; probably be changed to use the id - (define-syntax define-who - (lambda (x) - (syntax-case x () - [(_ (id . args) b1 b2 ...) - (identifier? #'id) - #'(define-who id (lambda args b1 b2 ...))] - [(_ id e) - (identifier? #'id) - (with-implicit (id who) - #'(define id (let ([who 'id]) e)))]))) - - (module (get-passes pass xpass pass-time?) - (define-syntax passes-loc (make-compile-time-value (box '()))) - (define-syntax get-passes - (lambda (x) - (lambda (r) - (syntax-case x () - [(_) #`(unbox (quote #,(datum->syntax #'* (r #'passes-loc))))])))) - (module (pass) - (define ir-printer - (lambda (unparser) - (lambda (val*) - (safe-assert (not (null? val*))) - (pretty-print (flatten-seq (unparser (car val*))))))) - (define values-printer - (lambda (val*) - (if (null? val*) - (printf "no output\n") - (pretty-print (car val*))))) - (define-syntax pass - (syntax-rules () - [(_ (pass-name ?arg ...) ?unparser) - (identifier? #'pass-name) - (let ([pass-name (pass-name ?arg ...)]) - (lambda args (xpass pass-name (ir-printer ?unparser) args)))] - [(_ pass-name ?unparser) - (identifier? #'pass-name) - (lambda args (xpass pass-name (ir-printer ?unparser) args))] - [(_ (pass-name ?arg ...)) - (identifier? #'pass-name) - (let ([pass-name (pass-name ?arg ...)]) - (lambda args (xpass pass-name values-printer args)))] - [(_ pass-name) - (identifier? #'pass-name) - (lambda args (xpass pass-name values-printer args))]))) - (module (xpass pass-time?) - (define-threaded pass-time?) - (define $xpass - (lambda (printer pass-name pass arg*) - (let-values ([val* (let ([th (lambda () (apply pass arg*))]) - (if pass-time? ($pass-time pass-name th) (th)))]) - (when (memq pass-name (tracer)) - (printf "output of ~s:\n" pass-name) - (printer val*)) - (apply values val*)))) - (define-syntax xpass - (lambda (x) - (syntax-case x () - [(_ pass-name ?printer ?args) - (lambda (r) - (let ([loc (r #'passes-loc)]) - (set-box! loc (cons (datum pass-name) (unbox loc)))) - #`($xpass ?printer 'pass-name pass-name ?args))])))) - (define flatten-seq - (lambda (x) - (define helper - (lambda (x*) - (if (null? x*) - '() - (let ([x (car x*)]) - (if (and (pair? x) (eq? (car x) 'seq)) - (append (helper (cdr x)) (helper (cdr x*))) - (cons (flatten-seq x) (helper (cdr x*)))))))) - (cond - [(null? x) '()] - [(and (pair? x) (eq? (car x) 'seq)) - (let ([x* (helper (cdr x))]) - (if (fx= (length x*) 1) - (car x*) - (cons 'begin x*)))] - [(and (pair? x) (eq? (car x) 'quote)) x] - [(list? x) (map flatten-seq x)] - [else x])))) - - (define compose - (lambda (v p . p*) - (let loop ([v* (list v)] [p p] [p* p*]) - (if (null? p*) - (apply p v*) - (let-values ([v* (apply p v*)]) - (loop v* (car p*) (cdr p*))))))) - - (define-syntax with-virgin-quasiquote - (lambda (x) - (syntax-case x () - [(k e1 e2 ...) - #`(let-syntax ([#,(datum->syntax #'k 'quasiquote) - (syntax-rules () [(_ x) `x])]) - e1 e2 ...)]))) - - (define valid-pass? - (lambda (x) - (memq x (get-passes)))) - - (define last-pass ; potentially not thread-safe, but currently unused - (make-parameter #f - (lambda (x) - (unless (or (eq? x #f) (valid-pass? x)) - (errorf 'last-pass "~s is not a valid pass" x)) - x))) - - (define tracer ; potentially not thread-safe, but currently unused - (let ([ls '()]) - (case-lambda - [() ls] - [(x) - (cond - [(or (null? x) (not x)) (set! ls '())] - [(eq? x #t) (set! ls (get-passes))] - [(valid-pass? x) (set! ls (cons x ls))] - [(list? x) (for-each tracer x)] - [else (errorf 'tracer "invalid trace list or pass name: ~s" x)])]))) - - (define maybe-cons - (lambda (x ls) - (if x (cons x ls) ls))) - - (define unannotate - (lambda (x) - (if (annotation? x) - (annotation-expression x) - x))) - - (let () - (import (nanopass) np-languages) - - (define signed-32? - (let ([n (bitwise-arithmetic-shift-left 1 (fx- 32 1))]) - (let ([low (- n)] [high (- n 1)]) - (if (fixnum? low) - (lambda (x) (and (fixnum? x) (fx<= low x high))) - (lambda (x) (or (fixnum? x) (<= low x high))))))) - - (define nodups - (lambda x** - (let ([x* (apply append x**)]) - (let ([ans (andmap (lambda (x) (and (not (uvar-seen? x)) (uvar-seen! x #t) #t)) x*)]) - (for-each (lambda (x) (uvar-seen! x #f)) x*) - ans)))) - - (define chunked-bytevector-bitcount - ; assumes "chunked" bytevector a multiple of 2 in size - (let ([bitcount-bv (make-bytevector #x10000)]) - (do ([i 0 (fx+ i 1)]) - ((fx= i #x10000)) - (bytevector-u8-set! bitcount-bv i (fxbit-count i))) - (lambda (bv) - (let loop ([n (bytevector-length bv)] [count 0]) - (if (fx= n 0) - count - (let ([n (fx- n 2)]) - (loop n (fx+ (bytevector-u8-ref bitcount-bv - (bytevector-u16-native-ref bv n)) - count)))))))) - - (module (empty-tree full-tree tree-extract tree-for-each tree-fold-left tree-bit-set? tree-bit-set tree-bit-unset tree-bit-count tree-same? tree-merge) - ; tree -> fixnum | (tree-node tree tree) - ; 0 represents any tree or subtree with no bits set, and a tree or subtree - ; with no bits set is always 0 - (define empty-tree 0) - - ; any tree or subtree with all bits set - (define full-tree #t) - - (define (full-fixnum size) (fxsrl (most-positive-fixnum) (fx- (fx- (fixnum-width) 1) size))) - - (define compute-split - (lambda (size) - (fxsrl size 1) - ; 2015/03/15 rkd: tried the following under the theory that we'd allocate - ; fewer nodes. for example, say fixmun-width is 30 and size is 80. if we - ; split 40/40 we create two nodes under the current node. if instead we - ; split 29/51 we create just one node and one fixnum under the current - ; node. this worked as planned; however, it reduced the number of nodes - ; created by only 3.3% on the x86 and made compile times slightly worse. - #;(if (fx<= size (fx* (fx- (fixnum-width) 1) 3)) (fx- (fixnum-width) 1) (fxsrl size 1)))) - - (meta-cond - [(fx= (optimize-level) 3) - (module (make-tree-node tree-node? tree-node-left tree-node-right) - (define make-tree-node cons) - (define tree-node? pair?) - (define tree-node-left car) - (define tree-node-right cdr))] - [else - (module (make-tree-node tree-node? tree-node-left tree-node-right) - (define-record-type tree-node - (nongenerative) - (sealed #t) - (fields left right) - (protocol - (lambda (new) - (lambda (left right) - (new left right))))) - (record-writer (record-type-descriptor tree-node) - (lambda (r p wr) - (define tree-node->s-exp - (lambda (tn) - (with-virgin-quasiquote - (let ([left (tree-node-left tn)] [right (tree-node-right tn)]) - `(tree-node - ,(if (tree-node? left) (tree-node->s-exp left) left) - ,(if (tree-node? right) (tree-node->s-exp right) right)))))) - (wr (tree-node->s-exp r) p))))]) - - (define tree-extract ; assumes empty-tree is 0 - (lambda (st size v) - (let extract ([st st] [size size] [offset 0] [x* '()]) - (cond - [(fixnum? st) - (do ([st st (fxsrl st 1)] - [offset offset (fx+ offset 1)] - [x* x* (if (fxodd? st) (cons (vector-ref v offset) x*) x*)]) - ((fx= st 0) x*))] - [(eq? st full-tree) - (do ([size size (fx- size 1)] - [offset offset (fx+ offset 1)] - [x* x* (cons (vector-ref v offset) x*)]) - ((fx= size 0) x*))] - [else - (let ([split (compute-split size)]) - (extract (tree-node-right st) (fx- size split) (fx+ offset split) - (extract (tree-node-left st) split offset x*)))])))) - - (define tree-for-each ; assumes empty-tree is 0 - (lambda (st size start end action) - (let f ([st st] [size size] [start start] [end end] [offset 0]) - (cond - [(fixnum? st) - (unless (eq? st empty-tree) - (do ([st (fxbit-field st start end) (fxsrl st 1)] [offset (fx+ offset start) (fx+ offset 1)]) - ((fx= st 0)) - (when (fxodd? st) (action offset))))] - [(eq? st full-tree) - (do ([start start (fx+ start 1)] [offset offset (fx+ offset 1)]) - ((fx= start end)) - (action offset))] - [else - (let ([split (compute-split size)]) - (when (fx< start split) - (f (tree-node-left st) split start (fxmin end split) offset)) - (when (fx> end split) - (f (tree-node-right st) (fx- size split) (fxmax (fx- start split) 0) (fx- end split) (fx+ offset split))))])))) - - (define tree-fold-left ; assumes empty-tree is 0 - (lambda (proc size init st) - (let f ([st st] [size size] [offset 0] [init init]) - (cond - [(fixnum? st) - (do ([st st (fxsrl st 1)] - [offset offset (fx+ offset 1)] - [init init (if (fxodd? st) (proc init offset) init)]) - ((fx= st 0) init))] - [(eq? st full-tree) - (do ([size size (fx- size 1)] - [offset offset (fx+ offset 1)] - [init init (proc init offset)]) - ((fx= size 0) init))] - [else - (let ([split (compute-split size)]) - (f (tree-node-left st) split offset - (f (tree-node-right st) (fx- size split) (fx+ offset split) init)))])))) - - (define tree-bit-set? ; assumes empty-tree is 0 - (lambda (st size bit) - (let loop ([st st] [size size] [bit bit]) - (cond - [(fixnum? st) - (and (not (eqv? st empty-tree)) - ; fxlogbit? is unnecessarily general, so roll our own - (fxlogtest st (fxsll 1 bit)))] - [(eq? st full-tree) #t] - [else - (let ([split (compute-split size)]) - (if (fx< bit split) - (loop (tree-node-left st) split bit) - (loop (tree-node-right st) (fx- size split) (fx- bit split))))])))) - - (define tree-bit-set ; assumes empty-tree is 0 - (lambda (st size bit) - ; set bit in tree. result is eq? to tr if result is same as tr. - (cond - [(eq? st full-tree) st] - [(fx< size (fixnum-width)) - (let ([st (fxlogbit1 bit st)]) - (if (fx= st (full-fixnum size)) - full-tree - st))] - [else - (let ([split (compute-split size)]) - (if (eqv? st empty-tree) - (if (fx< bit split) - (make-tree-node (tree-bit-set empty-tree split bit) empty-tree) - (make-tree-node empty-tree (tree-bit-set empty-tree (fx- size split) (fx- bit split)))) - (let ([lst (tree-node-left st)] [rst (tree-node-right st)]) - (if (fx< bit split) - (let ([new-lst (tree-bit-set lst split bit)]) - (if (eq? new-lst lst) - st - (if (and (eq? new-lst full-tree) (eq? rst full-tree)) - full-tree - (make-tree-node new-lst rst)))) - (let ([new-rst (tree-bit-set rst (fx- size split) (fx- bit split))]) - (if (eq? new-rst rst) - st - (if (and (eq? lst full-tree) (eq? new-rst full-tree)) - full-tree - (make-tree-node lst new-rst))))))))]))) - - (define tree-bit-unset ; assumes empty-tree is 0 - (lambda (st size bit) - ; reset bit in tree. result is eq? to tr if result is same as tr. - (cond - [(fixnum? st) - (if (eqv? st empty-tree) - empty-tree - (fxlogbit0 bit st))] - [(eq? st full-tree) - (if (fx< size (fixnum-width)) - (fxlogbit0 bit (full-fixnum size)) - (let ([split (compute-split size)]) - (if (fx< bit split) - (make-tree-node (tree-bit-unset full-tree split bit) full-tree) - (make-tree-node full-tree (tree-bit-unset full-tree (fx- size split) (fx- bit split))))))] - [else - (let ([split (compute-split size)] [lst (tree-node-left st)] [rst (tree-node-right st)]) - (if (fx< bit split) - (let ([new-lst (tree-bit-unset lst split bit)]) - (if (eq? new-lst lst) - st - (if (and (eq? new-lst empty-tree) (eq? rst empty-tree)) - empty-tree - (make-tree-node new-lst rst)))) - (let ([new-rst (tree-bit-unset rst (fx- size split) (fx- bit split))]) - (if (eq? new-rst rst) - st - (if (and (eq? lst empty-tree) (eq? new-rst empty-tree)) - empty-tree - (make-tree-node lst new-rst))))))]))) - - (define tree-bit-count ; assumes empty-tree is 0 - (lambda (st size) - (cond - [(fixnum? st) (fxbit-count st)] - [(eq? st full-tree) size] - [else - (let ([split (compute-split size)]) - (fx+ - (tree-bit-count (tree-node-left st) split) - (tree-bit-count (tree-node-right st) (fx- size split))))]))) - - (define tree-same? ; assumes empty-tree is 0 - (lambda (st1 st2) - (or (eq? st1 st2) ; assuming fixnums and full trees are eq-comparable - (and (tree-node? st1) - (tree-node? st2) - (tree-same? (tree-node-left st1) (tree-node-left st2)) - (tree-same? (tree-node-right st1) (tree-node-right st2)))))) - - (define tree-merge - ; merge tr1 and tr2. result is eq? to tr1 if result is same as tr1. - (lambda (st1 st2 size) - (cond - [(or (eq? st1 st2) (eq? st2 empty-tree)) st1] - [(eq? st1 empty-tree) st2] - [(or (eq? st1 full-tree) (eq? st2 full-tree)) full-tree] - [(fixnum? st1) - (safe-assert (fixnum? st2)) - (let ([st (fxlogor st1 st2)]) - (if (fx= st (full-fixnum size)) - full-tree - st))] - [else - (let ([lst1 (tree-node-left st1)] - [rst1 (tree-node-right st1)] - [lst2 (tree-node-left st2)] - [rst2 (tree-node-right st2)]) - (let ([split (compute-split size)]) - (let ([l (tree-merge lst1 lst2 split)] [r (tree-merge rst1 rst2 (fx- size split))]) - (cond - [(and (eq? l lst1) (eq? r rst1)) st1] - [(and (eq? l lst2) (eq? r rst2)) st2] - [(and (eq? l full-tree) (eq? r full-tree)) full-tree] - [else (make-tree-node l r)]))))])))) - - (define-syntax tc-disp - (lambda (x) - (syntax-case x () - [(_ name) - (case (datum name) - [(%ac0) (constant tc-ac0-disp)] - [(%ac1) (constant tc-ac1-disp)] - [(%sfp) (constant tc-sfp-disp)] - [(%cp) (constant tc-cp-disp)] - [(%esp) (constant tc-esp-disp)] - [(%ap) (constant tc-ap-disp)] - [(%eap) (constant tc-eap-disp)] - [(%trap) (constant tc-trap-disp)] - [(%xp) (constant tc-xp-disp)] - [(%yp) (constant tc-yp-disp)] - [else #f])]))) - - (define-syntax define-reserved-registers - (lambda (x) - (syntax-case x () - [(_ [regid alias ... callee-save? mdinfo] ...) - (syntax-case #'(regid ...) (%tc %sfp) [(%tc %sfp . others) #t] [_ #f]) - #'(begin - (begin - (define regid (make-reg 'regid 'mdinfo (tc-disp regid) callee-save?)) - (module (alias ...) (define x regid) (define alias x) ...)) - ...)]))) - - (define-syntax define-allocable-registers - (lambda (x) - (assert (fx<= (constant asm-arg-reg-cnt) (constant asm-arg-reg-max))) - (syntax-case x () - [(_ regvec arg-registers extra-registers with-initialized-registers [regid reg-alias ... callee-save? mdinfo] ...) - (with-syntax ([((tc-disp ...) (arg-regid ...) (extra-regid ...)) - (syntax-case #'(regid ...) (%ac0 %xp %ts %td) - [(%ac0 %xp %ts %td other ...) - (let f ([other* #'(other ...)] - [rtc-disp* '()] - [arg-offset (constant tc-arg-regs-disp)] - [rextra* '()]) - (if (null? other*) - (if (fx= (length rextra*) (constant asm-arg-reg-max)) - (let ([extra* (reverse rextra*)]) - (list - (list* - (constant tc-ac0-disp) - (constant tc-xp-disp) - (constant tc-ts-disp) - (constant tc-td-disp) - (reverse rtc-disp*)) - (list-head extra* (constant asm-arg-reg-cnt)) - (list-tail extra* (constant asm-arg-reg-cnt)))) - (syntax-error x (format "asm-arg-reg-max extra registers are not specified ~s" (syntax->datum rextra*)))) - (let ([other (car other*)]) - (if (memq (syntax->datum other) '(%ac1 %yp %cp %ret)) - (f (cdr other*) (cons #`(tc-disp #,other) rtc-disp*) - arg-offset rextra*) - (f (cdr other*) (cons arg-offset rtc-disp*) - (fx+ arg-offset (constant ptr-bytes)) (cons other rextra*))))))] - [_ (syntax-error x "missing or out-of-order required registers")])] - [(regid-loc ...) (generate-temporaries #'(regid ...))]) - #'(begin - (define-syntax define-squawking-parameter - (syntax-rules () - [(_ (id (... ...)) loc) - (begin - (define loc ($make-thread-parameter #f)) - (define-syntax id - (lambda (q) - (unless (identifier? q) (syntax-error q)) - #`(let ([x (loc)]) - (unless x (syntax-error #'#,q "uninitialized")) - x))) - (... ...))] - [(_ id loc) (define-squawking-parameter (id) loc)])) - (define-squawking-parameter (regid reg-alias ...) regid-loc) - ... - (define-squawking-parameter regvec regvec-loc) - (define-squawking-parameter arg-registers arg-registers-loc) - (define-squawking-parameter extra-registers extra-registers-loc) - (define-syntax with-initialized-registers - (syntax-rules () - [(_ b1 b2 (... ...)) - (parameterize ([regid-loc (make-reg 'regid 'mdinfo tc-disp callee-save?)] ...) - (parameterize ([regvec-loc (vector regid ...)] - [arg-registers-loc (list arg-regid ...)] - [extra-registers-loc (list extra-regid ...)]) - (let () b1 b2 (... ...))))]))))]))) - - (define-syntax define-machine-dependent-registers - (lambda (x) - (syntax-case x () - [(_ [regid alias ... callee-save? mdinfo] ...) - #'(begin - (begin - (define regid (make-reg 'regid 'mdinfo #f callee-save?)) - (module (alias ...) (define x regid) (define alias x) ...)) - ...)]))) - - (define-syntax define-registers - (lambda (x) - (syntax-case x (reserved allocable machine-dependent) - [(k (reserved [rreg rreg-alias ... rreg-callee-save? rreg-mdinfo] ...) - (allocable [areg areg-alias ... areg-callee-save? areg-mdinfo] ...) - (machine-dependent [mdreg mdreg-alias ... mdreg-callee-save? mdreg-mdinfo] ...)) - (with-implicit (k regvec arg-registers extra-registers real-register? with-initialized-registers) - #`(begin - (define-reserved-registers [rreg rreg-alias ... rreg-callee-save? rreg-mdinfo] ...) - (define-allocable-registers regvec arg-registers extra-registers with-initialized-registers [areg areg-alias ... areg-callee-save? areg-mdinfo] ...) - (define-machine-dependent-registers [mdreg mdreg-alias ... mdreg-callee-save? mdreg-mdinfo] ...) - (define-syntax real-register? - (with-syntax ([real-reg* #''(rreg ... rreg-alias ... ... areg ... areg-alias ... ... mdreg ... mdreg-alias ... ...)]) - (syntax-rules () - [(_ e) (memq e real-reg*)])))))]))) - - (architecture registers) - - ; pseudo register used for mref's with no actual index - (define %zero (make-reg 'zero #f #f #f)) - - ; define %ref-ret to be sfp[0] on machines w/no ret register - (define-syntax %ref-ret - (lambda (x) - (meta-cond - [(real-register? '%ret) #'%ret] - [else (with-syntax ([%mref (datum->syntax x '%mref)]) - #'(%mref ,%sfp 0))]))) - - (define make-Ldoargerr - (lambda () - (make-libspec-label 'doargerr (lookup-libspec doargerr) - (reg-list %ret %ac0 %cp)))) - (define make-Ldomvleterr - (lambda () - (make-libspec-label 'domvleterr (lookup-libspec domvleterr) - (reg-list %ret %ac0)))) - (define make-Lcall-error - (lambda () - (make-libspec-label 'call-error (lookup-libspec call-error) - (reg-list %ret %cp)))) - - (module (frame-vars get-fv) - (define-threaded frame-vars) - (define get-fv - (lambda (x) - (let ([n (vector-length frame-vars)]) - (when (fx>= x n) - (let ([new-vec (make-vector (fxmax (fx+ x 1) (fx* n 2)) #f)]) - (let loop ([n n]) - (unless (fx= n 0) - (let ([n (fx- n 1)]) - (vector-set! new-vec n (vector-ref frame-vars n)) - (loop n)))) - (set! frame-vars new-vec)))) - (or (vector-ref frame-vars x) - (let ([fv ($make-fv x)]) - (vector-set! frame-vars x fv) - fv))))) - - (define-syntax reg-cons* - (lambda (x) - (syntax-case x () - [(_ ?reg ... ?reg*) - (fold-right - (lambda (reg reg*) - (if (real-register? (syntax->datum reg)) - #`(cons #,reg #,reg*) - reg*)) - #'?reg* #'(?reg ...))]))) - - (define-syntax reg-list - (syntax-rules () - [(_ ?reg ...) (reg-cons* ?reg ... '())])) - - (define-syntax with-saved-ret-reg - (lambda (x) - (syntax-case x () - [(k ?e) - (if (real-register? '%ret) - (with-implicit (k %seq %mref) - #'(%seq - (set! ,(%mref ,%sfp 0) ,%ret) - ,?e - (set! ,%ret ,(%mref ,%sfp 0)))) - #'?e)]))) - - (module (restore-scheme-state save-scheme-state with-saved-scheme-state) - (define-syntax build-reg-list - ; TODO: create reg records at compile time, and build these lists at compile time - ; TODO: include ts & td - ; TODO: specify three lists: things that need to be saved/restored via the thread context, - ; things that need to be saved/restored somehow, and things that can be trashed - (lambda (x) - (syntax-case x (base-in in out) - [(_ orig-x (base-in base-inreg ...) (in inreg ...) (out outreg ...)) - (let ([all* '(%ts %td %ac0 %ac1 %cp %xp %yp scheme-args extra-regs)] - [in* (datum (inreg ...))] - [out* (datum (outreg ...))]) - (define remove* - (lambda (x* ls) - (if (null? x*) - ls - (remove* (cdr x*) (remq (car x*) ls))))) - (let ([bogus* (remove* all* in*)]) - (unless (equal? bogus* '()) (syntax-error #'orig-x (format "bogus in registers ~s" bogus*)))) - (let ([bogus* (remove* all* out*)]) - (unless (equal? bogus* '()) (syntax-error #'orig-x (format "bogus out registers ~s" bogus*)))) - (unless (equal? (remove* in* out*) out*) - (syntax-error #'orig-x "non-empty intersection")) - (let ([other* (remove* in* (remove* out* all*))]) - (unless (null? other*) - (syntax-error #'orig-x (format "registers not mentioned: ~s" other*)))) - (with-syntax ([(in ...) (datum->syntax #'* - (filter (lambda (x) (real-register? x)) - (append (datum (base-inreg ...)) in*)))]) - #`(cons* (ref-reg in) ... - #,(if (memq 'scheme-args in*) - (if (memq 'extra-regs in*) - #'(append arg-registers extra-registers) - #'arg-registers) - (if (memq 'extra-regs in*) - #'extra-registers - #''())))))]))) - (define-syntax get-tcslot - (lambda (x) - (syntax-case x () - [(_ k reg) - (with-implicit (k in-context %mref) - #'(in-context Lvalue - (%mref ,%tc ,(reg-tc-disp reg))))]))) - (define-syntax $save-scheme-state - (lambda (x) - (syntax-case x () - [(_ k orig-x in out) - (with-implicit (k quasiquote) - ; although eap might be changed by dirty writes, and esp might be changed by - ; one-shot continuation handling, we always write through to the tc so that - ; we never need to save eap or esp and also so that eap, which serves as the - ; base of the current dirty list, is always accurate, even when an invalid - ; memory reference or invalid instruction occurs. so we leave eap and esp - ; out of the save list (but not the restore list below). - #'(let ([regs-to-save (build-reg-list orig-x (base-in %sfp %ap %trap) in out)]) - (fold-left (lambda (body reg) - `(seq (set! ,(get-tcslot k reg) ,reg) ,body)) - `(nop) regs-to-save)))]))) - (define-syntax $restore-scheme-state - (lambda (x) - (syntax-case x () - [(_ k orig-x in out) - (with-implicit (k quasiquote) - #'(let ([regs-to-restore (build-reg-list orig-x (base-in %sfp %ap %trap %eap %esp) in out)]) - (fold-left (lambda (body reg) - `(seq (set! ,reg ,(get-tcslot k reg)) ,body)) - `(nop) regs-to-restore)))]))) - (define-syntax save-scheme-state - (lambda (x) - (syntax-case x () - [(k in out) #`($save-scheme-state k #,x in out)]))) - (define-syntax restore-scheme-state - (lambda (x) - (syntax-case x () - [(k in out) #`($restore-scheme-state k #,x in out)]))) - (define-syntax with-saved-scheme-state - (lambda (x) - (syntax-case x () - [(k in out ?body) - (with-implicit (k quasiquote %seq) - #`(%seq - ,($save-scheme-state k #,x in out) - ,?body - ,($restore-scheme-state k #,x in out)))])))) - - (define-record-type ctci ; compile-time version of code-info - (nongenerative) - (sealed #t) - (fields (mutable live) (mutable rpi*) (mutable closure-fv-names)) - (protocol - (lambda (new) - (lambda () - (new #f '() #f))))) - - (define-record-type ctrpi ; compile-time version of rp-info - (nongenerative) - (sealed #t) - (fields label src sexpr mask)) - - (define-threaded next-lambda-seqno) - - (define-record-type info-lambda (nongenerative) - (parent info) - (sealed #t) - (fields src sexpr libspec interface* (mutable dcl*) (mutable flags) (mutable fv*) (mutable name) - (mutable well-known?) (mutable closure-rep) ctci (mutable pinfo*) seqno) - (protocol - (lambda (pargs->new) - (define next-seqno - (lambda () - (let ([seqno next-lambda-seqno]) - (set! next-lambda-seqno (fx+ seqno 1)) - seqno))) - (rec cons-info-lambda - (case-lambda - [(src sexpr libspec interface*) (cons-info-lambda src sexpr libspec interface* #f 0)] - [(src sexpr libspec interface* name) (cons-info-lambda src sexpr libspec interface* name 0)] - [(src sexpr libspec interface* name flags) - ((pargs->new) src sexpr libspec interface* - (map (lambda (iface) (make-direct-call-label 'dcl)) interface*) - (if (eq? (subset-mode) 'system) (fxlogor flags (constant code-flag-system)) flags) - '() name #f 'closure (and (generate-inspector-information) (make-ctci)) '() (next-seqno))]))))) - - (define-record-type info-call (nongenerative) - (parent info) - (sealed #t) - (fields src sexpr (mutable check?) pariah? error?) - (protocol - (lambda (pargs->new) - (lambda (src sexpr check? pariah? error?) - ((pargs->new) src sexpr check? pariah? error?))))) - - (define-record-type info-newframe (nongenerative) - (parent info) - (sealed #t) - (fields - src - sexpr - cnfv* - nfv* - nfv** - (mutable weight) - (mutable call-live*) - (mutable frame-words) - (mutable local-save*)) - (protocol - (lambda (pargs->new) - (lambda (src sexpr cnfv* nfv* nfv**) - ((pargs->new) src sexpr cnfv* nfv* nfv** 0 #f #f #f))))) - - (define-record-type info-kill* (nongenerative) - (parent info) - (fields kill*)) - - (define-record-type info-kill*-live* (nongenerative) - (parent info-kill*) - (fields live*) - (protocol - (lambda (new) - (case-lambda - [(kill* live*) - ((new kill*) live*)] - [(kill*) - ((new kill*) (reg-list))])))) - - (define-record-type info-asmlib (nongenerative) - (parent info-kill*-live*) - (sealed #t) - (fields libspec save-ra?) - (protocol - (lambda (new) - (case-lambda - [(kill* libspec save-ra? live*) - ((new kill* live*) libspec save-ra?)] - [(kill* libspec save-ra?) - ((new kill*) libspec save-ra?)])))) - - (module (intrinsic-info-asmlib intrinsic-return-live* intrinsic-entry-live* dorest-intrinsics) - ; standing on our heads here to avoid referencing registers at - ; load time...would be cleaner if registers were immutable, - ; i.e., mutable fields (direct and inherited from var) were kept - ; in separate tables...but that might add more cost to register - ; allocation, which is already expensive. - (define-record-type intrinsic (nongenerative) - (sealed #t) - (fields libspec get-kill* get-live* get-rv*)) - (define intrinsic-info-asmlib - (lambda (intrinsic save-ra?) - (make-info-asmlib ((intrinsic-get-kill* intrinsic)) - (intrinsic-libspec intrinsic) - save-ra? - ((intrinsic-get-live* intrinsic))))) - (define intrinsic-return-live* - ; used a handful of times, just while compiling library.ss...don't bother optimizing - (lambda (intrinsic) - (fold-left (lambda (live* kill) (remq kill live*)) - (vector->list regvec) ((intrinsic-get-kill* intrinsic))))) - (define intrinsic-entry-live* - ; used a handful of times, just while compiling library.ss...don't bother optimizing - (lambda (intrinsic) ; return-live* - rv + live* - (fold-left (lambda (live* live) (if (memq live live*) live* (cons live live*))) - (fold-left (lambda (live* rv) (remq rv live*)) - (intrinsic-return-live* intrinsic) - ((intrinsic-get-rv* intrinsic))) - ((intrinsic-get-live* intrinsic))))) - (define-syntax declare-intrinsic - (syntax-rules (unquote) - [(_ name entry-name (kill ...) (live ...) (rv ...)) - (begin - (define name - (make-intrinsic - (lookup-libspec entry-name) - (lambda () (reg-list kill ...)) - (lambda () (reg-list live ...)) - (lambda () (reg-list rv ...)))) - (export name))])) - ; must include in kill ... any register explicitly assigned by the intrinsic - ; plus additional registers as needed to avoid spilled unspillables. the - ; list could be machine-dependent but at this point it doesn't matter. - (declare-intrinsic dofargint32 dofargint32 (%ts %td %xp) (%ac0) (%ac0)) - (constant-case ptr-bits - [(32) (declare-intrinsic dofargint64 dofargint64 (%ts %td %xp) (%ac0) (%ac0 %ac1))] - [(64) (declare-intrinsic dofargint64 dofargint64 (%ts %td %xp) (%ac0) (%ac0))]) - (declare-intrinsic dofretint32 dofretint32 (%ts %td %xp) (%ac0) (%ac0)) - (constant-case ptr-bits - [(32) (declare-intrinsic dofretint64 dofretint64 (%ts %td %xp) (%ac0 %ac1) (%ac0))] - [(64) (declare-intrinsic dofretint64 dofretint64 (%ts %td %xp) (%ac0) (%ac0))]) - (declare-intrinsic dofretuns32 dofretuns32 (%ts %td %xp) (%ac0) (%ac0)) - (constant-case ptr-bits - [(32) (declare-intrinsic dofretuns64 dofretuns64 (%ts %td %xp) (%ac0 %ac1) (%ac0))] - [(64) (declare-intrinsic dofretuns64 dofretuns64 (%ts %td %xp) (%ac0) (%ac0))]) - (declare-intrinsic dofretu8* dofretu8* (%ac0 %ts %td %cp %ac1) (%ac0) (%xp)) - (declare-intrinsic dofretu16* dofretu16* (%ac0 %ts %td %cp %ac1) (%ac0) (%xp)) - (declare-intrinsic dofretu32* dofretu32* (%ac0 %ts %td %cp %ac1) (%ac0) (%xp)) - (declare-intrinsic get-room get-room () (%xp) (%xp)) - (declare-intrinsic scan-remembered-set scan-remembered-set () () ()) - (declare-intrinsic dooverflow dooverflow () () ()) - (declare-intrinsic dooverflood dooverflood () (%xp) ()) - ; a dorest routine takes all of the register and frame arguments from the rest - ; argument forward and also modifies the rest argument. for the rest argument, - ; this is a wash (it's live both before and after). the others should also be - ; listed as live. it's inconvenient and currently unnecessary to do so. - ; (actually currently impossible to list the infinite set of frame arguments) - (define-syntax dorest-intrinsic-max (identifier-syntax 5)) - (export dorest-intrinsic-max) - (define (list-xtail ls n) - (if (or (null? ls) (fx= n 0)) - ls - (list-xtail (cdr ls) (fx1- n)))) - (define dorest-intrinsics - (let () - (define-syntax dorests - (lambda (x) - #`(vector #,@ - (let f ([i 0]) - (if (fx> i dorest-intrinsic-max) - '() - (cons #`(make-intrinsic - (lookup-libspec #,(construct-name #'k "dorest" i)) - (lambda () (reg-list %ac0 %xp %ts %td)) - (lambda () (reg-cons* %ac0 (list-xtail arg-registers #,i))) - (lambda () (let ([ls (list-xtail arg-registers #,i)]) (if (null? ls) '() (list (car ls)))))) - (f (fx+ i 1)))))))) - dorests))) - - (define-record-type info-alloc (nongenerative) - (parent info) - (sealed #t) - (fields tag save-flrv? save-ra?)) - - (define-record-type info-foreign (nongenerative) - (parent info) - (sealed #t) - (fields conv* arg-type* result-type (mutable name)) - (protocol - (lambda (pargs->new) - (lambda (conv* arg-type* result-type) - ((pargs->new) conv* arg-type* result-type #f))))) - - (define-record-type info-literal (nongenerative) - (parent info) - (sealed #t) - (fields indirect? type addr offset)) - - (define-record-type info-lea (nongenerative) - (parent info) - (sealed #t) - (fields offset)) - - (define-record-type info-load (nongenerative) - (parent info) - (sealed #t) - (fields type swapped?)) - - (define-record-type info-loadfl (nongenerative) - (parent info) - (sealed #t) - (fields flreg)) - - (define-record-type info-condition-code (nongenerative) - (parent info) - (sealed #t) - (fields type reversed? invertible?)) - - (define-record-type info-c-simple-call (nongenerative) - (parent info-kill*-live*) - (sealed #t) - (fields save-ra? entry) - (protocol - (lambda (new) - (case-lambda - [(save-ra? entry) ((new '() '()) save-ra? entry)] - [(live* save-ra? entry) ((new '() live*) save-ra? entry)])))) - - (define-record-type info-c-return (nongenerative) - (parent info) - (sealed #t) - (fields offset)) - - (module () - (record-writer (record-type-descriptor info-load) - (lambda (x p wr) - (fprintf p "#" (info-load-type x)))) - (record-writer (record-type-descriptor info-lambda) - (lambda (x p wr) - (fprintf p "#" - (info-lambda-libspec x) (info-lambda-interface* x) (info-lambda-name x) - (info-lambda-well-known? x) - (info-lambda-fv* x)))) - (record-writer (record-type-descriptor info-foreign) - (lambda (x p wr) - (fprintf p "#" (info-foreign-name x)))) - (record-writer (record-type-descriptor info-literal) - (lambda (x p wr) - (fprintf p "#" (info-literal-addr x)))) - ) - - (define-pass cpnanopass : Lsrc (ir) -> L1 () - (definitions - (define-syntax with-uvars - (syntax-rules () - [(_ (x* id*) b1 b2 ...) - (and (identifier? #'x*) (identifier? #'id*)) - (let ([uvar* (map prelex->uvar id*)] [name* (map prelex-name id*)]) - (dynamic-wind - (lambda () (for-each prelex-name-set! id* uvar*)) - (lambda () (let ([x* uvar*]) b1 b2 ...)) - (lambda () (for-each prelex-name-set! id* name*))))])) - (define extract-uvar - (lambda (id) - (let ([x (prelex-name id)]) - (unless (uvar? x) - (sorry! 'extract-uvar "~s is not a uvar" x)) - x)))) - (CaseLambdaExpr : Expr (ir x) -> CaseLambdaExpr () - [(case-lambda ,preinfo (clause (,x** ...) ,interface* ,body*) ...) - (let ([info (make-info-lambda (preinfo-src preinfo) (preinfo-sexpr preinfo) (preinfo-lambda-libspec preinfo) interface* - (preinfo-lambda-name preinfo) (preinfo-lambda-flags preinfo))]) - (when x (uvar-info-lambda-set! x info)) - `(case-lambda ,info - ,(map (lambda (x* interface body) - (with-uvars (uvar* x*) - (in-context CaseLambdaClause - `(clause (,uvar* ...) ,interface ,(Expr body))))) - x** interface* body*) ...))] - [(case-lambda ,preinfo ,cl* ...) - (sorry! who "found unreachable clause" ir)]) - (Expr : Expr (ir) -> Expr () - [(ref ,maybe-src ,x) (extract-uvar x)] - [(set! ,maybe-src ,x ,[e]) `(set! ,(extract-uvar x) ,e)] - [(case-lambda ,preinfo ,cl* ...) (CaseLambdaExpr ir #f)] - [(letrec ([,x* ,e*] ...) ,body) - (with-uvars (uvar* x*) - (let ([e* (map CaseLambdaExpr e* uvar*)]) - `(letrec ([,uvar* ,e*] ...) ,(Expr body))))] - [(call ,preinfo ,e ,[e*] ...) - `(call ,(make-info-call (preinfo-src preinfo) (preinfo-sexpr preinfo) (fx< (optimize-level) 3) #f #f) - ,(Expr e) ,e* ...)] - [(foreign (,conv* ...) ,name ,[e] (,arg-type* ...) ,result-type) - (let ([info (make-info-foreign conv* arg-type* result-type)]) - (info-foreign-name-set! info name) - `(foreign ,info ,e))] - [(fcallable (,conv* ...) ,[e] (,arg-type* ...) ,result-type) - `(fcallable ,(make-info-foreign conv* arg-type* result-type) ,e)]) - (CaseLambdaExpr ir #f)) - - (define find-matching-clause - (lambda (len x** interface* body* kfixed kvariable kfail) - (let f ([x** x**] [interface* interface*] [body* body*]) - (if (null? interface*) - (kfail) - (let ([interface (car interface*)]) - (if (fx< interface 0) - (let ([nfixed (fxlognot interface)]) - (if (fx>= len nfixed) - (kvariable nfixed (car x**) (car body*)) - (f (cdr x**) (cdr interface*) (cdr body*)))) - (if (fx= interface len) - (kfixed (car x**) (car body*)) - (f (cdr x**) (cdr interface*) (cdr body*))))))))) - - (define-syntax define-$type-check - (lambda (x) - (syntax-case x () - [(k L) (with-implicit (k $type-check) - #'(define $type-check - (lambda (mask type expr) - (with-output-language L - (cond - [(fx= type 0) (%inline log!test ,expr (immediate ,mask))] - [(= mask (constant byte-constant-mask)) (%inline eq? ,expr (immediate ,type))] - [else (%inline type-check? ,expr (immediate ,mask) (immediate ,type))])))))]))) - - (define-syntax %type-check - (lambda (x) - (syntax-case x () - [(k mask type expr) - (with-implicit (k $type-check quasiquote) - #'($type-check (constant mask) (constant type) `expr))]))) - - (define-syntax %typed-object-check ; NB: caller must bind e - (lambda (x) - (syntax-case x () - [(k mask type expr) - (with-implicit (k quasiquote %type-check %constant %mref) - #'`(if ,(%type-check mask-typed-object type-typed-object expr) - ,(%type-check mask type - ,(%mref expr ,(constant typed-object-type-disp))) - ,(%constant sfalse)))]))) - - (define-syntax %seq - (lambda (x) - (syntax-case x () - [(k e1 ... e2) - (with-implicit (k quasiquote) - #``#,(fold-right (lambda (x body) #`(seq #,x #,body)) - #'e2 #'(e1 ...)))]))) - - (define-syntax %mref - (lambda (x) - (syntax-case x () - [(k e0 e1 imm) - (with-implicit (k quasiquote) - #'`(mref e0 e1 imm))] - [(k e0 imm) - (with-implicit (k quasiquote) - #'`(mref e0 ,%zero imm))]))) - - (define-syntax %inline - (lambda (x) - (syntax-case x () - [(k name e ...) - (with-implicit (k quasiquote) - #'`(inline ,null-info ,(%primitive name) e ...))]))) - - (define-syntax %lea - (lambda (x) - (syntax-case x () - [(k base offset) - (with-implicit (k quasiquote) - #'`(inline ,(make-info-lea offset) ,%lea1 base))] - [(k base index offset) - (with-implicit (k quasiquote) - #'`(inline ,(make-info-lea offset) ,%lea2 base index))]))) - - (define-syntax %constant - (lambda (x) - (syntax-case x () - [(k x) - (with-implicit (k quasiquote) - #'`(immediate ,(constant x)))]))) - - (define-syntax %tc-ref - (lambda (x) - (define-who field-type - (lambda (struct field) - (cond - [(assq field (getprop struct '*fields* '())) => - (lambda (a) - (apply - (lambda (field type disp len) type) - a))] - [else ($oops who "undefined field ~s-~s" struct field)]))) - (syntax-case x () - [(k field) #'(k ,%tc field)] - [(k e-tc field) - (if (memq (field-type 'tc (datum field)) '(ptr void* uptr iptr)) - (with-implicit (k %mref) - #`(%mref e-tc - #,(lookup-constant - (string->symbol - (format "tc-~a-disp" (datum field)))))) - (syntax-error x "non-ptr-size tc field"))]))) - - (define-syntax %constant-alloc - (lambda (x) - (syntax-case x () - [(k tag size) #'(k tag size #f #f)] - [(k tag size save-flrv?) #'(k tag size save-flrv? #f)] - [(k tag size save-flrv? save-asm-ra?) - (with-implicit (k quasiquote) - #'`(alloc - ,(make-info-alloc (constant tag) save-flrv? save-asm-ra?) - (immediate ,(c-alloc-align size))))]))) - - (define-pass np-recognize-let : L1 (ir) -> L2 () - (definitions - (define seqs-and-profiles? - (lambda (e) - (nanopass-case (L1 Expr) e - [(profile ,src) #t] - [(seq ,e1 ,e2) (and (seqs-and-profiles? e1) (seqs-and-profiles? e2))] - [else #f]))) - (define Profile - (lambda (e) - (let f ([e e] [profile* '()]) - (nanopass-case (L1 Expr) e - [(seq ,e1 ,e2) - (guard (seqs-and-profiles? e1)) - (f e2 (cons e1 profile*))] - [else (values e profile*)])))) - (define build-seq (lambda (e1 e2) (with-output-language (L2 Expr) `(seq ,(Expr e1) ,e2)))) - (define build-seq* (lambda (e* e) (fold-right build-seq e e*)))) - (Expr : Expr (ir) -> Expr () - [(call ,info1 ,[Profile : e profile1*] ,[e*] ...) - (nanopass-case (L1 Expr) e - [(case-lambda ,info2 (clause (,x* ...) ,interface ,[Expr : body])) - (guard (fx= (length e*) interface)) - (build-seq* profile1* `(let ([,x* ,e*] ...) ,body))] - [(letrec ([,x1 ,[Expr : le*]]) ,[Profile : body profile2*]) - ; can't use a guard, since body isn't bound in guard. - (if (eq? body x1) - (build-seq* profile1* - (build-seq* profile2* - `(letrec ([,x1 ,le*]) (call ,info1 ,x1 ,e* ...)))) - `(call ,info1 ,(build-seq* profile1* (Expr e)) ,e* ...))] - [else - `(call ,info1 ,(build-seq* profile1* (Expr e)) ,e* ...)])])) - - (define-pass np-discover-names : L2 (ir) -> L3 () - (definitions - (define ->name - (lambda (x) - (cond - [(uvar? x) (->name (uvar-name x))] - [(string? x) x] - [(symbol? x) - (let ([name ($symbol-name x)]) - (if (pair? name) (cdr name) name))] - [(eq? #f x) #f] - [else (error 'np-discover-names "x is not a name" x)])))) - (Expr : Expr (ir name moi) -> Expr () - [(letrec ([,x* ,le*] ...) ,[body]) - (let ([le* (map (lambda (le x) (CaseLambdaExpr le (->name x) moi)) le* x*)]) - `(letrec ([,x* ,le*] ...) ,body))] - [(let ([,x* ,e*] ...) ,[body]) - (let ([e* (map (lambda (e x) (Expr e (->name x) moi)) e* x*)]) - `(let ([,x* ,e*] ...) ,body))] - ; handle top-level set! (i.e. $set-top-level-value) - [(call ,info ,pr (quote ,d) ,e0) - (guard (and (eq? (primref-name pr) '$set-top-level-value!) (symbol? d))) - (let ([e0 (Expr e0 (->name d) moi)]) - `(call ,info ,pr (quote ,d) ,e0))] - [(call ,info ,[e0 #f moi -> e0] ,[e1* #f moi -> e1*] ...) - `(call ,info ,e0 ,e1* ...)] - [(if ,[e0 #f moi -> e0] ,[e1] ,[e2]) - `(if ,e0 ,e1 ,e2)] - [(seq ,[e0 #f moi -> e0] ,[e1]) - `(seq ,e0 ,e1)] - [(foreign ,info ,[e #f moi -> e]) - (when name (info-foreign-name-set! info name)) - `(foreign ,info ,e)] - [(fcallable ,info ,[e #f moi -> e]) - (info-foreign-name-set! info name) - `(fcallable ,info ,e)] - [(set! ,x ,e0) - (let ([e0 (Expr e0 (->name x) moi)]) `(set! ,x ,e0))] - [(moi) `(quote ,moi)]) - (CaseLambdaExpr : CaseLambdaExpr (ir [name #f] [moi #f]) -> CaseLambdaExpr () - [(case-lambda ,info ,[cl #f name -> cl] ...) - (unless (info-lambda-name info) (info-lambda-name-set! info name)) - `(case-lambda ,info ,cl ...)]) - (CaseLambdaClause : CaseLambdaClause (ir name moi) -> CaseLambdaClause ())) - - (define-pass np-convert-assignments : L3 (ir) -> L4 () - (definitions - (define-syntax %primcall - (lambda (x) - (syntax-case x () - [(k src sexpr prim arg ...) - (identifier? #'prim) - (with-implicit (k quasiquote) - #``(call ,(make-info-call src sexpr #f #f #f) - ,(lookup-primref 3 'prim) - arg ...))]))) - (define unbound-object ($unbound-object)) - (define partition-assigned - (lambda (x*) - (if (null? x*) - (values '() '() '()) - (let ([x (car x*)] [x* (cdr x*)]) - (let-values ([(x* t* a*) (partition-assigned x*)]) - (if (uvar-assigned? x) - (let ([t (make-tmp 't)]) - (uvar-assigned! x #f) - (values (cons t x*) (cons t t*) (cons x a*))) - (values (cons x x*) t* a*))))))) - (define handle-assigned - (lambda (x* body k) - (let-values ([(x* t* a*) (partition-assigned x*)]) - (k x* (if (null? a*) - body - (with-output-language (L4 Expr) - `(let ([,a* ,(map (lambda (t) (%primcall #f #f cons ,t (quote ,unbound-object))) t*)] ...) - ,body)))))))) - (Expr : Expr (ir) -> Expr () - [,x (if (uvar-assigned? x) (%primcall #f #f car ,x) x)] - [(set! ,x ,[e]) (%primcall #f #f set-car! ,x ,e)] - [(let ([,x* ,[e*]] ...) ,[body]) - (handle-assigned x* body - (lambda (x* body) - `(let ([,x* ,e*] ...) ,body)))]) - (CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause () - [(clause (,x* ...) ,interface ,[body]) - (handle-assigned x* body - (lambda (x* body) - `(clause (,x* ...) ,interface ,body)))])) - - ; for use only after mdcl field has been added to the call syntax - (define-syntax %primcall - (lambda (x) - (syntax-case x () - [(k src sexpr prim arg ...) - (identifier? #'prim) - (with-implicit (k quasiquote) - #``(call ,(make-info-call src sexpr #f #f #f) #f - ,(lookup-primref 3 'prim) - arg ...))]))) - - (define-pass np-sanitize-bindings : L4 (ir) -> L4 () - ; must come before suppress-procedure-checks and recognize-mrvs - ; since it sets up uvar-info-lambda, but after convert-assignments - (definitions - (define maybe-build-let - (lambda (x* e* body) - (if (null? x*) - body - (with-output-language (L4 Expr) - `(let ([,x* ,e*] ...) ,body))))) - (define maybe-build-letrec - (lambda (x* e* body) - (if (null? x*) - body - (with-output-language (L4 Expr) - `(letrec ([,x* ,e*] ...) ,body)))))) - (Expr : Expr (ir) -> Expr () - [(let ([,x* ,[e*]] ...) ,[body]) - (with-values - (let f ([x* x*] [e* e*]) - (if (null? x*) - (values '() '() '() '()) - (let-values ([(ex* ee* lx* le*) (f (cdr x*) (cdr e*))]) - (nanopass-case (L4 Expr) (car e*) - [(case-lambda ,info ,cl ...) - (uvar-info-lambda-set! (car x*) info) - (values ex* ee* (cons (car x*) lx*) (cons (car e*) le*))] - [else (values (cons (car x*) ex*) (cons (car e*) ee*) lx* le*)])))) - (lambda (ex* ee* lx* le*) - (maybe-build-let ex* ee* - (maybe-build-letrec lx* le* - body))))])) - - (define-pass np-suppress-procedure-checks : L4 (ir) -> L4 () - ; N.B. check must be done after e and e* have been evaluated, so we attach - ; a flag to the call syntax rather than introducing explicit checks. - ; if we could introduce explicit checks instead, we could avoid doing - ; so along some branches of an if in call context, even if others - ; need the check. c'est la vie. - (Proc : Expr (ir) -> * (#f) - [,x (uvar-info-lambda x)] - [(quote ,d) (procedure? d)] - [,pr #t] - [(seq ,[] ,[* suppress?]) suppress?] - [(if ,[] ,[* suppress1?] ,[* suppress2?]) (and suppress1? suppress2?)] - [(letrec ([,x* ,[]] ...) ,[* suppress?]) suppress?] - [(let ([,x* ,[]] ...) ,[* suppress?]) suppress?] - [(case-lambda ,info ,[] ...) #t] - [else #f]) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> * () - [(case-lambda ,info ,[] ...) (values)]) - (CaseLambdaClause : CaseLambdaClause (ir) -> * () - [(clause (,x* ...) ,interface ,[]) (values)]) - ; NB: explicitly handling every form because the nanopass infrastructure can't autofill when the output is * - (Expr : Expr (ir) -> * () - [,x (values)] - [(quote ,d) (values)] - [(case-lambda ,info ,[] ...) (values)] - [(call ,info0 - (call ,info1 ,pr (quote ,d)) - ,[] ...) - (guard (and (eq? (primref-name pr) '$top-level-value) (symbol? d))) - (info-call-check?-set! info0 #f) - (info-call-check?-set! info1 #f) - (values)] - [(call ,info ,[* suppress?] ,[] ...) - (when suppress? (info-call-check?-set! info #f)) - (values)] - [(if ,[] ,[] ,[]) (values)] - [(seq ,[] ,[]) (values)] - [,pr (values)] - [(let ([,x ,[]] ...) ,[]) (values)] - [(letrec ([,x ,[]] ...) ,[]) (values)] - [(foreign ,info ,[]) (values)] - [(fcallable ,info ,[]) (values)] - [(profile ,src) (values)] - [(pariah) (values)] - [else (sorry! who "unhandled expression ~s" ir)]) - (begin (CaseLambdaExpr ir) ir)) - - (define-pass np-recognize-mrvs : L4 (ir) -> L4.5 () - (definitions - (define insert-procedure-check - (lambda (check? tmp e) - (with-output-language (L4.5 Expr) - (if check? - `(seq - (if ,(%primcall #f #f procedure? ,tmp) - (quote ,(void)) - ,(%primcall #f #f $oops (quote #f) (quote "attempt to apply non-procedure ~s") ,tmp)) - ,e) - e))))) - (Expr : Expr (ir) -> Expr () - [(call ,info ,pr ,e1 ,e2) - (guard (eq? (primref-name pr) 'call-with-values)) - (let ([check? (not (all-set? (prim-mask unsafe) (primref-flags pr)))]) - (Producer e1 check? (info-call-src info) (info-call-sexpr info) - (lambda (e1 src sexpr) - (Consumer e2 e1 check? src sexpr))))] - [(call ,info ,[e] ,[e*] ...) `(call ,info #f ,e ,e* ...)]) - (Producer : Expr (ir check? src sexpr k) -> Expr () - [,x (k `(call ,(make-info-call src sexpr check? #f #f) #f ,x) src sexpr)] - [(case-lambda ,info (clause (,x** ...) ,interface* ,body*) ...) - (find-matching-clause 0 x** interface* body* - (lambda (x* body) (k (Expr body) src sexpr)) - (lambda (nfixed x* body) `(let ([,(car x*) (quote ())]) ,(k (Expr body) src sexpr))) - (lambda () - (let ([tmp (make-tmp 'tp)]) - (uvar-info-lambda-set! tmp info) - `(letrec ([,tmp ,(Expr ir)]) - ,(k tmp src sexpr)))))] - [(seq ,[Expr : e1] ,[Producer : e2]) `(seq ,e1 ,e2)] - [(let ([,x* ,[Expr : e*]] ...) ,[Producer : e]) `(let ([,x* ,e*] ...) ,e)] - [(letrec ([,x* ,[le*]] ...) ,[Producer : e]) `(letrec ([,x* ,le*] ...) ,e)] - [,pr (k `(call ,(make-info-call src sexpr #f #f #f) #f ,pr) src sexpr)] - [else (let ([tmp (make-tmp 'tp)]) - ; force last part of producer to be evaluated before consumer, to - ; avoid interleaved evaluation of producer and consumer - `(let ([,tmp ,(Expr ir)]) - ,(k `(call ,(make-info-call #f #f check? #f #f) #f ,tmp) src sexpr)))]) - (Consumer : Expr (ir producer-or check? src sexpr) -> Expr () - ; generate same code for single-value let-values as for let - [(case-lambda ,info (clause (,x) ,interface ,[Expr : body])) - (guard (= interface 1)) - `(let ([,x ,producer-or]) ,body)] - [(case-lambda ,info (clause (,x** ...) ,interface* ,[Expr : body*]) ...) - `(mvlet ,producer-or ((,x** ...) ,interface* ,body*) ...)] - [,x (cond - [(uvar-info-lambda x) => - (lambda (info) - (define make-tmps - (lambda (n) - (do ([n (if (fx< n 0) (fx- n) n) (fx- n 1)] - [tmp* '() (cons (make-tmp 't) tmp*)]) - ((fx= n 0) tmp*)))) - (let ([interface* (info-lambda-interface* info)]) - (let ([info* (map (lambda (dcl) (make-info-call src sexpr #f #f #f)) (info-lambda-dcl* info))] - [x* (make-list (length interface*) x)] - [x** (map make-tmps interface*)]) - `(mvlet ,producer-or - ((,x** ...) ,interface* (call ,info* ,(info-lambda-dcl* info) ,x* ,x** ...)) - ...))))] - [else (insert-procedure-check check? x `(mvcall ,(make-info-call src sexpr #f #f #f) ,producer-or ,x))])] - [(seq ,[Expr : e1] ,[Consumer : e2]) `(seq ,e1 ,e2)] - [(let ([,x* ,[Expr : e*]] ...) ,[Consumer : e]) `(let ([,x* ,e*] ...) ,e)] - [(letrec ([,x* ,[le*]] ...) ,[Consumer : e]) `(letrec ([,x* ,le*] ...) ,e)] - [,pr `(mvcall ,(make-info-call src sexpr #f #f #f) ,producer-or ,pr)] - [(quote ,d) (guard (procedure? d)) `(mvcall ,(make-info-call src sexpr #f #f #f) ,producer-or (quote ,d))] - [else (let ([tmp (make-tmp 'tc)]) - ; force consumer expression to be evaluated before producer body - ; this includes references to top-level variables: since they can - ; be altered by the producer, we can use a pvalue call - `(let ([,tmp ,(Expr ir)]) - ,(insert-procedure-check check? tmp - `(mvcall ,(make-info-call src sexpr #f #f #f) ,producer-or ,tmp))))])) - - (define-pass np-expand-foreign : L4.5 (ir) -> L4.75 () - (Expr : Expr (ir) -> Expr () - [(foreign ,info ,[e]) - (let ([iface (length (info-foreign-arg-type* info))] - [t (make-tmp 'tentry 'uptr)] - [t* (map (lambda (x) (make-tmp 't)) (info-foreign-arg-type* info))]) - (let ([lambda-info (make-info-lambda #f #f #f (list iface) (info-foreign-name info))]) - `(let ([,t ,e]) - (case-lambda ,lambda-info - (clause (,t* ...) ,iface - (foreign-call ,info ,t ,t* ...))))))] - [(fcallable ,info ,[e]) - (%primcall #f #f $instantiate-code-object - (fcallable ,info) - (quote 0) ; hard-wiring "cookie" to 0 - ,e)])) - - (define-pass np-recognize-loops : L4.75 (ir) -> L4.875 () - ; TODO: also recognize andmap/for-all, ormap/exists, for-each - ; and remove inline handlers - (definitions - (define make-assigned-tmp - (lambda (x) - (let ([t (make-tmp 'tloop)]) - (uvar-assigned! t #t) - t)))) - (Expr : Expr (ir [tail* '()]) -> Expr () - [,x (uvar-referenced! x #t) (uvar-loop! x #f) x] - [(letrec ([,x1 (case-lambda ,info1 - (clause (,x* ...) ,interface - ,body))]) - (call ,info2 ,mdcl ,x2 ,e* ...)) - (guard (eq? x2 x1) (eq? (length e*) interface)) - (uvar-referenced! x1 #f) - (uvar-loop! x1 #t) - (let ([tref?* (map uvar-referenced? tail*)]) - (for-each (lambda (x) (uvar-referenced! x #f)) tail*) - (let ([e* (map (lambda (e) (Expr e '())) e*)] - [body (Expr body (cons x1 tail*))]) - (let ([body-tref?* (map uvar-referenced? tail*)]) - (for-each (lambda (x tref?) (when tref? (uvar-referenced! x #t))) tail* tref?*) - (if (uvar-referenced? x1) - (if (uvar-loop? x1) - (let ([t* (map make-assigned-tmp x*)]) - `(let ([,t* ,e*] ...) - (loop ,x1 (,t* ...) - (let ([,x* ,t*] ...) - ,body)))) - (begin - (for-each (lambda (x body-tref?) - (when body-tref? (uvar-loop! x #f))) - tail* body-tref?*) - `(letrec ([,x1 (case-lambda ,info1 - (clause (,x* ...) ,interface - ,body))]) - (call ,info2 ,mdcl ,x2 ,e* ...)))) - `(let ([,x* ,e*] ...) ,body)))))] - [(letrec ([,x* ,[le*]] ...) ,[body]) - `(letrec ([,x* ,le*] ...) ,body)] - [(call ,info ,mdcl ,x ,[e* '() -> e*] ...) - (guard (memq x tail*)) - (uvar-referenced! x #t) - (let ([interface* (info-lambda-interface* (uvar-info-lambda x))]) - (unless (and (fx= (length interface*) 1) (fx= (length e*) (car interface*))) - (uvar-loop! x #f))) - `(call ,info ,mdcl ,x ,e* ...)] - [(call ,info ,mdcl ,[e '() -> e] ,[e* '() -> e*] ...) - `(call ,info ,mdcl ,e ,e* ...)] - [(foreign-call ,info ,[e '() -> e] ,[e* '() -> e*] ...) - `(foreign-call ,info ,e ,e* ...)] - [(fcallable ,info) `(fcallable ,info)] - [(label ,l ,[body]) `(label ,l ,body)] - [(mvlet ,[e '() -> e] ((,x** ...) ,interface* ,[body*]) ...) - `(mvlet ,e ((,x** ...) ,interface* ,body*) ...)] - [(mvcall ,info ,[e1 '() -> e1] ,[e2 '() -> e2]) - `(mvcall ,info ,e1 ,e2)] - [(let ([,x ,[e* '() -> e*]] ...) ,[body]) - `(let ([,x ,e*] ...) ,body)] - [(case-lambda ,info ,[cl] ...) `(case-lambda ,info ,cl ...)] - [(quote ,d) `(quote ,d)] - [(if ,[e0 '() -> e0] ,[e1] ,[e2]) `(if ,e0 ,e1 ,e2)] - [(seq ,[e0 '() -> e0] ,[e1]) `(seq ,e0 ,e1)] - [(profile ,src) `(profile ,src)] - [(pariah) `(pariah)] - [,pr pr] - [else ($oops who "unexpected Expr ~s" ir)])) - - (define-pass np-name-anonymous-lambda : L4.875 (ir) -> L5 () - (CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause ()) - (Expr : Expr (ir) -> Expr () - [(case-lambda ,info ,[cl] ...) - (let ([anon (make-tmp (or (let ([name (info-lambda-name info)]) - (and name (string->symbol name))) - 'anon))]) - (uvar-info-lambda-set! anon info) - `(letrec ([,anon (case-lambda ,info ,cl ...)]) - ,anon))]) - (nanopass-case (L4.875 CaseLambdaExpr) ir - [(case-lambda ,info ,[CaseLambdaClause : cl] ...) `(case-lambda ,info ,cl ...)])) - - (define-pass np-convert-closures : L5 (x) -> L6 () - (definitions - (define-record-type clinfo - (nongenerative) - (sealed #t) - (fields lid (mutable mask) (mutable fv*)) - (protocol (lambda (n) (lambda (index) (n index 0 '()))))) - (module (with-offsets) - (define set-offsets! - (lambda (x* index) - (do ([x* x* (cdr x*)] [index index (fx+ index 1)]) - ((null? x*) index) - (var-index-set! (car x*) index)))) - (define-syntax with-offsets - (syntax-rules () - [(_ index ?x* ?e1 ?e2 ...) - (identifier? #'index) - (let ([x* ?x*]) - (let ([index (set-offsets! x* index)]) - (let ([v (begin ?e1 ?e2 ...)]) - (for-each (lambda (x) (var-index-set! x #f)) x*) - v)))]))) - (define record-ref! - (lambda (x clinfo) - (let ([index (var-index x)]) - (unless index (sorry! who "variable ~a lost its binding" x)) - (when (fx< index (clinfo-lid clinfo)) - (let ([mask (clinfo-mask clinfo)]) - (unless (bitwise-bit-set? mask index) - (clinfo-mask-set! clinfo (bitwise-copy-bit mask index 1)) - (clinfo-fv*-set! clinfo (cons x (clinfo-fv* clinfo)))))))))) - (Expr : Expr (ir index clinfo) -> Expr () - [,x (record-ref! x clinfo) x] - [(letrec ([,x* ,le*] ...) ,body) - (with-offsets index x* - (let loop ([le* le*] [rle* '()] [rfv** '()]) - (if (null? le*) - `(closures ([,x* (,(reverse rfv**) ...) ,(reverse rle*)] ...) - ,(Expr body index clinfo)) - (let-values ([(le fv*) (CaseLambdaExpr (car le*) index clinfo)]) - (loop (cdr le*) (cons le rle*) (cons fv* rfv**))))))] - [(let ([,x* ,[e*]] ...) ,body) - (with-offsets index x* - `(let ([,x* ,e*] ...) ,(Expr body index clinfo)))] - [(mvlet ,[e] ((,x** ...) ,interface* ,body*) ...) - `(mvlet ,e - ((,x** ...) - ,interface* - ,(let f ([x** x**] [body* body*]) - (if (null? x**) - '() - (cons - (with-offsets index (car x**) - (Expr (car body*) index clinfo)) - (f (cdr x**) (cdr body*)))))) - ...)] - [(loop ,x (,x* ...) ,body) - (with-offsets index (cons x x*) - `(loop ,x (,x* ...) ,(Expr body index clinfo)))]) - (CaseLambdaExpr : CaseLambdaExpr (ir index outer-clinfo) -> CaseLambdaExpr () - [(case-lambda ,info ,cl* ...) - (let ([clinfo (make-clinfo index)]) - (let ([cl* (map (lambda (cl) (CaseLambdaClause cl index clinfo)) cl*)]) - (let ([fv* (clinfo-fv* clinfo)]) - (for-each (lambda (x) (record-ref! x outer-clinfo)) fv*) - (values - `(case-lambda ,info ,cl* ...) - fv*))))]) - (CaseLambdaClause : CaseLambdaClause (ir index parent-clinfo) -> CaseLambdaClause () - [(clause (,x* ...) ,interface ,body) - (let ([clinfo (make-clinfo index)]) - (with-offsets index x* - (let ([body (Expr body index clinfo)]) - (let ([fv* (clinfo-fv* clinfo)]) - (for-each (lambda (x) (record-ref! x parent-clinfo)) fv*) - `(clause (,x* ...) ,(if (null? fv*) #f (make-cpvar)) ,interface ,body)))))]) - (let-values ([(le fv*) (CaseLambdaExpr x 0 (make-clinfo 0))]) - (unless (null? fv*) (sorry! who "found unbound variables ~s" fv*)) - le)) - - (define-pass np-optimize-direct-call : L6 (ir) -> L6 () - (definitions - (define find-matching-clause - (lambda (len info kfixed kvariable kfail) - (if info - (let f ([interface* (info-lambda-interface* info)] [dcl* (info-lambda-dcl* info)]) - (if (null? interface*) - (kfail) - (let ([interface (car interface*)]) - (if (fx< interface 0) - (let ([nfixed (fxlognot interface)]) - (if (fx>= len nfixed) - (kvariable nfixed (car dcl*)) - (f (cdr interface*) (cdr dcl*)))) - (if (fx= interface len) - (kfixed (car dcl*)) - (f (cdr interface*) (cdr dcl*))))))) - (kfail))))) - (CaseLambdaExpr1 : CaseLambdaExpr (ir) -> * () - [(case-lambda ,info ,cl* ...) - (info-lambda-well-known?-set! info #t)]) - (CaseLambdaExpr2 : CaseLambdaExpr (ir) -> CaseLambdaExpr ()) - (Expr : Expr (ir) -> Expr () - [,x (let ([info (uvar-info-lambda x)]) - (when info (info-lambda-well-known?-set! info #f)) - x)] - [(closures ([,x* (,x** ...) ,le*] ...) ,body) - (for-each CaseLambdaExpr1 le*) - `(closures ([,x* (,x** ...) ,(map CaseLambdaExpr2 le*)] ...) ,(Expr body))] - [(loop ,x (,x* ...) ,body) - (uvar-location-set! x 'loop) - (let ([body (Expr body)]) - (uvar-location-set! x #f) - `(loop ,x (,x* ...) ,body))] - [(call ,info ,mdcl ,x ,[e*] ...) - (guard (not (eq? (uvar-location x) 'loop))) - (if mdcl - (begin - ; already a direct-call produced, e.g., by recognize-mrvs - (direct-call-label-referenced-set! mdcl #t) - `(call ,info ,mdcl ,x ,e* ...)) - (find-matching-clause (length e*) (uvar-info-lambda x) - (lambda (dcl) - (direct-call-label-referenced-set! dcl #t) - `(call ,info ,dcl ,x ,e* ...)) - (lambda (nfixed dcl) - (direct-call-label-referenced-set! dcl #t) - (let ([fixed-e* (list-head e* nfixed)] [rest-e* (list-tail e* nfixed)]) - (let ([t* (map (lambda (x) (make-tmp 't)) fixed-e*)]) - ; evaluate fixed-e* first, before the rest list is created. rest-e* should - ; be evaluated before as well assuming later passes handle calls correctly - `(let ([,t* ,fixed-e*] ...) - (call ,info ,dcl ,x ,t* ... - ,(%primcall #f #f list ,rest-e* ...)))))) - (lambda () `(call ,info #f ,(Expr x) ,e* ...))))]) - (CaseLambdaExpr2 ir)) - - ; this pass doesn't change the language, but it does add an extragrammatical - ; restriction: each letrec is now strongly connected - (define-pass np-identify-scc : L6 (ir) -> L6 () - (definitions - ; returns a list of lists of strongly connected bindings sorted so that - ; if a binding in some list binding1* binds a variable x that is in the - ; free list of a binding in some other list binding2*, binding1* comes - ; before binding2*. - (define-record-type binding - (fields le x x* (mutable link*) (mutable root) (mutable done)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (le x x*) - (let ([b (new le x x* '() #f #f)]) - (uvar-location-set! x b) - b))))) - (define (compute-sccs v*) ; Tarjan's algorithm - ; adapted from cpletrec - (define scc* '()) - (define (compute-sccs v) - (define index 0) - (define stack '()) - (define (tarjan v) - (let ([v-index index]) - (binding-root-set! v v-index) - (set! stack (cons v stack)) - (set! index (fx+ index 1)) - (for-each - (lambda (v^) - (unless (binding-done v^) - (unless (binding-root v^) (tarjan v^)) - (binding-root-set! v (fxmin (binding-root v) (binding-root v^))))) - (binding-link* v)) - (when (fx= (binding-root v) v-index) - (set! scc* - (cons - (let f ([ls stack]) - (let ([v^ (car ls)]) - (binding-done-set! v^ #t) - (cons v^ (if (eq? v^ v) - (begin (set! stack (cdr ls)) '()) - (f (cdr ls)))))) - scc*))))) - (tarjan v)) - (for-each (lambda (v) (unless (binding-done v) (compute-sccs v))) v*) - (reverse scc*))) - (Expr : Expr (ir) -> Expr () - [(closures ([,x* (,x** ...) ,[le*]] ...) ,[body]) - ; create bindings and set each uvar's location to the corresponding binding - (let ([b* (map make-binding le* x* x**)]) - ; establish links from each binding to the bindings of its free variables - (for-each - (lambda (b) - (binding-link*-set! b - (fold-left - (lambda (link* x) - (let ([loc (uvar-location x)]) - (if (binding? loc) - (cons loc link*) - link*))) - '() (binding-x* b)))) - b*) - ; reset uvar locations - (for-each (lambda (b) (uvar-location-set! (binding-x b) #f)) b*) - ; sort bindings into strongly connected components, then - ; create one closure for each not-well-known binding, - ; and one for all well-known bindings - (let f ([b** (compute-sccs b*)]) - (if (null? b**) - body - (let ([b* (car b**)]) - `(closures ([,(map binding-x b*) (,(map binding-x* b*) ...) ,(map binding-le b*)] ...) - ,(f (cdr b**)))))))])) - - (module (np-expand-closures np-expand/optimize-closures) - (define sort-bindings - ; sort-bindings uses the otherwise unneeded info-lambda-seqno to put labels - ; bindings in the same order whether we run np-expand/optimize-closures or - ; just np-expand-closures, thus reducing code/icache layout differences and, - ; when there are few other differences, eliminating spurious differences - ; in run times. ultimately, we should try laying code objects out - ; in some order that minimizes cache misses, whether at compile, - ; load, or collection time. - (lambda (l* le*) - (define seqno - (lambda (p) - (let ([le (cdr p)]) - (nanopass-case (L7 CaseLambdaExpr) le - [(case-lambda ,info ,cl* ...) (info-lambda-seqno info)] - [else 0])))) - (let ([ls (sort (lambda (x y) (< (seqno x) (seqno y))) (map cons l* le*))]) - (values (map car ls) (map cdr ls))))) - - (define-pass np-expand-closures : L6 (ir) -> L7 () - (definitions - (define gl* '()) - (define gle* '()) - (define-record-type closure - (nongenerative) - (sealed #t) - (fields name label (mutable free*))) - (define-syntax with-uvar-location - (syntax-rules () - [(_ ?uvar ?expr ?e) - (let ([uvar ?uvar]) - (let ([old (uvar-location uvar)]) - (uvar-location-set! uvar ?expr) - (let ([v ?e]) - (uvar-location-set! uvar old) - v)))])) - (with-output-language (L7 Expr) - (define with-locations - (lambda (free* mcp body) - (if mcp - (let f ([free* free*] [i (constant closure-data-disp)]) - (if (null? free*) - (Expr body) - (with-uvar-location (car free*) (%mref ,mcp ,i) - (f (cdr free*) (fx+ i (constant ptr-bytes)))))) - (Expr body)))) - (module (create-bindings create-inits) - (define (build-free-ref x) (or (uvar-location x) x)) - (define create-bindings - (lambda (c* body) - (fold-right - (lambda (c body) - `(let ([,(closure-name c) ,(%constant-alloc type-closure - (fx* (fx+ (length (closure-free* c)) 1) (constant ptr-bytes)))]) - ,(%seq - (set! ,(%mref ,(closure-name c) ,(constant closure-code-disp)) - (label-ref ,(closure-label c) ,(constant code-data-disp))) - ,body))) - body - c*))) - (define create-inits - (lambda (c* body) - (fold-right - (lambda (c body) - (let f ([x* (closure-free* c)] [i (constant closure-data-disp)]) - (if (null? x*) - body - (%seq - (set! ,(%mref ,(closure-name c) ,i) ,(build-free-ref (car x*))) - ,(f (cdr x*) (fx+ i (constant ptr-bytes))))))) - body c*)))))) - (CaseLambdaExpr : CaseLambdaExpr (ir c) -> CaseLambdaExpr () - [(case-lambda ,info ,[cl*] ...) - (info-lambda-fv*-set! info (closure-free* c)) - (info-lambda-closure-rep-set! info 'closure) - `(case-lambda ,info ,cl* ...)]) - (CaseLambdaClause : CaseLambdaClause (ir c) -> CaseLambdaClause () - [(clause (,x* ...) ,mcp ,interface ,body) - `(clause (,x* ...) ,mcp ,interface - ,(with-locations (if c (closure-free* c) '()) mcp body))]) - (Expr : Expr (ir) -> Expr () - [(closures ([,x* (,x** ...) ,le*] ...) ,body) - (let* ([l* (map (lambda (x) (make-local-label (uvar-name x))) x*)] - [c* (map make-closure x* l* x**)]) - (let ([le* (map CaseLambdaExpr le* c*)] [body (Expr body)]) - (set! gl* (append l* gl*)) - (set! gle* (append le* gle*)) - (create-bindings c* (create-inits c* body))))] - [,x (or (uvar-location x) x)] - [(fcallable ,info) - (let ([label (make-local-label 'fcallable)]) - (set! gl* (cons label gl*)) - (set! gle* (cons (in-context CaseLambdaExpr `(fcallable ,info ,label)) gle*)) - `(label-ref ,label 0))]) - (nanopass-case (L6 CaseLambdaExpr) ir - [(case-lambda ,info ,[CaseLambdaClause : cl #f -> cl] ...) - (let ([l (make-local-label 'main)]) - (let-values ([(gl* gle*) (sort-bindings gl* gle*)]) - `(labels ([,gl* ,gle*] ... [,l (case-lambda ,info ,cl ...)]) ,l)))])) - - (define-pass np-expand/optimize-closures : L6 (ir) -> L7 () - (definitions - (module (add-original-closures! add-final-closures! - add-ref-counter add-create-and-alloc-counters - add-raw-counters with-raw-closure-ref-counter - with-was-closure-ref) - (include "types.ss") - (define add-create-and-alloc-counters - (lambda (c* e) - (if (track-dynamic-closure-counts) - (let f ([c* c*] [pair-count 0] [vector-count 0] [closure-count 0] - [vector-alloc-amount 0] [closure-alloc-amount 0] - [padded-vector-alloc-amount 0] [padded-closure-alloc-amount 0]) - (if (null? c*) - (add-counter '#{pair-create-count bhowt6w0coxl0s2y-5} pair-count - (add-counter '#{vector-create-count bhowt6w0coxl0s2y-6} vector-count - (add-counter '#{closure-create-count bhowt6w0coxl0s2y-7} closure-count - (add-counter '#{vector-alloc-count bhowt6w0coxl0s2y-8} vector-alloc-amount - (add-counter '#{closure-alloc-count bhowt6w0coxl0s2y-9} closure-alloc-amount - (add-counter '#{padded-vector-alloc-count bhowt6w0coxl0s2y-11} padded-vector-alloc-amount - (add-counter '#{padded-closure-alloc-count bhowt6w0coxl0s2y-10} padded-closure-alloc-amount - e))))))) - (let ([c (car c*)]) - (case (closure-type c) - [(pair) (f (cdr c*) (fx+ pair-count 1) vector-count closure-count - vector-alloc-amount closure-alloc-amount padded-vector-alloc-amount - padded-closure-alloc-amount)] - [(vector) - (let ([n (fx+ (length (closure-free* c)) 1)]) - (f (cdr c*) pair-count (fx+ vector-count 1) closure-count - (fx+ vector-alloc-amount n) closure-alloc-amount - (fx+ padded-vector-alloc-amount (fxsll (fxsra (fx+ n 1) 1) 1)) - padded-closure-alloc-amount))] - [(closure) - (let ([n (fx+ (length (closure-free* c)) 1)]) - (f (cdr c*) pair-count vector-count (fx+ closure-count 1) - vector-alloc-amount (fx+ closure-alloc-amount n) - padded-vector-alloc-amount - (fx+ padded-closure-alloc-amount (fxsll (fxsra (fx+ n 1) 1) 1))))] - [else (f (cdr c*) pair-count vector-count closure-count - vector-alloc-amount closure-alloc-amount padded-vector-alloc-amount - padded-closure-alloc-amount)])))) - e))) - (define add-counter - (lambda (counter amount e) - (with-output-language (L7 Expr) - (%seq - ,(%inline inc-profile-counter - ,(%mref - (literal ,(make-info-literal #t 'object counter (constant symbol-value-disp))) - ,(constant record-data-disp)) - (quote ,amount)) - ,e)))) - (define add-ref-counter - (lambda (e) - (if (track-dynamic-closure-counts) - (add-counter '#{ref-count bhowt6w0coxl0s2y-4} 1 e) - e))) - (define-syntax with-raw-closure-ref-counter - (syntax-rules () - [(_ ?x ?e1 ?e2 ...) - (let ([expr (begin ?e1 ?e2 ...)]) - (if (and (track-dynamic-closure-counts) (uvar-was-closure-ref? ?x)) - (add-counter '#{raw-ref-count bhowt6w0coxl0s2y-1} 1 expr) - expr))])) - (define add-raw-counters - (lambda (free** e) - (if (track-dynamic-closure-counts) - (let f ([x** free**] [alloc 0] [raw 0]) - (if (null? x**) - (add-counter '#{raw-create-count bhowt6w0coxl0s2y-2} (length free**) - (add-counter '#{raw-alloc-count bhowt6w0coxl0s2y-3} alloc - (add-counter '#{raw-ref-count bhowt6w0coxl0s2y-1} raw e))) - (let ([x* (car x**)]) - (f (cdr x**) (fx+ alloc (length x*) 1) - (fold-left - (lambda (cnt x) (if (uvar-was-closure-ref? x) (fx+ cnt 1) cnt)) - raw x*))))) - e))) - (define-syntax with-was-closure-ref - (syntax-rules () - [(_ ?x* ?e1 ?e2 ...) - (let f ([x* ?x*]) - (if (or (null? x*) (not (track-dynamic-closure-counts))) - (begin ?e1 ?e2 ...) - (let ([x (car x*)]) - (let ([old-was-cr? (uvar-was-closure-ref? x)]) - (uvar-was-closure-ref! x #t) - (let ([expr (f (cdr x*))]) - (uvar-was-closure-ref! x old-was-cr?) - expr)))))])) - (define add-original-closures! - (lambda (free**) - (cond - [(track-static-closure-counts) => - (lambda (ci) - (static-closure-info-raw-closure-count-set! ci - (fold-left (lambda (count free*) - (static-closure-info-raw-free-var-count-set! ci - (+ (static-closure-info-raw-free-var-count ci) - (length free*))) - (+ count 1)) - (static-closure-info-raw-closure-count ci) free**)))]))) - (define add-final-closures! - (lambda (c*) - (cond - [(track-static-closure-counts) => - (lambda (ci) - (for-each - (lambda (c) - (let ([type (closure-type c)]) - (if (closure-wk? c) - (case type - [(constant) - (static-closure-info-wk-empty-count-set! ci - (+ (static-closure-info-wk-empty-count ci) 1))] - [(singleton) - (static-closure-info-wk-single-count-set! ci - (+ (static-closure-info-wk-single-count ci) 1))] - [(pair) - (static-closure-info-wk-pair-count-set! ci - (+ (static-closure-info-wk-pair-count ci) 1))] - [(vector) - (static-closure-info-wk-vector-count-set! ci - (+ (static-closure-info-wk-vector-count ci) 1)) - (static-closure-info-wk-vector-free-var-count-set! ci - (+ (static-closure-info-wk-vector-free-var-count ci) - (length (closure-free* c))))] - [(borrowed) - (static-closure-info-wk-borrowed-count-set! ci - (+ (static-closure-info-wk-borrowed-count ci) 1))] - [(closure) - (static-closure-info-nwk-closure-count-set! ci - (+ (static-closure-info-nwk-closure-count ci) 1)) - (static-closure-info-nwk-closure-free-var-count-set! ci - (+ (static-closure-info-nwk-closure-free-var-count ci) - (length (closure-free* c))))] - [else (sorry! who "unexpected well-known closure type ~s" type)]) - (case type - [(constant) - (static-closure-info-nwk-empty-count-set! ci - (+ (static-closure-info-nwk-empty-count ci) 1))] - [(closure) - (static-closure-info-nwk-closure-count-set! ci - (+ (static-closure-info-nwk-closure-count ci) 1)) - (static-closure-info-nwk-closure-free-var-count-set! ci - (+ (static-closure-info-nwk-closure-free-var-count ci) - (length (closure-free* c))))] - [else (sorry! who "unexpected non-well-known closure type ~s" type)])))) - c*))])))) - (define gl* '()) - (define gle* '()) - (define-record-type binding - (fields l x x*) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (l x x*) - (new l x x*))))) - (define binding-well-known? - (lambda (b) - (info-lambda-well-known? - (uvar-info-lambda - (binding-x b))))) - (define-record-type frob - (fields name (mutable expr) (mutable seen frob-seen? frob-seen!)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (case-lambda - [(name expr) (new name expr #f)] - [(name expr seen) (new name expr seen)])))) - (define-record-type closure - (nongenerative) - (sealed #t) - (fields wk? name label b* - (mutable sibling*) (mutable free*) (mutable type) - (mutable seen closure-seen? closure-seen!) - (mutable borrowed-name)) - (protocol - (lambda (new) - (lambda (wk? b*) - ; must use name and label of first binding - (let ([b (car b*)]) - (let ([c (new wk? (binding-x b) (binding-l b) b* '() '() #f #f #f)]) - (for-each - (lambda (b) (uvar-location-set! (binding-x b) c)) - b*) - c)))))) - (module (make-bank deposit retain borrow) - ; NB: borrowing is probably cubic at present - ; might should represent bank as a prefix tree - (define sort-free - (lambda (free*) - (sort (lambda (x y) (fx< (var-index x) (var-index y))) free*))) - (define make-bank (lambda () '())) - (define deposit - ; NB: if used when self-references are possible, remove (olosure-name c) from free* - (lambda (free* c bank) - (cons (cons (sort-free free*) c) - (cons (cons (sort-free (cons (closure-name c) free*)) c) - bank)))) - (define retain - (lambda (name* bank) - (filter (lambda (a) (memq (closure-name (cdr a)) name*)) bank))) - (define borrow - ; NB: if used when self-references are possible, remove (olosure-name c) from free* - (lambda (free* bank) - (let ([free* (sort-free free*)]) - (cond - [(assoc free* bank) => cdr] - [else #f]))))) - (module (with-offsets) - (define set-offsets! - (lambda (x* index) - (do ([x* x* (cdr x*)] [index index (fx+ index 1)]) - ((null? x*) index) - (var-index-set! (car x*) index)))) - (define-syntax with-offsets - (syntax-rules () - [(_ index ?x* ?e1 ?e2 ...) - (identifier? #'index) - (let ([x* ?x*]) - (let ([index (set-offsets! x* index)]) - (let ([v (begin ?e1 ?e2 ...)]) - (for-each (lambda (x) (var-index-set! x #f)) x*) - v)))]))) - (with-output-language (L7 Expr) - (module (create-bindings create-inits) - (define (build-free-ref x) - (let ([loc (uvar-location x)]) - (when (eq? loc 'loop) - (sorry! who "found reference to loop variable outside call position" x)) - (frob-expr loc))) - (define create-bindings - (lambda (c* body) - (fold-right - (lambda (c body) - (case (closure-type c) - ; NB: the pair and vector cases can be done this way only if well-known - ; NB: closures can be shared with each other and up to one non-well-known closure - [(pair) - `(let ([,(closure-name c) ,(%primcall #f #f cons ,(map build-free-ref (closure-free* c)) ...)]) - ,body)] - [(vector) - `(let ([,(closure-name c) ,(%primcall #f #f vector ,(map build-free-ref (closure-free* c)) ...)]) - ,body)] - [else - (safe-assert (eq? (closure-type c) 'closure)) - `(let ([,(closure-name c) ,(%constant-alloc type-closure - (fx* (fx+ (length (closure-free* c)) 1) (constant ptr-bytes)))]) - ,(%seq - (set! ,(%mref ,(closure-name c) ,(constant closure-code-disp)) - (label-ref ,(closure-label c) ,(constant code-data-disp))) - ,body))])) - (add-create-and-alloc-counters c* body) - c*))) - (define create-inits - (lambda (c* body) - (fold-right - (lambda (c body) - (case (closure-type c) - [(closure) - (let f ([x* (closure-free* c)] [i (constant closure-data-disp)]) - (if (null? x*) - body - (%seq - (set! ,(%mref ,(closure-name c) ,i) ,(build-free-ref (car x*))) - ,(f (cdr x*) (fx+ i (constant ptr-bytes))))))] - [else body])) - body c*)))) - (define-syntax with-frob-location - (syntax-rules () - [(_ ?x ?expr ?e) - (let ([frob (uvar-location ?x)]) - (let ([loc (frob-expr frob)]) - (frob-expr-set! frob ?expr) - (let ([v ?e]) - (frob-expr-set! frob loc) - v)))])) - (define with-locations - (lambda (type free* mcp body index bank) - (case type - [(singleton) (with-frob-location (car free*) mcp (Expr body index bank))] - [(pair) - (with-frob-location (car free*) (add-ref-counter (%mref ,mcp ,(constant pair-car-disp))) - (with-frob-location (cadr free*) (add-ref-counter (%mref ,mcp ,(constant pair-cdr-disp))) - (Expr body index bank)))] - [else - (safe-assert (memq type '(vector closure))) - (let f ([free* free*] [i (if (eq? type 'vector) (constant vector-data-disp) (constant closure-data-disp))]) - (if (null? free*) - (Expr body index bank) - (with-frob-location (car free*) (add-ref-counter (%mref ,mcp ,i)) - (f (cdr free*) (fx+ i (constant ptr-bytes))))))]))))) - (CaseLambdaExpr : CaseLambdaExpr (ir index c bank) -> CaseLambdaExpr () - [(case-lambda ,info ,cl* ...) - (info-lambda-fv*-set! info (closure-free* c)) - (info-lambda-closure-rep-set! info (closure-type c)) - `(case-lambda ,info - ,(let ([bank (retain (closure-free* c) bank)]) - (map (lambda (cl) (CaseLambdaClause cl index c bank)) cl*)) - ...)]) - (CaseLambdaClause : CaseLambdaClause (ir index c bank) -> CaseLambdaClause () - [(clause (,x* ...) ,mcp ,interface ,body) - (with-offsets index x* - (let ([type (if (and c mcp) (closure-type c) 'constant)]) - (if (eq? type 'constant) - `(clause (,x* ...) #f ,interface ,(Expr body index bank)) - `(clause (,x* ...) ,mcp ,interface - ,(with-frob-location (closure-name c) mcp - (if (eq? type 'borrowed) - (with-frob-location (closure-borrowed-name c) mcp - (let ([free* (closure-free* c)]) - (with-locations (if (fx= (length free*) 2) 'pair 'vector) free* mcp body index bank))) - (with-locations type (closure-free* c) mcp body index bank)))))))]) - (Expr : Expr (ir index bank) -> Expr () - [(closures ([,x* (,x** ...) ,le*] ...) ,body) - (with-offsets index x* - (safe-assert (andmap var-index x*)) ; should be bound now - (safe-assert (andmap (lambda (x*) (andmap var-index x*)) x**)) ; should either have already been bound, or are bound now - (add-original-closures! x**) - (let* ([x**-loc (map (lambda (x*) (map uvar-location x*)) x**)] - [l* (map (lambda (x) (make-local-label (uvar-name x))) x*)] - ; create one closure for each not-well-known binding, and one for all well-known bindings - [c* (let-values ([(wk* !wk*) (partition binding-well-known? (map make-binding l* x* x**))]) - (cond - [(null? wk*) (map (lambda (b) (make-closure #f (list b))) !wk*)] - [(null? !wk*) (list (make-closure #t wk*))] - [else - ; putting one !wk* in with wk*. claim: if any of the closures is nonempty, - ; all will be nonempty, so might as well allow wk* to share a !wk's closure. - ; if all are empty, no harm done. - ; TODO: there might be a more suitable !wk to pick than (car !wk*) - (cons - (make-closure #f (cons (car !wk*) wk*)) - (map (lambda (b) (make-closure #f (list b))) (cdr !wk*)))]))] - [xc* (map uvar-location x*)]) - - ; set up sibling* and initial free* - (for-each - (lambda (c) - (let fb ([b* (closure-b* c)] [free* '()] [sibling* '()]) - (if (null? b*) - (begin - (closure-free*-set! c free*) - (closure-sibling*-set! c sibling*)) - (let fx ([x* (binding-x* (car b*))] [free* free*] [sibling* sibling*]) - (if (null? x*) - (fb (cdr b*) free* sibling*) - (let* ([x (car x*)] [loc (uvar-location x)]) - (cond - [(not loc) - (let ([frob (make-frob x x #t)]) - (uvar-location-set! x frob) - (fx (cdr x*) (cons x free*) sibling*) - (frob-seen! frob #f))] - [(frob? loc) - (if (or (frob-seen? loc) (not (frob-name loc))) - (fx (cdr x*) free* sibling*) - (begin - (frob-seen! loc #t) - (fx (cdr x*) (cons (frob-name loc) free*) sibling*) - (frob-seen! loc #f)))] - [(closure? loc) - (if (or (eq? loc c) (closure-seen? loc)) ; no reflexive links - (fx (cdr x*) free* sibling*) - (begin - (closure-seen! loc #t) - (fx (cdr x*) free* (cons (closure-name loc) sibling*)) - (closure-seen! loc #f)))] - [else (sorry! who "unexpected uvar location ~s" loc)]))))))) - c*) - - ; find closures w/free variables (non-constant closures) and propagate - (when (ormap (lambda (c) (not (null? (closure-free* c)))) c*) - (for-each - (lambda (c) - (closure-free*-set! c (append (closure-sibling* c) (closure-free* c)))) - c*)) - - ; determine each closure's representation & set uvar location frobs - (for-each - (lambda (c) - (let ([free* (closure-free* c)]) - (let ([frob (cond - [(null? free*) - (closure-type-set! c 'constant) - (make-frob #f `(literal ,(make-info-literal #f 'closure (closure-label c) 0)))] - [(closure-wk? c) - (cond - [(fx= (length free*) 1) - (closure-type-set! c 'singleton) - (uvar-location (car free*))] - [(borrow free* bank) => - (lambda (mc) - (closure-type-set! c 'borrowed) - (closure-borrowed-name-set! c (closure-name mc)) - (closure-free*-set! c (closure-free* mc)) - (uvar-location (closure-name mc)))] - [else - ; NB: HACK - (set! bank (deposit free* c bank)) - (closure-type-set! c (if (fx= (length free*) 2) 'pair 'vector)) - (make-frob (closure-name c) (closure-name c))])] - [else - (closure-type-set! c 'closure) - (make-frob (closure-name c) (closure-name c))])]) - (for-each - (lambda (b) (uvar-location-set! (binding-x b) frob)) - (closure-b* c))))) - c*) - - ; NB: if we are not sharing, but we are borrowing, we need to ensure - ; NB: all closure variables point to final frob, and not a closure record - - ; record static closure counts - (add-final-closures! c*) - - ; process subforms and rebuild - (fold-left (lambda (body le) - (nanopass-case (L6 CaseLambdaExpr) le - [(case-lambda ,info ,cl ...) body])) - (let ([le* (map (lambda (le xc x*) (with-was-closure-ref x* (CaseLambdaExpr le index xc bank))) - le* xc* x**)] - [body (Expr body index bank)]) - (set! gl* (append l* gl*)) - (set! gle* (append le* gle*)) - (let ([c* (filter (lambda (c) (memq (closure-type c) '(pair closure vector))) c*)]) - (let ([body (create-bindings c* (create-inits c* (add-raw-counters x** body)))]) - ; leave location clean for later passes - (for-each (lambda (x) (uvar-location-set! x #f)) x*) - (for-each (lambda (x* x*-loc) (for-each uvar-location-set! x* x*-loc)) x** x**-loc) - body))) - le*)))] - [,x (with-raw-closure-ref-counter x (cond [(uvar-location x) => frob-expr] [else x]))] - [(loop ,x (,x* ...) ,body) - (uvar-location-set! x 'loop) - (let ([body (with-offsets index x* (Expr body index bank))]) - (uvar-location-set! x #f) - `(loop ,x (,x* ...) ,body))] - [(call ,info ,mdcl ,x ,[e*] ...) - (guard (eq? (uvar-location x) 'loop)) - `(call ,info ,mdcl ,x ,e* ...)] - [(call ,info ,mdcl ,x ,[e*] ...) - (guard mdcl) - (with-raw-closure-ref-counter x - (cond - [(uvar-location x) => - (lambda (frob) - (if (frob-name frob) - `(call ,info ,mdcl ,(frob-expr frob) ,e* ...) - `(call ,info ,mdcl #f ,e* ...)))] - [else `(call ,info ,mdcl ,x ,e* ...)]))] - [(fcallable ,info) - (let ([label (make-local-label 'fcallable)]) - (set! gl* (cons label gl*)) - (set! gle* (cons (in-context CaseLambdaExpr `(fcallable ,info ,label)) gle*)) - `(label-ref ,label 0))] - [(let ([,x* ,[e*]] ...) ,body) - (with-offsets index x* - `(let ([,x* ,e*] ...) ,(Expr body index bank)))] - [(mvlet ,[e] ((,x** ...) ,interface* ,body*) ...) - (let f ([var** x**] [body* body*] [rbody* '()]) - (if (null? var**) - `(mvlet ,e ((,x** ...) ,interface* ,(reverse rbody*)) ...) - (f (cdr var**) (cdr body*) (cons (with-offsets index (car var**) (Expr (car body*) index bank)) rbody*))))]) - (nanopass-case (L6 CaseLambdaExpr) ir - [(case-lambda ,info ,[CaseLambdaClause : cl 0 #f (make-bank) -> cl] ...) - (let ([l (make-local-label 'main)]) - (let-values ([(gl* gle*) (sort-bindings gl* gle*)]) - `(labels ([,gl* ,gle*] ... [,l (case-lambda ,info ,cl ...)]) ,l)))]))) - - (define-pass np-simplify-if : L7 (ir) -> L7 () - (definitions - (define-$type-check (L7 Expr)) - (with-output-language (L7 Expr) - ; (and (fixnum? x1) ... (fixnum xn) e ...) => (and (fixnum? (logor x1 ... xn)) e ...) - ; restricting fixnum? arguments to vars to avoid unnecessary computation - (define process-fixnum? - (lambda (info1 pr1 e x*) - (define build-fixnum? - (lambda (x*) - `(call ,info1 #f ,pr1 - ,(if (fx= (length x*) 1) - (car x*) - (%primcall #f #f fxlogor ,x* ...))))) - (let f ([e e] [x* x*]) - (nanopass-case (L7 Expr) e - [(if (call ,info1 ,mdcl ,pr1 ,x1) ,e2 (quote ,d)) - (guard (eq? mdcl #f) (eq? (primref-name pr1) 'fixnum?) (eq? d #f)) - (f e2 (cons x1 x*))] - [(call ,info1 ,mdcl ,pr1 ,x1) - (guard (eq? mdcl #f) (eq? (primref-name pr1) 'fixnum?)) - (build-fixnum? (cons x1 x*))] - [else `(if ,(build-fixnum? x*) ,(Expr e) (quote #f))])))) - (define process-paired-predicate - (lambda (info1 pr1 pr2 x-arg) - (let ([pr1 (primref-name pr1)] [pr2 (primref-name pr2)]) - (cond - [(and (eq? pr1 'integer?) (eq? pr2 'exact?)) - `(if ,(%primcall #f #f fixnum? ,x-arg) (quote #t) ,(%primcall #f #f bignum? ,x-arg))] - [(and (eq? pr1 'port?) (eq? pr2 'binary-port?)) - (%typed-object-check mask-binary-port type-binary-port ,x-arg)] - [(and (eq? pr1 'port?) (eq? pr2 'textual-port?)) - (%typed-object-check mask-textual-port type-textual-port ,x-arg)] - [(and (eq? pr1 'input-port?) (eq? pr2 'binary-port?)) - (%typed-object-check mask-binary-input-port type-binary-input-port ,x-arg)] - [(and (eq? pr1 'input-port?) (eq? pr2 'textual-port?)) - (%typed-object-check mask-textual-input-port type-textual-input-port ,x-arg)] - [(and (eq? pr1 'output-port?) (eq? pr2 'binary-port?)) - (%typed-object-check mask-binary-output-port type-binary-output-port ,x-arg)] - [(and (eq? pr1 'output-port?) (eq? pr2 'textual-port?)) - (%typed-object-check mask-textual-output-port type-textual-output-port ,x-arg)] - [else #f])))))) - (Expr : Expr (ir) -> Expr () - [(if (call ,info1 ,mdcl ,pr1 ,x1) ,e2 (quote ,d)) - (guard (eq? d #f) (eq? mdcl #f)) - (if (eq? (primref-name pr1) 'fixnum?) - (process-fixnum? info1 pr1 e2 (list x1)) - (or (and (nanopass-case (L7 Expr) e2 - [(if (call ,info5 ,mdcl5 ,pr2 ,x2) ,e2 (quote ,d)) - (guard (eq? x2 x1) (eq? mdcl5 #f) (eq? d #f)) - (let ([e-paired-pred (process-paired-predicate info1 pr1 pr2 x1)]) - (and e-paired-pred `(if ,e-paired-pred ,(Expr e2) (quote #f))))] - [(call ,info4 ,mdcl4 ,pr2 ,x2) - (guard (eq? x2 x1) (eq? mdcl4 #f)) - (process-paired-predicate info1 pr1 pr2 x1)] - [else #f])) - `(if (call ,info1 ,mdcl ,pr1 ,x1) ,(Expr e2) (quote ,d))))])) - - (module (np-profile-unroll-loops) - (define-syntax mvmap - (lambda (x) - (syntax-case x () - [(_ ?n ?proc ?ls1 ?ls2 ...) - (let ([n (datum ?n)]) - (unless (and (fixnum? n) (fx>= n 0)) (syntax-error #'?n "invalid return-value count")) - (let ([foo* (make-list n)]) - (with-syntax ([(ls2 ...) (generate-temporaries #'(?ls2 ...))] - [(out ...) (generate-temporaries foo*)] - [(out* ...) (generate-temporaries foo*)]) - #'(let ([proc ?proc]) - (let f ([ls1 ?ls1] [ls2 ?ls2] ...) - (if (null? ls1) - (let ([out '()] ...) (values out ...)) - (let-values ([(out ...) (proc (car ls1) (car ls2) ...)] - [(out* ...) (f (cdr ls1) (cdr ls2) ...)]) - (values (cons out out*) ...))))))))]))) - (define-who loop-unroll-limit - ($make-thread-parameter - 0 ; NB: disabling loop unrolling for now - (lambda (x) - (cond - [(fixnum? x) x] - [else ($oops who "~s is not a fixnum" x)])))) - (define PATH-SIZE-LIMIT 100) - ;; NB: this comment is no longer accurate - ;; Code growth computation is a little restrictive since it's measured - ;; per loop... but maybe since new-size is weighted when profiling is - ;; enabled it's fine. - #;(define CODE-GROWTH-FACTOR (fx1+ (loop-unroll-limit))) - (define-syntax delay - (syntax-rules () - [(_ x) (lambda () x)])) - (define (force x) (if (procedure? x) (x) x)) - (define-who analyze-loops ;; -> (lambda () body) size new-weighted-size - (lambda (body path-size unroll-count) - (with-output-language (L7 Expr) - ;; Not really a loop, just didn't want to pass around path-size and unroll-count when unnecessary - (let loop ([body body]) - (if (not body) - (values #f 0 0) - (nanopass-case (L7 Expr) body - [(literal ,info) (values body 0 0)] - [(immediate ,imm) (values body 0 0)] - [(quote ,d) (values body 0 0)] - [(goto ,l) (values body 1 1)] - [(mref ,[loop : e1 -> e1-promise e1-size e1-new-size] ,[loop : e2 -> e2-promise e2-size e2-new-size] ,imm) - (values (delay `(mref ,(force e1-promise) ,(force e2-promise) ,imm)) - (fx+ e1-size e2-size 1) - (fx+ e1-new-size e2-new-size 1))] - [,lvalue (values body 1 1)] - [(profile ,src) (values body 0 0)] - [(pariah) (values body 0 0)] - [(label-ref ,l ,offset) (values body 0 0)] - [,pr (values body 1 1)] - [(inline ,info ,prim ,[loop : e* -> e*-promise size* new-size*] ...) - (values (delay `(inline ,info ,prim ,(map force e*-promise) ...)) - (apply fx+ size*) - (apply fx+ new-size*))] - [(values ,info ,[loop : e* -> e*-promise size* new-size*] ...) - (values (delay `(values ,info ,(map force e*-promise) ...)) - (apply fx+ size*) - (apply fx+ new-size*))] - [(call ,info ,mdcl ,x ,[loop : e* -> e*-promise size* new-size*] ...) - (guard (uvar-location x)) - ;; NB: Magic formulas, using number assuming query-count \in [0,1000] - (let* ([src (info-call-src info)] - [query-count (if src (profile-query-weight src) #f)] - ;; don't bother with unimportant loops (less than 1% count relative to max) - [query-count (if (or (not query-count) (< query-count .1)) 0 (exact (truncate (* query-count 1000))))] - ;; allow path-size to increase up to 300 - [adjusted-path-size-limit (fx+ PATH-SIZE-LIMIT (fx/ (or query-count 0) 5))] - ;; allow unroll limit to increase up to 4 - [adjusted-unroll-limit (fx+ (loop-unroll-limit) (fx/ (or query-count 0) 300))]) - (if (or (fxzero? query-count) - (fxzero? (fx+ unroll-count adjusted-unroll-limit)) - (fx> path-size adjusted-path-size-limit)) - (begin - (values (delay `(call ,info ,mdcl ,x ,(map force e*-promise) ...)) - (fx1+ (apply fx+ size*)) - (fx1+ (apply fx+ new-size*)))) - (let*-values ([(var*) (car (uvar-location x))] - [(loop-body-promise body-size new-size) (analyze-loops (cdr (uvar-location x)) (fx1+ path-size) (fx1- unroll-count))] - [(new-size) ((lambda (x) (if query-count (fx/ x query-count) x)) (fx+ (length e*-promise) new-size))] - [(acceptable-new-size) (fx* (fx1+ adjusted-unroll-limit) body-size)]) - ;; NB: trying code growth computation here, where it could be per call site. - (values - (if (<= new-size acceptable-new-size) - (delay (fold-left - (lambda (body var e-promise) - `(seq (set! ,var ,(force e-promise)) ,body)) - (rename-loop-body (force loop-body-promise)) - var* e*-promise)) - body) - (fx1+ (apply fx+ size*)) - ;; pretend the new size is smaller for important loops - new-size))))] - [(call ,info ,mdcl ,pr ,e* ...) - (let-values ([(e*-promise size* new-size*) (mvmap 3 (lambda (e) (analyze-loops e (fx1+ path-size) unroll-count)) e*)]) - (values (delay `(call ,info ,mdcl ,pr ,(map force e*-promise) ...)) - (fx+ 2 (apply fx+ size*)) - (fx+ 2 (apply fx+ new-size*))))] - [(call ,info ,mdcl ,e ,e* ...) - (let-values ([(e-promise e-size e-new-size) (loop e)] - [(e*-promise size* new-size*) (mvmap 3 (lambda (e) (analyze-loops e (fx1+ path-size) unroll-count)) e*)]) - (values (delay `(call ,info ,mdcl ,(force e-promise) ,(map force e*-promise) ...)) - (fx+ 5 e-size (apply fx+ size*)) - (fx+ 5 e-new-size (apply fx+ new-size*))))] - [(foreign-call ,info ,[loop : e -> e-promise e-size e-new-size] ,[loop : e* -> e*-promise size* new-size*] ...) - (values (delay `(foreign-call ,info ,(force e-promise) ,(map force e*-promise) ...)) - (fx+ 5 e-size (apply fx+ size*)) - (fx+ 5 e-new-size (apply fx+ new-size*)))] - [(label ,l ,[loop : body -> e size new-size]) - (values (delay `(label ,l ,(force e))) size new-size)] - [(mvlet ,[loop : e -> e-promise e-size e-new-size] ((,x** ...) ,interface* ,body*) ...) - (let-values ([(body*-promise body*-size body*-new-size) (mvmap 3 (lambda (e) (analyze-loops e (fx+ e-size path-size) unroll-count)) body*)]) - (values (delay `(mvlet ,(force e-promise) ((,x** ...) ,interface* ,(map force body*-promise)) ...)) - (fx+ e-size (apply fx+ body*-size)) - (fx+ e-new-size (apply fx+ body*-new-size))))] - [(mvcall ,info ,e1 ,e2) - (let-values ([(e1-promise e1-size e1-new-size) (analyze-loops e1 (fx+ 5 e1) unroll-count)] - [(e2-promise e2-size e2-new-size) (analyze-loops e2 (fx+ 5 e2) unroll-count)]) - (values (delay `(mvcall ,info ,(force e1-promise) ,(force e2-promise))) - (fx+ 5 e1-size e2-size) - (fx+ 5 e1-new-size e2-new-size)))] - [(let ([,x* ,[loop : e* -> e*-promise size* new-size*]] ...) ,body) - (let-values ([(body-promise body-size body-new-size) (analyze-loops body (fx+ path-size (apply fx+ size*)) unroll-count)]) - (values (delay `(let ([,x* ,(map force e*-promise)] ...) ,(force body-promise))) - (fx+ 1 body-size (apply fx+ size*)) - (fx+ 1 body-new-size (apply fx+ new-size*))))] - [(if ,[loop : e0 -> e0-promise e0-size e0-new-size] ,e1 ,e2) - (let-values ([(e1-promise e1-size e1-new-size) (analyze-loops e1 (fx+ path-size e0-size) unroll-count)] - [(e2-promise e2-size e2-new-size) (analyze-loops e2 (fx+ path-size e0-size) unroll-count)]) - (values (delay `(if ,(force e0-promise) ,(force e1-promise) ,(force e2-promise))) - (fx+ e0-size e1-size e2-size) - (fx+ e0-new-size e1-new-size e2-new-size)))] - [(seq ,[loop : e0 -> e0-promise e0-size e0-new-size] ,e1) - (let-values ([(e1-promise e1-size e1-new-size) (analyze-loops e1 (fx+ path-size e0-size) unroll-count)]) - (values (delay `(seq ,(force e0-promise) ,(force e1-promise))) - (fx+ e0-size e1-size) - (fx+ e0-new-size e1-new-size)))] - [(set! ,lvalue ,[loop : e -> e-promise e-size e-new-size]) - (values (delay `(set! ,lvalue ,(force e-promise))) - (fx+ 1 e-size) - (fx+ 1 e-new-size))] - [(alloc ,info ,[loop : e -> e-promise e-size e-new-size]) - (values (delay `(alloc ,info ,(force e-promise))) - (fx+ 1 e-size) - (fx+ 1 e-new-size))] - [(loop ,x (,x* ...) ,[loop : body -> body-promise body-size body-new-size]) - ;; NB: Handling of inner loops? - (values (delay `(loop ,x (,x* ...) ,(force body-promise))) - body-size - body-new-size)] - [else ($oops who "forgot a case: ~a" body)])))))) - - (define-pass rename-loop-body : (L7 Expr) (ir) -> (L7 Expr) () - (definitions - (define-syntax with-fresh - (syntax-rules () - [(_ rename-ht x* body) - (let* ([x* x*] - [rename-ht (hashtable-copy rename-ht #t)] - [x* (let ([t* (map (lambda (x) (make-tmp (uvar-name x))) x*)]) - (for-each (lambda (x t) (eq-hashtable-set! rename-ht x t)) x* t*) - t*)]) - body)]))) - (Lvalue : Lvalue (ir rename-ht) -> Lvalue () - [,x (eq-hashtable-ref rename-ht x x)] - [(mref ,[e1] ,[e2] ,imm) `(mref ,e1 ,e2 ,imm)]) - (Expr : Expr (ir rename-ht) -> Expr () - [(loop ,x (,[Lvalue : x* rename-ht -> x*] ...) ,body) - ;; NB: with-fresh is so well designed that it can't handle this case - (let*-values ([(x) (list x)] - [(x body) (with-fresh rename-ht x (values (car x) (Expr body rename-ht)))]) - `(loop ,x (,x* ...) ,body))] - [(let ([,x* ,[e*]] ...) ,body) - (with-fresh rename-ht x* - `(let ([,x* ,e*] ...) ,(Expr body rename-ht)))] - [(mvlet ,[e] ((,x** ...) ,interface* ,body*) ...) - (let* ([x**/body* (map (lambda (x* body) - (with-fresh rename-ht x* (cons x* (Expr body rename-ht)))) - x** body*)] - [x** (map car x**/body*)] - [body* (map cdr x**/body*)]) - `(mvlet ,e ((,x** ...) ,interface* ,body*) ...))]) - (Expr ir (make-eq-hashtable))) - - (define-pass np-profile-unroll-loops : L7 (ir) -> L7 () - (Expr : Expr (ir) -> Expr () - [(loop ,x (,x* ...) ,body) - (uvar-location-set! x (cons x* body)) - (let-values ([(e-promise size new-size) (analyze-loops body 0 (loop-unroll-limit))]) - (uvar-location-set! x #f) - ;; NB: Not fx - `(loop ,x (,x* ...) ,(force e-promise)) - ;; trying out code-growth computation higher up - #;(if (<= new-size (* size CODE-GROWTH-FACTOR)) - (begin - #;(printf "Opt: ~a\n" x) - `(loop ,x (,x* ...) ,(force e-promise))) - (begin - #;(printf "New size: ~a, old size: ~a\n" new-size size) - ir)))])) - (set! $loop-unroll-limit loop-unroll-limit)) - - (define target-fixnum? - (if (and (= (constant most-negative-fixnum) (most-negative-fixnum)) - (= (constant most-positive-fixnum) (most-positive-fixnum))) - fixnum? - (lambda (x) - (and (or (fixnum? x) (bignum? x)) - (<= (constant most-negative-fixnum) x (constant most-positive-fixnum)))))) - - (define unfix - (lambda (imm) - (ash imm (fx- (constant fixnum-offset))))) - - (define fix - (lambda (imm) - (ash imm (constant fixnum-offset)))) - - (define ptr->imm - (lambda (x) - (cond - [(eq? x #f) (constant sfalse)] - [(eq? x #t) (constant strue)] - [(eq? x (void)) (constant svoid)] - [(null? x) (constant snil)] - [(eof-object? x) (constant seof)] - [($unbound-object? x) (constant sunbound)] - [(bwp-object? x) (constant sbwp)] - [(target-fixnum? x) (fix x)] - [(char? x) (+ (* (constant char-factor) (char->integer x)) (constant type-char))] - [else #f]))) - - (define-syntax ref-reg - (lambda (x) - (syntax-case x () - [(k reg) - (identifier? #'reg) - (if (real-register? (datum reg)) - #'reg - (with-implicit (k %mref) #`(%mref ,%tc ,(tc-disp reg))))]))) - - ; TODO: recognize a direct call when it is at the end of a sequence, closures, or let form - ; TODO: push call into if? (would need to pull arguments into temporaries to ensure order of evaluation - ; TODO: how does this interact with mvcall? - (module (np-expand-primitives) - (define-threaded new-l*) - (define-threaded new-le*) - (define ht2 (make-hashtable symbol-hash eq?)) - (define ht3 (make-hashtable symbol-hash eq?)) - (define handle-prim - (lambda (src sexpr level name e*) - (let ([handler (or (and (fx= level 3) (symbol-hashtable-ref ht3 name #f)) - (symbol-hashtable-ref ht2 name #f))]) - (and handler (handler src sexpr e*))))) - (define-syntax Symref - (lambda (x) - (syntax-case x () - [(k ?sym) - (with-implicit (k quasiquote) - #'`(literal ,(make-info-literal #t 'object ?sym (constant symbol-value-disp))))]))) - (define-pass np-expand-primitives : L7 (ir) -> L9 () - (Program : Program (ir) -> Program () - [(labels ([,l* ,le*] ...) ,l) - (fluid-let ([new-l* '()] [new-le* '()]) - (let ([le* (map CaseLambdaExpr le*)]) - `(labels ([,l* ,le*] ... [,new-l* ,new-le*] ...) ,l)))]) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr ()) - (CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause ()) - (Expr : Expr (ir) -> Expr () - [(quote ,d) - (cond - [(ptr->imm d) => (lambda (i) `(immediate ,i))] - [else `(literal ,(make-info-literal #f 'object d 0))])] - [,pr (Symref (primref-name pr))] - [(call ,info0 ,mdcl0 - (call ,info1 ,mdcl1 ,pr (quote ,d)) - ,[e*] ...) - (guard (and (eq? (primref-name pr) '$top-level-value) (symbol? d))) - `(call ,info0 ,mdcl0 ,(Symref d) ,e* ...)] - [(call ,info ,mdcl ,pr ,e* ...) - (cond - [(handle-prim (info-call-src info) (info-call-sexpr info) (primref-level pr) (primref-name pr) e*) => Expr] - [else - (let ([e* (map Expr e*)]) - ; NB: expand calls through symbol top-level values similarly - (let ([info (if (any-set? (prim-mask abort-op) (primref-flags pr)) - (make-info-call (info-call-src info) (info-call-sexpr info) (info-call-check? info) #t #t) - info)]) - `(call ,info ,mdcl ,(Symref (primref-name pr)) ,e* ...)))])])) - (define-who unhandled-arity - (lambda (name args) - (sorry! who "unhandled argument count ~s for ~s" (length args) 'name))) - (with-output-language (L7 Expr) - (define-$type-check (L7 Expr)) - (define-syntax define-inline - (let () - (define ctht2 (make-hashtable symbol-hash eq?)) - (define ctht3 (make-hashtable symbol-hash eq?)) - (define check-and-record - (lambda (level name) - (let ([a (symbol-hashtable-cell (if (fx= level 2) ctht2 ctht3) (syntax->datum name) #f)]) - (when (cdr a) (syntax-error name "duplicate inline")) - (set-cdr! a #t)))) - (lambda (x) - (define compute-interface - (lambda (clause) - (syntax-case clause () - [(x e1 e2 ...) (identifier? #'x) -1] - [((x ...) e1 e2 ...) (length #'(x ...))] - [((x ... . r) e1 e2 ...) (fxlognot (length #'(x ...)))]))) - (define bitmaskify - (lambda (i*) - (fold-left (lambda (mask i) - (logor mask (if (fx< i 0) (ash -1 (fxlognot i)) (ash 1 i)))) - 0 i*))) - (syntax-case x () - [(k level id clause ...) - (identifier? #'id) - (let ([level (datum level)] [name (datum id)]) - (unless (memv level '(2 3)) - (syntax-error x (format "invalid level ~s in inline definition" level))) - (let ([pr ($sgetprop name (if (eqv? level 2) '*prim2* '*prim3*) #f)]) - (include "primref.ss") - (unless pr - (syntax-error x (format "unrecognized primitive name ~s in inline definition" name))) - (let ([arity (primref-arity pr)]) - (when arity - (unless (= (bitmaskify arity) (bitmaskify (map compute-interface #'(clause ...)))) - (syntax-error x (format "arity mismatch for ~s" name)))))) - (check-and-record level #'id) - (with-implicit (k src sexpr moi) - #`(symbol-hashtable-set! #,(if (eqv? level 2) #'ht2 #'ht3) 'id - (rec moi - (lambda (src sexpr args) - (apply (case-lambda clause ... [rest #f]) args))))))])))) - (define no-need-to-bind? - (lambda (multiple-ref? e) - (nanopass-case (L7 Expr) e - [,x (if (uvar? x) (not (uvar-assigned? x)) (eq? x %zero))] - [(immediate ,imm) #t] ; might should produce binding if imm is large - [(quote ,d) (or (not multiple-ref?) (ptr->imm d))] - [,pr (not multiple-ref?)] - [(literal ,info) (and (not multiple-ref?) (not (info-literal-indirect? info)))] - [(profile ,src) #t] - [(pariah) #t] - [else #f]))) - (define binder - (lambda (multiple-ref? type e) - (if (no-need-to-bind? multiple-ref? e) - (values e values) - (let ([t (make-tmp 't type)]) - (values t - (lambda (body) - `(let ([,t ,e]) ,body))))))) - (define list-binder - (lambda (multiple-ref? type e*) - (if (null? e*) - (values '() values) - (let-values ([(e dobind) (binder multiple-ref? type (car e*))] - [(e* dobind*) (list-binder multiple-ref? type (cdr e*))]) - (values (cons e e*) - (lambda (body) - (dobind (dobind* body)))))))) - (define-syntax $bind - (lambda (x) - (syntax-case x () - [(_ binder multiple-ref? type (b ...) e) - (let ([t0* (generate-temporaries #'(b ...))]) - (let f ([b* #'(b ...)] [t* t0*] [x* '()]) - (if (null? b*) - (with-syntax ([(x ...) (reverse x*)] [(t ...) t0*]) - #`(let ([x t] ...) e)) - (syntax-case (car b*) () - [x (identifier? #'x) - #`(let-values ([(#,(car t*) dobind) (binder multiple-ref? 'type x)]) - (dobind #,(f (cdr b*) (cdr t*) (cons #'x x*))))] - [(x e) (identifier? #'x) - #`(let-values ([(#,(car t*) dobind) (binder multiple-ref? 'type e)]) - (dobind #,(f (cdr b*) (cdr t*) (cons #'x x*))))]))))]))) - (define-syntax bind - (syntax-rules () - [(_ multiple-ref? type (b ...) e) - (identifier? #'type) - ($bind binder multiple-ref? type (b ...) e)] - [(_ multiple-ref? (b ...) e) - ($bind binder multiple-ref? ptr (b ...) e)])) - (define-syntax list-bind - (syntax-rules () - [(_ multiple-ref? type (b ...) e) - (identifier? #'type) - ($bind list-binder multiple-ref? type (b ...) e)] - [(_ multiple-ref? (b ...) e) - ($bind list-binder multiple-ref? ptr (b ...) e)])) - (define-syntax build-libcall - (lambda (x) - (syntax-case x () - [(k pariah? src sexpr name e ...) - (let ([libspec ($sgetprop (datum name) '*libspec* #f)]) - (define interface-okay? - (lambda (interface* cnt) - (ormap - (lambda (interface) - (if (fx< interface 0) - (fx>= cnt (lognot interface)) - (fx= cnt interface))) - interface*))) - (unless libspec (syntax-error x "unrecognized library routine")) - (unless (eqv? (length #'(e ...)) (libspec-interface libspec)) - (syntax-error x "invalid number of arguments")) - (let ([is-pariah? (datum pariah?)]) - (unless (boolean? is-pariah?) - (syntax-error x "pariah indicator must be a boolean literal")) - (when (and (libspec-error? libspec) (not is-pariah?)) - (syntax-error x "pariah indicator is inconsistent with libspec-error indicator")) - (with-implicit (k quasiquote) - (with-syntax ([body #`(call ,(make-info-call src sexpr #f pariah? #,(libspec-error? libspec)) #f - (literal ,(make-info-literal #f 'library '#,(datum->syntax #'* libspec) 0)) - ,e ...)]) - (if is-pariah? - #'`(seq (pariah) body) - #'`body)))))]))) - (define constant? - (case-lambda - [(x) - (nanopass-case (L7 Expr) x - [(quote ,d) #t] - ; TODO: handle immediate? - [else #f])] - [(pred? x) - (nanopass-case (L7 Expr) x - [(quote ,d) (pred? d)] - ; TODO: handle immediate? - [else #f])])) - (define constant-value - (lambda (x) - (nanopass-case (L7 Expr) x - [(quote ,d) d] - ; TODO: handle immediate if constant? does - [else #f]))) - (define maybe-add-label - (lambda (Llib body) - (if Llib - `(label ,Llib ,body) - body))) - (define build-and - (lambda (e1 e2) - `(if ,e1 ,e2 ,(%constant sfalse)))) - (define build-simple-or - (lambda (e1 e2) - `(if ,e1 ,(%constant strue) ,e2))) - (define build-fix - (lambda (e) - (%inline sll ,e ,(%constant fixnum-offset)))) - (define build-unfix - (lambda (e) - (nanopass-case (L7 Expr) e - [(quote ,d) (guard (target-fixnum? d)) `(immediate ,d)] - [else (%inline sra ,e ,(%constant fixnum-offset))]))) - (define build-not - (lambda (e) - `(if ,e ,(%constant sfalse) ,(%constant strue)))) - (define build-null? - (lambda (e) - (%type-check mask-nil snil ,e))) - (define build-eq? - (lambda (e1 e2) - (%inline eq? ,e1 ,e2))) - (define build-eqv? - (lambda (src sexpr e1 e2) - (build-libcall #f src sexpr eqv? e1 e2))) - (define make-build-eqv? - (lambda (src sexpr) - (lambda (e1 e2) - (build-eqv? src sexpr e1 e2)))) - (define fixnum-constant? - (lambda (e) - (constant? target-fixnum? e))) - (define expr->index - (lambda (e alignment limit) - (nanopass-case (L7 Expr) e - [(quote ,d) - (and (target-fixnum? d) - (>= d 0) - (< d limit) - (fxzero? (logand d (fx- alignment 1))) - d)] - [else #f]))) - (define build-fixnums? - (lambda (e*) - (let ([e* (remp fixnum-constant? e*)]) - (if (null? e*) - `(quote #t) - (%type-check mask-fixnum type-fixnum - ,(fold-left (lambda (e1 e2) (%inline logor ,e1 ,e2)) - (car e*) (cdr e*))))))) - (define build-flonums? - (lambda (e*) - (let ([e* (remp (lambda (e) (constant? flonum? e)) e*)]) - (if (null? e*) - `(quote #t) - (let f ([e* e*]) - (let ([e (car e*)] [e* (cdr e*)]) - (let ([check (%type-check mask-flonum type-flonum ,e)]) - (if (null? e*) - check - (build-and check (f e*)))))))))) - (define build-chars? - (lambda (e1 e2) - (define char-constant? - (lambda (e) - (constant? char? e))) - (if (char-constant? e1) - (if (char-constant? e2) - (%constant strue) - (%type-check mask-char type-char ,e2)) - (if (char-constant? e2) - (%type-check mask-char type-char ,e1) - (build-and - (%type-check mask-char type-char ,e1) - (%type-check mask-char type-char ,e2)))))) - (define build-list - (lambda (e*) - (if (null? e*) - (%constant snil) - (list-bind #f (e*) - (bind #t ([t (%constant-alloc type-pair (fx* (constant size-pair) (length e*)))]) - (let loop ([e* e*] [i 0]) - (let ([e (car e*)] [e* (cdr e*)]) - `(seq - (set! ,(%mref ,t ,(fx+ i (constant pair-car-disp))) ,e) - ,(if (null? e*) - `(seq - (set! ,(%mref ,t ,(fx+ i (constant pair-cdr-disp))) ,(%constant snil)) - ,t) - (let ([next-i (fx+ i (constant size-pair))]) - `(seq - (set! ,(%mref ,t ,(fx+ i (constant pair-cdr-disp))) - ,(%inline + ,t (immediate ,next-i))) - ,(loop e* next-i)))))))))))) - (define build-pair? - (lambda (e) - (%type-check mask-pair type-pair ,e))) - (define build-car - (lambda (e) - (%mref ,e ,(constant pair-car-disp)))) - (define build-cdr - (lambda (e) - (%mref ,e ,(constant pair-cdr-disp)))) - (define build-char->integer - (lambda (e) - (%inline srl ,e - (immediate ,(fx- (constant char-data-offset) (constant fixnum-offset)))))) - (define build-integer->char - (lambda (e) - (%inline + - ,(%inline sll ,e - (immediate ,(fx- (constant char-data-offset) (constant fixnum-offset)))) - ,(%constant type-char)))) - (define build-dirty-store - (case-lambda - [(base offset e) (build-dirty-store base %zero offset e)] - [(base index offset e) (build-dirty-store base index offset e - (lambda (base index offset e) `(set! ,(%mref ,base ,index ,offset) ,e)) - (lambda (s r) `(seq ,s ,r)))] - [(base index offset e build-assign build-seq) - (if (nanopass-case (L7 Expr) e - [(quote ,d) (ptr->imm d)] - [else #f]) - (build-assign base index offset e) - (let ([a (if (eq? index %zero) - (%lea ,base offset) - (%lea ,base ,index offset))]) - ; NB: should work harder to determine cases where x can't be a fixnum - (if (nanopass-case (L7 Expr) e - [(quote ,d) #t] - [(literal ,info) #t] - [else #f]) - (bind #f ([e e]) - ; eval a second so the address is not live across any calls - (bind #t ([a a]) - (build-seq - (build-assign a %zero 0 e) - (%inline remember ,a)))) - (bind #t ([e e]) - ; eval a second so the address is not live across any calls - (bind #t ([a a]) - (build-seq - (build-assign a %zero 0 e) - `(if ,(%type-check mask-fixnum type-fixnum ,e) - ,(%constant svoid) - ,(%inline remember ,a))))))))])) - (define make-build-cas - (lambda (old-v) - (lambda (base index offset v) - `(seq - ,(%inline cas ,base ,index (immediate ,offset) ,old-v ,v) - (inline ,(make-info-condition-code 'eq? #f #t) ,%condition-code))))) - (define build-cas-seq - (lambda (cas remember) - `(if ,cas - (seq ,remember ,(%constant strue)) - ,(%constant sfalse)))) - (define build-$record - (lambda (tag args) - (bind #f (tag) - (list-bind #f (args) - (let ([n (fx+ (length args) 1)]) - (bind #t ([t (%constant-alloc type-typed-object (fx* n (constant ptr-bytes)))]) - `(seq - (set! ,(%mref ,t ,(constant record-type-disp)) ,tag) - ,(let f ([args args] [offset (constant record-data-disp)]) - (if (null? args) - t - `(seq - (set! ,(%mref ,t ,offset) ,(car args)) - ,(f (cdr args) (fx+ offset (constant ptr-bytes))))))))))))) - (define build-$real->flonum - (lambda (src sexpr x who) - (if (constant? flonum? x) - x - (bind #t (x) - (bind #f (who) - `(if ,(%type-check mask-flonum type-flonum ,x) - ,x - ,(build-libcall #t src sexpr real->flonum x who))))))) - (define build-$inexactnum-real-part - (lambda (e) - (%lea ,e (fx+ (constant inexactnum-real-disp) - (fx- (constant type-flonum) (constant typemod)))))) - (define build-$inexactnum-imag-part - (lambda (e) - (%lea ,e (fx+ (constant inexactnum-imag-disp) - (fx- (constant type-flonum) (constant typemod)))))) - (define make-build-fill - (lambda (elt-bytes data-disp) - (define ptr-bytes (constant ptr-bytes)) - (define super-size - (lambda (e-fill) - (define-who super-size-imm - (lambda (imm) - `(immediate - ,(constant-case ptr-bytes - [(4) - (case elt-bytes - [(1) (let ([imm (logand imm #xff)]) - (let ([imm (logor (ash imm 8) imm)]) - (logor (ash imm 16) imm)))] - [(2) (let ([imm (logand imm #xffff)]) - (logor (ash imm 16) imm))] - [else (sorry! who "unexpected elt-bytes ~s" elt-bytes)])] - [(8) - (case elt-bytes - [(1) (let ([imm (logand imm #xff)]) - (let ([imm (logor (ash imm 8) imm)]) - (let ([imm (logor (ash imm 16) imm)]) - (logor (ash imm 32) imm))))] - [(2) (let ([imm (logand imm #xffff)]) - (let ([imm (logor (ash imm 16) imm)]) - (logor (ash imm 32) imm)))] - [(4) (let ([imm (logand imm #xffffffff)]) - (logor (ash imm 32) imm))] - [else (sorry! who "unexpected elt-bytes ~s" elt-bytes)])])))) - (define-who super-size-expr - (lambda (e-fill) - (define (double e-fill k) - (%inline logor - ,(%inline sll ,e-fill (immediate ,k)) - ,e-fill)) - (define (mask e-fill k) - (%inline logand ,e-fill (immediate ,k))) - (constant-case ptr-bytes - [(4) - (case elt-bytes - [(1) (bind #t ([e-fill (mask e-fill #xff)]) - (bind #t ([e-fill (double e-fill 8)]) - (double e-fill 16)))] - [(2) (bind #t ([e-fill (mask e-fill #xffff)]) - (double e-fill 16))] - [else (sorry! who "unexpected elt-bytes ~s" elt-bytes)])] - [(8) - (case elt-bytes - [(1) (bind #t ([e-fill (mask e-fill #xff)]) - (bind #t ([e-fill (double e-fill 8)]) - (bind #t ([e-fill (double e-fill 16)]) - (double e-fill 32))))] - [(2) (bind #t ([e-fill (mask e-fill #xffff)]) - (bind #t ([e-fill (double e-fill 16)]) - (double e-fill 32)))] - [(4) (bind #t ([e-fill (mask e-fill #xffffffff)]) - (double e-fill 32))] - [else (sorry! who "unexpected elt-bytes ~s" elt-bytes)])]))) - (if (fx= elt-bytes ptr-bytes) - e-fill - (nanopass-case (L7 Expr) e-fill - [(quote ,d) - (cond - [(ptr->imm d) => super-size-imm] - [else (super-size-expr e-fill)])] - [(immediate ,imm) (super-size-imm imm)] - [else (super-size-expr e-fill)])))) - (lambda (e-vec e-bytes e-fill) - ; NB: caller must bind e-vec and e-fill - (safe-assert (no-need-to-bind? #t e-vec)) - (safe-assert (no-need-to-bind? #f e-fill)) - (nanopass-case (L7 Expr) e-bytes - [(immediate ,imm) - (guard (fixnum? imm) (fx<= 0 imm (fx* 4 ptr-bytes))) - (if (fx= imm 0) - e-vec - (bind #t ([e-fill (super-size e-fill)]) - (let f ([n (if (fx>= elt-bytes ptr-bytes) - imm - (fxlogand (fx+ imm (fx- ptr-bytes 1)) (fx- ptr-bytes)))]) - (let ([n (fx- n ptr-bytes)]) - `(seq - (set! ,(%mref ,e-vec ,(fx+ data-disp n)) ,e-fill) - ,(if (fx= n 0) e-vec (f n)))))))] - [else - (let ([Ltop (make-local-label 'Ltop)] [t (make-assigned-tmp 't 'uptr)]) - (bind #t ([e-fill (super-size e-fill)]) - `(let ([,t ,(if (fx>= elt-bytes ptr-bytes) - e-bytes - (nanopass-case (L7 Expr) e-bytes - [(immediate ,imm) - `(immediate ,(logand (+ imm (fx- ptr-bytes 1)) (fx- ptr-bytes)))] - [else - (%inline logand - ,(%inline + - ,e-bytes - (immediate ,(fx- ptr-bytes 1))) - (immediate ,(fx- ptr-bytes)))]))]) - (label ,Ltop - (if ,(%inline eq? ,t (immediate 0)) - ,e-vec - ,(%seq - (set! ,t ,(%inline - ,t (immediate ,ptr-bytes))) - (set! ,(%mref ,e-vec ,t ,data-disp) ,e-fill) - (goto ,Ltop)))))))])))) - - ;; NOTE: integer->ptr and unsigned->ptr DO NOT handle 64-bit integers on a 32-bit machine. - ;; this is okay for $object-ref and $object-set!, which do not support moving 64-bit values - ;; as single entities on a 32-bit machine, but care should be taken if these are used with - ;; other primitives. - (define-who integer->ptr - (lambda (x width) - (if (fx>= (constant fixnum-bits) width) - (build-fix x) - (%seq - (set! ,%ac0 ,x) - (set! ,%xp ,(build-fix %ac0)) - (set! ,%xp ,(build-unfix %xp)) - (if ,(%inline eq? ,%ac0 ,%xp) - ,(build-fix %ac0) - (seq - (set! ,%ac0 - (inline - ,(case width - [(32) (intrinsic-info-asmlib dofretint32 #f)] - [(64) (intrinsic-info-asmlib dofretint64 #f)] - [else ($oops who "can't handle width ~s" width)]) - ,%asmlibcall)) - ,%ac0)))))) - (define-who unsigned->ptr - (lambda (x width) - (if (fx>= (constant fixnum-bits) width) - (build-fix x) - `(seq - (set! ,%ac0 ,x) - (if ,(%inline u< ,(%constant most-positive-fixnum) ,%ac0) - (seq - (set! ,%ac0 - (inline - ,(case width - [(32) (intrinsic-info-asmlib dofretuns32 #f)] - [(64) (intrinsic-info-asmlib dofretuns64 #f)] - [else ($oops who "can't handle width ~s" width)]) - ,%asmlibcall)) - ,%ac0) - ,(build-fix %ac0)))))) - (define-who i32xu32->ptr - (lambda (hi lo) - (safe-assert (eqv? (constant ptr-bits) 32)) - (let ([Lbig (make-local-label 'Lbig)]) - (bind #t (lo hi) - `(if ,(%inline eq? ,hi ,(%inline sra ,lo (immediate 31))) - ,(bind #t ([fxlo (build-fix lo)]) - `(if ,(%inline eq? ,(build-unfix fxlo) ,lo) - ,fxlo - (goto ,Lbig))) - (label ,Lbig - ,(%seq - (set! ,%ac0 ,lo) - (set! ,(ref-reg %ac1) ,hi) - (set! ,%ac0 (inline ,(intrinsic-info-asmlib dofretint64 #f) ,%asmlibcall)) - ,%ac0))))))) - (define-who u32xu32->ptr - (lambda (hi lo) - (safe-assert (eqv? (constant ptr-bits) 32)) - (let ([Lbig (make-local-label 'Lbig)]) - (bind #t (lo hi) - `(if ,(%inline eq? ,hi (immediate 0)) - (if ,(%inline u< ,(%constant most-positive-fixnum) ,lo) - (goto ,Lbig) - ,(build-fix lo)) - (label ,Lbig - ,(%seq - (set! ,%ac0 ,lo) - (set! ,(ref-reg %ac1) ,hi) - (set! ,%ac0 (inline ,(intrinsic-info-asmlib dofretuns64 #f) ,%asmlibcall)) - ,%ac0))))))) - - (define-who ptr->integer - (lambda (value width) - (if (fx> (constant fixnum-bits) width) - (build-unfix value) - `(seq - (set! ,%ac0 ,value) - (if ,(%type-check mask-fixnum type-fixnum ,%ac0) - ,(build-unfix %ac0) - (seq - (set! ,%ac0 - (inline - ,(cond - [(fx<= width 32) (intrinsic-info-asmlib dofargint32 #f)] - [(fx<= width 64) (intrinsic-info-asmlib dofargint64 #f)] - [else ($oops who "can't handle width ~s" width)]) - ,%asmlibcall)) - ,%ac0)))))) - (define ptr-type (constant-case ptr-bits - [(32) 'unsigned-32] - [(64) 'unsigned-64] - [else ($oops 'ptr-type "unknown ptr-bit size ~s" (constant ptr-bits))])) - (define-who type->width - (lambda (x) - (case x - [(integer-8 unsigned-8 char) 8] - [(integer-16 unsigned-16) 16] - [(integer-24 unsigned-24) 24] - [(integer-32 unsigned-32 single-float) 32] - [(integer-40 unsigned-40) 40] - [(integer-48 unsigned-48) 48] - [(integer-56 unsigned-56) 56] - [(integer-64 unsigned-64 double-float) 64] - [(scheme-object fixnum) (constant ptr-bits)] - [(wchar) (constant wchar-bits)] - [else ($oops who "unknown type ~s" x)]))) - (define offset-expr->index+offset - (lambda (offset) - (if (fixnum-constant? offset) - (values %zero (constant-value offset)) - (values (build-unfix offset) 0)))) - (define-who build-int-load - (lambda (swapped? type base index offset build-int) - (case type - [(integer-8 unsigned-8) - (build-int `(inline ,(make-info-load type #f) ,%load ,base ,index (immediate ,offset)))] - [(integer-16 integer-32 unsigned-16 unsigned-32) - (build-int `(inline ,(make-info-load type swapped?) ,%load ,base ,index (immediate ,offset)))] - [(integer-64 unsigned-64) - (constant-case ptr-bits - [(32) - (let-values ([(lo hi) (if (constant-case native-endianness [(little) swapped?] [(big) (not swapped?)]) - (values (+ offset 4) offset) - (values offset (+ offset 4)))]) - (bind #t (base index) - (build-int - `(inline ,(make-info-load 'integer-32 swapped?) ,%load ,base ,index (immediate ,hi)) - `(inline ,(make-info-load 'unsigned-32 swapped?) ,%load ,base ,index (immediate ,lo)))))] - [(64) - (build-int `(inline ,(make-info-load type swapped?) ,%load ,base ,index (immediate ,offset)))])] - [(integer-24 unsigned-24) - (constant-case unaligned-integers - [(#t) - (let-values ([(lo hi) (if (constant-case native-endianness [(little) swapped?] [(big) (not swapped?)]) - (values (+ offset 1) offset) - (values offset (+ offset 2)))]) - (define hi-type (if (eq? type 'integer-24) 'integer-8 'unsigned-8)) - (bind #t (base index) - (build-int - (%inline logor - ,(%inline sll - (inline ,(make-info-load hi-type #f) ,%load ,base ,index (immediate ,hi)) - (immediate 16)) - (inline ,(make-info-load 'unsigned-16 swapped?) ,%load ,base ,index (immediate ,lo))))))])] - [(integer-40 unsigned-40) - (constant-case unaligned-integers - [(#t) - (let-values ([(lo hi) (if (constant-case native-endianness [(little) swapped?] [(big) (not swapped?)]) - (values (+ offset 1) offset) - (values offset (+ offset 4)))]) - (define hi-type (if (eq? type 'integer-40) 'integer-8 'unsigned-8)) - (bind #t (base index) - (constant-case ptr-bits - [(32) - (build-int - `(inline ,(make-info-load hi-type #f) ,%load ,base ,index (immediate ,hi)) - `(inline ,(make-info-load 'unsigned-32 swapped?) ,%load ,base ,index (immediate ,lo)))] - [(64) - (build-int - (%inline logor - ,(%inline sll - (inline ,(make-info-load hi-type #f) ,%load ,base ,index (immediate ,hi)) - (immediate 32)) - (inline ,(make-info-load 'unsigned-32 swapped?) ,%load ,base ,index (immediate ,lo))))])))])] - [(integer-48 unsigned-48) - (constant-case unaligned-integers - [(#t) - (let-values ([(lo hi) (if (constant-case native-endianness [(little) swapped?] [(big) (not swapped?)]) - (values (+ offset 2) offset) - (values offset (+ offset 4)))]) - (define hi-type (if (eq? type 'integer-48) 'integer-16 'unsigned-16)) - (bind #t (base index) - (constant-case ptr-bits - [(32) - (build-int - `(inline ,(make-info-load hi-type swapped?) ,%load ,base ,index (immediate ,hi)) - `(inline ,(make-info-load 'unsigned-32 swapped?) ,%load ,base ,index (immediate ,lo)))] - [(64) - (build-int - (%inline logor - ,(%inline sll - (inline ,(make-info-load hi-type swapped?) ,%load ,base ,index (immediate ,hi)) - (immediate 32)) - (inline ,(make-info-load 'unsigned-32 swapped?) ,%load ,base ,index (immediate ,lo))))])))])] - [(integer-56 unsigned-56) - (constant-case unaligned-integers - [(#t) - (let-values ([(lo mi hi) (if (constant-case native-endianness [(little) swapped?] [(big) (not swapped?)]) - (values (+ offset 3) (+ offset 1) offset) - (values offset (+ offset 4) (+ offset 6)))]) - (define hi-type (if (eq? type 'integer-56) 'integer-8 'unsigned-8)) - (bind #t (base index) - (constant-case ptr-bits - [(32) - (build-int - (%inline logor - ,(%inline sll - (inline ,(make-info-load hi-type #f) ,%load ,base ,index (immediate ,hi)) - (immediate 16)) - (inline ,(make-info-load 'unsigned-16 swapped?) ,%load ,base ,index (immediate ,mi))) - `(inline ,(make-info-load 'unsigned-32 swapped?) ,%load ,base ,index (immediate ,lo)))] - [(64) - (build-int - (%inline logor - ,(%inline sll - ,(%inline logor - ,(%inline sll - (inline ,(make-info-load hi-type #f) ,%load ,base ,index (immediate ,hi)) - (immediate 16)) - (inline ,(make-info-load 'unsigned-16 swapped?) ,%load ,base ,index (immediate ,mi))) - (immediate 32)) - (inline ,(make-info-load 'unsigned-32 swapped?) ,%load ,base ,index (immediate ,lo))))])))])] - [else (sorry! who "unsupported type ~s" type)]))) - (define-who build-object-ref - (case-lambda - [(swapped? type base offset-expr) - (let-values ([(index offset) (offset-expr->index+offset offset-expr)]) - (build-object-ref swapped? type base index offset))] - [(swapped? type base index offset) - (case type - [(scheme-object) `(inline ,(make-info-load ptr-type swapped?) ,%load ,base ,index (immediate ,offset))] - [(double-float) - (if swapped? - (constant-case ptr-bits - [(32) - (bind #t (base index) - (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))]) - (%seq - (set! ,(%mref ,t ,(constant flonum-data-disp)) - (inline ,(make-info-load 'unsigned-32 #t) ,%load ,base ,index - (immediate ,(+ offset 4)))) - (set! ,(%mref ,t ,(+ (constant flonum-data-disp) 4)) - (inline ,(make-info-load 'unsigned-32 #t) ,%load ,base ,index - (immediate ,offset))) - ,t)))] - [(64) - (bind #f (base index) - (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))]) - `(seq - (set! ,(%mref ,t ,(constant flonum-data-disp)) - (inline ,(make-info-load 'unsigned-64 #t) ,%load ,base ,index - (immediate ,offset))) - ,t)))]) - (bind #f (base index) - (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))]) - (%seq - (inline ,(make-info-loadfl %flreg1) ,%load-double - ,base ,index (immediate ,offset)) - (inline ,(make-info-loadfl %flreg1) ,%store-double - ,t ,%zero ,(%constant flonum-data-disp)) - ,t))))] - [(single-float) - (if swapped? - (bind #f (base index) - (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))]) - (%seq - (set! ,(%mref ,t ,(constant flonum-data-disp)) - (inline ,(make-info-load 'unsigned-32 #t) ,%load ,base ,index - (immediate ,offset))) - (inline ,(make-info-loadfl %flreg1) ,%load-single->double - ,t ,%zero ,(%constant flonum-data-disp)) - (inline ,(make-info-loadfl %flreg1) ,%store-double - ,t ,%zero ,(%constant flonum-data-disp)) - ,t))) - (bind #f (base index) - (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))]) - (%seq - (inline ,(make-info-loadfl %flreg1) ,%load-single->double - ,base ,index (immediate ,offset)) - (inline ,(make-info-loadfl %flreg1) ,%store-double - ,t ,%zero ,(%constant flonum-data-disp)) - ,t))))] - [(integer-8 integer-16 integer-24 integer-32 integer-40 integer-48 integer-56 integer-64) - (build-int-load swapped? type base index offset - (if (and (eqv? (constant ptr-bits) 32) (memq type '(integer-40 integer-48 integer-56 integer-64))) - i32xu32->ptr - (lambda (x) (integer->ptr x (type->width type)))))] - [(unsigned-8 unsigned-16 unsigned-24 unsigned-32 unsigned-40 unsigned-48 unsigned-56 unsigned-64) - (build-int-load swapped? type base index offset - (if (and (eqv? (constant ptr-bits) 32) (memq type '(unsigned-40 unsigned-48 unsigned-56 unsigned-64))) - u32xu32->ptr - (lambda (x) (unsigned->ptr x (type->width type)))))] - [(fixnum) (build-fix `(inline ,(make-info-load ptr-type swapped?) ,%load ,base ,index (immediate ,offset)))] - [else (sorry! who "unsupported type ~s" type)])])) - (define-who build-int-store - (lambda (swapped? type base index offset value) - (case type - [(integer-8 unsigned-8) - `(inline ,(make-info-load type #f) ,%store ,base ,index (immediate ,offset) ,value)] - [(integer-16 integer-32 integer-64 unsigned-16 unsigned-32 unsigned-64) - `(inline ,(make-info-load type swapped?) ,%store ,base ,index (immediate ,offset) ,value)] - [(integer-24 unsigned-24) - (constant-case unaligned-integers - [(#t) - (let-values ([(lo hi) (if (constant-case native-endianness [(little) swapped?] [(big) (not swapped?)]) - (values (+ offset 1) offset) - (values offset (+ offset 2)))]) - (bind #t (base index value) - (%seq - (inline ,(make-info-load 'unsigned-16 swapped?) ,%store ,base ,index (immediate ,lo) ,value) - (inline ,(make-info-load 'unsigned-8 #f) ,%store ,base ,index (immediate ,hi) - ,(%inline srl ,value (immediate 16))))))])] - [(integer-40 unsigned-40) - (constant-case unaligned-integers - [(#t) - (let-values ([(lo hi) (if (constant-case native-endianness [(little) swapped?] [(big) (not swapped?)]) - (values (+ offset 1) offset) - (values offset (+ offset 4)))]) - (bind #t (base index value) - (%seq - (inline ,(make-info-load 'unsigned-32 swapped?) ,%store ,base ,index (immediate ,lo) ,value) - (inline ,(make-info-load 'unsigned-8 #f) ,%store ,base ,index (immediate ,hi) - ,(%inline srl ,value (immediate 32))))))])] - [(integer-48 unsigned-48) - (constant-case unaligned-integers - [(#t) - (let-values ([(lo hi) (if (constant-case native-endianness [(little) swapped?] [(big) (not swapped?)]) - (values (+ offset 2) offset) - (values offset (+ offset 4)))]) - (bind #t (base index value) - (%seq - (inline ,(make-info-load 'unsigned-32 swapped?) ,%store ,base ,index (immediate ,lo) ,value) - (inline ,(make-info-load 'unsigned-16 swapped?) ,%store ,base ,index (immediate ,hi) - ,(%inline srl ,value (immediate 32))))))])] - [(integer-56 unsigned-56) - (constant-case unaligned-integers - [(#t) - (let-values ([(lo mi hi) (if (constant-case native-endianness [(little) swapped?] [(big) (not swapped?)]) - (values (+ offset 3) (+ offset 1) offset) - (values offset (+ offset 4) (+ offset 6)))]) - (bind #t (base index value) - (%seq - (inline ,(make-info-load 'unsigned-32 swapped?) ,%store ,base ,index (immediate ,lo) ,value) - (inline ,(make-info-load 'unsigned-16 swapped?) ,%store ,base ,index (immediate ,mi) - ,(%inline srl ,value (immediate 32))) - (inline ,(make-info-load 'unsigned-8 #f) ,%store ,base ,index (immediate ,hi) - ,(%inline srl ,value (immediate 48))))))])] - [else (sorry! who "unsupported type ~s" type)]))) - (define-who build-object-set! - (case-lambda - [(type base offset-expr value) - (let-values ([(index offset) (offset-expr->index+offset offset-expr)]) - (build-object-set! type base index offset value))] - [(type base index offset value) - (case type - [(scheme-object) (build-dirty-store base index offset value)] - [(double-float) - (bind #f (base index) - (%seq - (inline ,(make-info-loadfl %flreg1) ,%load-double - ,value ,%zero ,(%constant flonum-data-disp)) - (inline ,(make-info-loadfl %flreg1) ,%store-double - ,base ,index (immediate ,offset))))] - [(single-float) - (bind #f (base index) - (%seq - (inline ,(make-info-loadfl %flreg1) ,%load-double->single - ,value ,%zero ,(%constant flonum-data-disp)) - (inline ,(make-info-loadfl %flreg1) ,%store-single - ,base ,index (immediate ,offset))))] - ; 40-bit+ only on 64-bit machines - [(integer-8 integer-16 integer-24 integer-32 integer-40 integer-48 integer-56 integer-64 - unsigned-8 unsigned-16 unsigned-24 unsigned-32 unsigned-40 unsigned-48 unsigned-56 unsigned-64) - (build-int-store #f type base index offset (ptr->integer value (type->width type)))] - [(fixnum) - `(inline ,(make-info-load ptr-type #f) ,%store - ,base ,index (immediate ,offset) ,(build-unfix value))] - [else (sorry! who "unrecognized type ~s" type)])])) - (define-who build-swap-object-set! - (case-lambda - [(type base offset-expr value) - (let-values ([(index offset) (offset-expr->index+offset offset-expr)]) - (build-swap-object-set! type base index offset value))] - [(type base index offset value) - (case type - ; only on 64-bit machines - [(double-float) - `(inline ,(make-info-load 'unsigned-64 #t) ,%store - ,base ,index (immediate ,offset) - ,(%mref ,value ,(constant flonum-data-disp)))] - ; 40-bit+ only on 64-bit machines - [(integer-16 integer-24 integer-32 integer-40 integer-48 integer-56 integer-64 - unsigned-16 unsigned-24 unsigned-32 unsigned-40 unsigned-48 unsigned-56 unsigned-64) - (build-int-store #t type base index offset (ptr->integer value (type->width type)))] - [(fixnum) - `(inline ,(make-info-load ptr-type #t) ,%store ,base ,index (immediate ,offset) - ,(build-unfix value))] - [else (sorry! who "unrecognized type ~s" type)])])) - (define extract-unsigned-bitfield - (lambda (raw? start end arg) - (let* ([left (fx- (if raw? (constant ptr-bits) (constant fixnum-bits)) end)] - [right (if raw? (fx- (fx+ left start) (constant fixnum-offset)) (fx+ left start))] - [body (%inline srl - ,(if (fx= left 0) - arg - (%inline sll ,arg (immediate ,left))) - (immediate ,right))]) - (if (fx= start 0) - body - (%inline logand ,body (immediate ,(- (constant fixnum-factor)))))))) - (define extract-signed-bitfield - (lambda (raw? start end arg) - (let* ([left (fx- (if raw? (constant ptr-bits) (constant fixnum-bits)) end)] - [right (if raw? (fx- (fx+ left start) (constant fixnum-offset)) (fx+ left start))]) - (let ([body (if (fx= left 0) arg (%inline sll ,arg (immediate ,left)))]) - (let ([body (if (fx= right 0) body (%inline sra ,body (immediate ,right)))]) - (if (fx= start 0) - body - (%inline logand ,body (immediate ,(- (constant fixnum-factor)))))))))) - (define insert-bitfield - (lambda (raw? start end bf-width arg val) - (if raw? - (cond - [(fx= start 0) - (%inline logor - ,(%inline sll - ,(%inline srl ,arg (immediate ,end)) - (immediate ,end)) - ,(%inline srl - ,(%inline sll ,val (immediate ,(fx- (constant fixnum-bits) end))) - (immediate ,(fx- (constant ptr-bits) end))))] - [(fx= end bf-width) - (%inline logor - ,(%inline srl - ,(%inline sll ,arg - (immediate ,(fx- (constant ptr-bits) start))) - (immediate ,(fx- (constant ptr-bits) start))) - ,(cond - [(fx< start (constant fixnum-offset)) - (%inline srl ,val - (immediate ,(fx- (constant fixnum-offset) start)))] - [(fx> start (constant fixnum-offset)) - (%inline sll ,val - (immediate ,(fx- start (constant fixnum-offset))))] - [else val]))] - [else - (%inline logor - ,(%inline logand ,arg - (immediate ,(lognot (ash (- (expt 2 (fx- end start)) 1) start)))) - ,(%inline srl - ,(if (fx= (fx- end start) (constant fixnum-bits)) - val - (%inline sll ,val - (immediate ,(fx- (constant fixnum-bits) (fx- end start))))) - (immediate ,(fx- (constant ptr-bits) end))))]) - (cond - [(fx= start 0) - (%inline logor - ,(%inline sll - ,(%inline srl ,arg (immediate ,(fx+ end (constant fixnum-offset)))) - (immediate ,(fx+ end (constant fixnum-offset)))) - ,(%inline srl - ,(%inline sll ,val (immediate ,(fx- (constant fixnum-bits) end))) - (immediate ,(fx- (constant fixnum-bits) end))))] - #;[(fx= end (constant fixnum-bits)) ---] ; end < fixnum-bits - [else - (%inline logor - ,(%inline logand ,arg - (immediate ,(lognot (ash (- (expt 2 (fx- end start)) 1) - (fx+ start (constant fixnum-offset)))))) - ,(%inline srl - ,(%inline sll ,val - (immediate ,(fx- (constant fixnum-bits) (fx- end start)))) - (immediate ,(fx- (constant fixnum-bits) end))))])))) - (define translate - (lambda (e current-shift target-shift) - (let ([delta (fx- current-shift target-shift)]) - (if (fx= delta 0) - e - (if (fx< delta 0) - (%inline sll ,e (immediate ,(fx- delta))) - (%inline srl ,e (immediate ,delta))))))) - (define extract-length - (lambda (t/l length-offset) - (%inline logand - ,(translate t/l length-offset (constant fixnum-offset)) - (immediate ,(- (constant fixnum-factor)))))) - (define build-type/length - (lambda (e type current-shift target-shift) - (let ([e (translate e current-shift target-shift)]) - (if (eqv? type 0) - e - (%inline logor ,e (immediate ,type)))))) - (define-syntax build-ref-check - (syntax-rules () - [(_ type-disp maximum-length length-offset type mask immutable-flag) - (lambda (e-v e-i maybe-e-new) - ; NB: caller must bind e-v, e-i, and maybe-e-new - (safe-assert (no-need-to-bind? #t e-v)) - (safe-assert (no-need-to-bind? #t e-i)) - (safe-assert (or (not maybe-e-new) (no-need-to-bind? #t maybe-e-new))) - (build-and - (%type-check mask-typed-object type-typed-object ,e-v) - (bind #t ([t (%mref ,e-v ,(constant type-disp))]) - (cond - [(expr->index e-i 1 (constant maximum-length)) => - (lambda (index) - (let ([e (%inline u< - (immediate ,(logor (ash index (constant length-offset)) (constant type) (constant immutable-flag))) - ,t)]) - (if (and (eqv? (constant type) (constant type-fixnum)) - (eqv? (constant mask) (constant mask-fixnum))) - (build-and e (build-fixnums? (if maybe-e-new (list t maybe-e-new) (list t)))) - (build-and - (%type-check mask type ,t) - (if maybe-e-new (build-and e (build-fixnums? (list maybe-e-new))) e)))))] - [else - (let ([e (%inline u< ,e-i ,(extract-length t (constant length-offset)))]) - (if (and (eqv? (constant type) (constant type-fixnum)) - (eqv? (constant mask) (constant mask-fixnum))) - (build-and e (build-fixnums? (if maybe-e-new (list e-i t maybe-e-new) (list e-i t)))) - (build-and - (%type-check mask type ,t) - (build-and - (build-fixnums? (if maybe-e-new (list e-i maybe-e-new) (list e-i))) - e))))]))))])) - (define-syntax build-set-immutable! - (syntax-rules () - [(_ type-disp immutable-flag) - (lambda (e-v) - (bind #t (e-v) - `(set! ,(%mref ,e-v ,(constant type-disp)) - ,(%inline logor - ,(%mref ,e-v ,(constant type-disp)) - (immediate ,(constant immutable-flag))))))])) - (define inline-args-limit 10) - (define reduce-equality - (lambda (src sexpr moi e1 e2 e*) - (and (fx<= (length e*) (fx- inline-args-limit 2)) - (bind #t (e1) - (bind #f (e2) - (list-bind #f (e*) - (let compare ([src src] [e2 e2] [e* e*]) - (if (null? e*) - (moi src sexpr (list e1 e2)) - `(if ,(moi src sexpr (list e1 e2)) - ,(compare #f (car e*) (cdr e*)) - (quote #f)))))))))) - (define reduce-inequality - (lambda (src sexpr moi e1 e2 e*) - (and (fx<= (length e*) (fx- inline-args-limit 2)) - (let f ([e2 e2] [e* e*] [re* '()]) - (if (null? e*) - (bind #f ([e2 e2]) - (let compare ([src src] [e* (cons e1 (reverse (cons e2 re*)))]) - (let ([more-args (cddr e*)]) - (if (null? more-args) - (moi src sexpr e*) - `(if ,(moi src sexpr (list (car e*) (cadr e*))) - ,(compare #f (cdr e*)) - (quote #f)))))) - (bind #t ([e2 e2]) (f (car e*) (cdr e*) (cons e2 re*)))))))) - (define reduce ; left associative as required for, e.g., fx- - (lambda (src sexpr moi e e*) - (and (fx<= (length e*) (fx- inline-args-limit 1)) - (bind #f (e) - (list-bind #f ([e* e*]) - (let reduce ([src src] [e e] [e* e*]) - (if (null? e*) - e - (reduce #f (moi src sexpr (list e (car e*))) (cdr e*))))))))) - (module (relop-length RELOP< RELOP<= RELOP= RELOP>= RELOP>) - (define RELOP< -2) - (define RELOP<= -1) - (define RELOP= 0) - (define RELOP>= 1) - (define RELOP> 2) - (define (mirror op) (fx- op)) - (define go - (lambda (op e n) - (let f ([n n] [e e]) - (if (fx= n 0) - (cond - [(or (eqv? op RELOP=) (eqv? op RELOP<=)) (build-null? e)] - [(eqv? op RELOP<) `(seq ,e (quote #f))] - [(eqv? op RELOP>) (build-not (build-null? e))] - [(eqv? op RELOP>=) `(seq ,e (quote #t))] - [else (sorry! 'relop-length "unexpected op ~s" op)]) - (cond - [(or (eqv? op RELOP=) (eqv? op RELOP>)) - (bind #t (e) - (build-and - (build-not (build-null? e)) - (f (fx- n 1) (build-cdr e))))] - [(eqv? op RELOP<) - (if (fx= n 1) - (build-null? e) - (bind #t (e) - (build-simple-or - (build-null? e) - (f (fx- n 1) (build-cdr e)))))] - [(eqv? op RELOP<=) - (bind #t (e) - (build-simple-or - (build-null? e) - (f (fx- n 1) (build-cdr e))))] - [(eqv? op RELOP>=) - (if (fx= n 1) - (build-not (build-null? e)) - (bind #t (e) - (build-and - (build-not (build-null? e)) - (f (fx- n 1) (build-cdr e)))))] - [else (sorry! 'relop-length "unexpected op ~s" op)]))))) - (define relop-length1 - (lambda (op e n) - (nanopass-case (L7 Expr) e - [(call ,info ,mdcl ,pr ,e) - (guard (and (eq? (primref-name pr) 'length) (all-set? (prim-mask unsafe) (primref-flags pr)))) - (go op e n)] - [else #f]))) - (define relop-length2 - (lambda (op e1 e2) - (nanopass-case (L7 Expr) e2 - [(quote ,d) (and (fixnum? d) (fx<= 0 d 4) (relop-length1 op e1 d))] - [else #f]))) - (define relop-length - (case-lambda - [(op e) (relop-length1 op e 0)] - [(op e1 e2) (or (relop-length2 op e1 e2) (relop-length2 (mirror op) e2 e1))]))) - (define make-ftype-pointer-equal? - (lambda (e1 e2) - (bind #f (e1 e2) - (%inline eq? - ,(%mref ,e1 ,(constant record-data-disp)) - ,(%mref ,e2 ,(constant record-data-disp)))))) - (define make-ftype-pointer-null? - (lambda (e) - (%inline eq? - ,(%mref ,e ,(constant record-data-disp)) - (immediate 0)))) - (define eqvop-null-fptr - (lambda (e1 e2) - (nanopass-case (L7 Expr) e1 - [(call ,info ,mdcl ,pr ,e1) - (and - (eq? (primref-name pr) 'ftype-pointer-address) - (all-set? (prim-mask unsafe) (primref-flags pr)) - (nanopass-case (L7 Expr) e2 - [(quote ,d) - (and (eqv? d 0) (make-ftype-pointer-null? e1))] - [(call ,info ,mdcl ,pr ,e2) - (and (eq? (primref-name pr) 'ftype-pointer-address) - (all-set? (prim-mask unsafe) (primref-flags pr)) - (make-ftype-pointer-equal? e1 e2))] - [else #f]))] - [(quote ,d) - (and (eqv? d 0) - (nanopass-case (L7 Expr) e2 - [(call ,info ,mdcl ,pr ,e2) - (and (eq? (primref-name pr) 'ftype-pointer-address) - (all-set? (prim-mask unsafe) (primref-flags pr)) - (make-ftype-pointer-null? e2))] - [else #f]))] - [else #f]))) - (define-inline 2 values - [(e) e] - [e* `(values ,(make-info-call src sexpr #f #f #f) ,e* ...)]) - (define-inline 2 eq? - [(e1 e2) - (or (eqvop-null-fptr e1 e2) - (relop-length RELOP= e1 e2) - (%inline eq? ,e1 ,e2))]) - (define-inline 2 $keep-live - [(e) (%seq ,(%inline keep-live ,e) ,(%constant svoid))]) - (let () - (define (zgo src sexpr e e1 e2 r6rs?) - (build-simple-or - (%inline eq? ,e (immediate 0)) - `(if ,(build-fixnums? (list e)) - ,(%constant sfalse) - ,(if r6rs? - (build-libcall #t src sexpr fx=? e1 e2) - (build-libcall #t src sexpr fx= e1 e2))))) - (define (go src sexpr e1 e2 r6rs?) - (or (relop-length RELOP= e1 e2) - (cond - [(constant? (lambda (x) (eqv? x 0)) e1) - (bind #t (e2) (zgo src sexpr e2 e1 e2 r6rs?))] - [(constant? (lambda (x) (eqv? x 0)) e2) - (bind #t (e1) (zgo src sexpr e1 e1 e2 r6rs?))] - [else (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(%inline eq? ,e1 ,e2) - ,(if r6rs? - (build-libcall #t src sexpr fx=? e1 e2) - (build-libcall #t src sexpr fx= e1 e2))))]))) - (define-inline 2 fx= - [(e1 e2) (go src sexpr e1 e2 #f)] - [(e1 . e*) #f]) - (define-inline 2 fx=? - [(e1 e2) (go src sexpr e1 e2 #t)] - [(e1 e2 . e*) #f])) - (let () ; level 2 fx<, fx= fx>=? RELOP>= >=) - (fx-pred fx> fx>? RELOP> >)) - (let () ; level 3 fx=, fx=?, etc. - (define-syntax fx-pred - (syntax-rules () - [(_ op r6rs:op length-op inline-op) - (let () - (define (go e1 e2) - (or (relop-length length-op e1 e2) - (%inline inline-op ,e1 ,e2))) - (define reducer - (if (eq? 'inline-op 'eq?) - reduce-equality - reduce-inequality)) - (define-inline 3 op - [(e) `(seq ,e ,(%constant strue))] - [(e1 e2) (go e1 e2)] - [(e1 e2 . e*) (reducer src sexpr moi e1 e2 e*)]) - (define-inline 3 r6rs:op - [(e1 e2) (go e1 e2)] - [(e1 e2 . e*) (reducer src sexpr moi e1 e2 e*)]))])) - (fx-pred fx< fx= fx>=? RELOP>= >=) - (fx-pred fx> fx>? RELOP> >)) - (let () ; level 3 fxlogand, ... - (define-syntax fxlogop - (syntax-rules () - [(_ op inline-op base) - (define-inline 3 op - [() `(immediate ,(fix base))] - [(e) e] - [(e1 e2) (%inline inline-op ,e1 ,e2)] - [(e1 . e*) (reduce src sexpr moi e1 e*)])])) - (fxlogop fxlogand logand -1) - (fxlogop fxand logand -1) - (fxlogop fxlogor logor 0) - (fxlogop fxlogior logor 0) - (fxlogop fxior logor 0) - (fxlogop fxlogxor logxor 0) - (fxlogop fxxor logxor 0)) - (let () - (define log-partition - (lambda (p base e*) - (let loop ([e* e*] [n base] [nc* '()]) - (if (null? e*) - (if (and (fixnum? n) (fx= n base) (not (null? nc*))) - (values (car nc*) (cdr nc*) nc*) - (values `(immediate ,(fix n)) nc* nc*)) - (let ([e (car e*)]) - (if (fixnum-constant? e) - (let ([m (constant-value e)]) - (loop (cdr e*) (if n (p n m) m) nc*)) - (loop (cdr e*) n (cons e nc*)))))))) - (let () ; level 2 fxlogor, fxlogior, fxor - (define-syntax fxlogorop - (syntax-rules () - [(_ op) - (let () - (define (go src sexpr e*) - (and (fx<= (length e*) inline-args-limit) - (list-bind #t (e*) - (let-values ([(e e* nc*) (log-partition logor 0 e*)]) - (bind #t ([t (fold-left (lambda (e1 e2) (%inline logor ,e1 ,e2)) e e*)]) - `(if ,(%type-check mask-fixnum type-fixnum ,t) - ,t - ,(case (length nc*) - [(1) (build-libcall #t src sexpr op (car nc*) `(immediate ,(fix 0)))] - [(2) (build-libcall #t src sexpr op (car nc*) (cadr nc*))] - ; TODO: need fxargerr library routine w/who arg & rest interface - [else `(call ,(make-info-call src sexpr #f #t #t) #f ,(Symref 'op) ,nc* (... ...))]))))))) ; NB: should be error call---but is it? - (define-inline 2 op - [() `(immediate ,(fix 0))] - [e* (go src sexpr e*)]))])) - (fxlogorop fxlogor) - (fxlogorop fxlogior) - (fxlogorop fxior)) - (let () ; level 2 fxlogand, ... - (define-syntax fxlogop - (syntax-rules () - [(_ op inline-op base) - (define-inline 2 op - [() `(immediate ,(fix base))] - [e* (and (fx<= (length e*) (fx- inline-args-limit 1)) - (list-bind #t (e*) - ;; NB: using inline-op here because it works when target's - ;; NB: fixnum range is larger than the host's fixnum range - ;; NB: during cross compile - (let-values ([(e e* nc*) (log-partition inline-op base e*)]) - `(if ,(build-fixnums? nc*) - ,(fold-left (lambda (e1 e2) (%inline inline-op ,e1 ,e2)) e e*) - ; TODO: need fxargerr library routine w/who arg & rest interface - ,(case (length nc*) - [(1) (build-libcall #t src sexpr op (car nc*) `(immediate ,(fix 0)))] - [(2) (build-libcall #t src sexpr op (car nc*) (cadr nc*))] - ; TODO: need fxargerr library routine w/who arg & rest interface - [else `(call ,(make-info-call src sexpr #f #t #t) #f ,(Symref 'op) ,nc* (... ...))])))))])])) ; NB: should be error call---but is it? - (fxlogop fxlogand logand -1) - (fxlogop fxand logand -1) - (fxlogop fxlogxor logxor 0) - (fxlogop fxxor logxor 0))) - (define-inline 3 fxlogtest - [(e1 e2) (%inline logtest ,e1 ,e2)]) - (define-inline 2 fxlogtest - [(e1 e2) - (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(%inline logtest ,e1 ,e2) - ,(build-libcall #t src sexpr fxlogtest e1 e2)))]) - (let () - (define xorbits (lognot (constant mask-fixnum))) - (define-syntax fxlognotop - (syntax-rules () - [(_ name) - (begin - (define-inline 3 name - [(e) (%inline logxor ,e (immediate ,xorbits))]) - (define-inline 2 name - [(e) (bind #t (e) - `(if ,(%type-check mask-fixnum type-fixnum ,e) - ,(%inline logxor ,e (immediate ,xorbits)) - ,(build-libcall #t src sexpr name e)))]))])) - (fxlognotop fxlognot) - (fxlognotop fxnot)) - (define-inline 3 $fxu< - [(e1 e2) (or (relop-length RELOP< e1 e2) - (%inline u< ,e1 ,e2))]) - (define-inline 3 fx+ - [() `(immediate 0)] - [(e) e] - [(e1 e2) (%inline + ,e1 ,e2)] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - (define-inline 3 r6rs:fx+ ; limited to two arguments - [(e1 e2) (%inline + ,e1 ,e2)]) - (define-inline 3 fx1+ - [(e) (%inline + ,e (immediate ,(fix 1)))]) - (define-inline 2 $fx+? - [(e1 e2) - (let ([Lfalse (make-local-label 'Lfalse)]) - (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(bind #f ([t (%inline +/ovfl ,e1 ,e2)]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (label ,Lfalse ,(%constant sfalse)) - ,t)) - (goto ,Lfalse))))]) - (let () - (define (go src sexpr e1 e2) - (let ([Llib (make-local-label 'Llib)]) - (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(bind #f ([t (%inline +/ovfl ,e1 ,e2)]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (label ,Llib ,(build-libcall #t src sexpr fx+ e1 e2)) - ,t)) - (goto ,Llib))))) - (define-inline 2 fx+ - [() `(immediate 0)] - [(e) - (bind #t (e) - `(if ,(%type-check mask-fixnum type-fixnum ,e) - ,e - ,(build-libcall #t #f sexpr fx+ e `(immediate ,(fix 0)))))] - [(e1 e2) (go src sexpr e1 e2)] - ; TODO: 3-operand case requires 3-operand library routine - #;[(e1 e2 e3) - (let ([Llib (make-local-label 'Llib)]) - (bind #t (e1 e2 e3) - `(if ,(build-fixnums? (list e1 e2 e3)) - ,(bind #t ([t (%inline +/ovfl ,e1 ,e2)]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (label ,Llib ,(build-libcall #t src sexpr fx+ e1 e2 e3)) - ,(bind #t ([t (%inline +/ovfl ,t ,e3)]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (goto ,Llib) - ,t)))) - (goto ,Llib))))] - [(e1 . e*) #f]) - (define-inline 2 r6rs:fx+ ; limited to two arguments - [(e1 e2) (go src sexpr e1 e2)])) - - (define-inline 3 fx- - [(e) (%inline - (immediate 0) ,e)] - [(e1 e2) (%inline - ,e1 ,e2)] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - (define-inline 3 r6rs:fx- ; limited to one or two arguments - [(e) (%inline - (immediate 0) ,e)] - [(e1 e2) (%inline - ,e1 ,e2)]) - (define-inline 3 fx1- - [(e) (%inline - ,e (immediate ,(fix 1)))]) - (define-inline 2 $fx-? - [(e1 e2) - (let ([Lfalse (make-local-label 'Lfalse)]) - (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(bind #f ([t (%inline -/ovfl ,e1 ,e2)]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (label ,Lfalse ,(%constant sfalse)) - ,t)) - (goto ,Lfalse))))]) - (let () - (define (go src sexpr e1 e2) - (let ([Llib (make-local-label 'Llib)]) - (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(bind #t ([t (%inline -/ovfl ,e1 ,e2)]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (label ,Llib ,(build-libcall #t src sexpr fx- e1 e2)) - ,t)) - (goto ,Llib))))) - (define-inline 2 fx- - [(e) (go src sexpr `(immediate ,(fix 0)) e)] - [(e1 e2) (go src sexpr e1 e2)] - ; TODO: 3-operand case requires 3-operand library routine - #;[(e1 e2 e3) - (let ([Llib (make-local-label 'Llib)]) - (bind #t (e1 e2 e3) - `(if ,(build-fixnums? (list e1 e2 e3)) - ,(bind #t ([t (%inline -/ovfl ,e1 ,e2)]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (label ,Llib ,(build-libcall #t src sexpr fx- e1 e2 e3)) - ,(bind #t ([t (%inline -/ovfl ,t ,e3)]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (goto ,Llib) - ,t)))) - (goto ,Llib))))] - [(e1 . e*) #f]) - (define-inline 2 r6rs:fx- ; limited to one or two arguments - [(e) (go src sexpr `(immediate ,(fix 0)) e)] - [(e1 e2) (go src sexpr e1 e2)])) - (define-inline 2 fx1- - [(e) (let ([Llib (make-local-label 'Llib)]) - (bind #t (e) - `(if ,(build-fixnums? (list e)) - ,(bind #t ([t (%inline -/ovfl ,e (immediate ,(fix 1)))]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (label ,Llib ,(build-libcall #t src sexpr fx1- e)) - ,t)) - (goto ,Llib))))]) - (define-inline 2 fx1+ - [(e) (let ([Llib (make-local-label 'Llib)]) - (bind #t (e) - `(if ,(build-fixnums? (list e)) - ,(bind #f ([t (%inline +/ovfl ,e (immediate ,(fix 1)))]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (label ,Llib ,(build-libcall #t src sexpr fx1+ e)) - ,t)) - (goto ,Llib))))]) - - (let () - (define fixnum-powers-of-two - (let f ([m 2] [e 1]) - (if (<= m (constant most-positive-fixnum)) - (cons (cons m e) (f (* m 2) (fx+ e 1))) - '()))) - (define-inline 3 fxdiv - [(e1 e2) - (nanopass-case (L7 Expr) e2 - [(quote ,d) - (let ([a (assv d fixnum-powers-of-two)]) - (and a - (%inline logand - ,(%inline sra ,e1 (immediate ,(cdr a))) - (immediate ,(- (constant fixnum-factor))))))] - [else #f])]) - (define-inline 3 fxmod - [(e1 e2) - (nanopass-case (L7 Expr) e2 - [(quote ,d) - (let ([a (assv d fixnum-powers-of-two)]) - (and a (%inline logand ,e1 (immediate ,(fix (- d 1))))))] - [else #f])]) - (let () - (define (build-fx* e1 e2 ovfl?) - (define (fx*-constant e n) - (if ovfl? - (%inline */ovfl ,e (immediate ,n)) - (cond - [(eqv? n 1) e] - [(eqv? n -1) (%inline - (immediate 0) ,e)] - [(eqv? n 2) (%inline sll ,e (immediate 1))] - [(eqv? n 3) - (bind #t (e) - (%inline + - ,(%inline + ,e ,e) - ,e))] - [(eqv? n 10) - (bind #t (e) - (%inline + - ,(%inline + - ,(%inline sll ,e (immediate 3)) - ,e) - ,e))] - [(assv n fixnum-powers-of-two) => - (lambda (a) (%inline sll ,e (immediate ,(cdr a))))] - [else (%inline * ,e (immediate ,n))]))) - (nanopass-case (L7 Expr) e2 - [(quote ,d) (guard (target-fixnum? d)) (fx*-constant e1 d)] - [else - (nanopass-case (L7 Expr) e1 - [(quote ,d) (guard (target-fixnum? d)) (fx*-constant e2 d)] - [else - (let ([t (make-tmp 't 'uptr)]) - `(let ([,t ,(build-unfix e2)]) - ,(if ovfl? - (%inline */ovfl ,e1 ,t) - (%inline * ,e1 ,t))))])])) - (define-inline 3 fx* - [() `(immediate ,(fix 1))] - [(e) e] - [(e1 e2) (build-fx* e1 e2 #f)] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - (define-inline 3 r6rs:fx* ; limited to two arguments - [(e1 e2) (build-fx* e1 e2 #f)]) - (let () - (define (go src sexpr e1 e2) - (let ([Llib (make-local-label 'Llib)]) - (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(bind #t ([t (build-fx* e1 e2 #t)]) - `(if (inline ,(make-info-condition-code 'multiply-overflow #f #t) ,%condition-code) - (label ,Llib ,(build-libcall #t src sexpr fx* e1 e2)) - ,t)) - (goto ,Llib))))) - (define-inline 2 fx* - [() `(immediate ,(fix 1))] - [(e) - (bind #t (e) - `(if ,(%type-check mask-fixnum type-fixnum ,e) - ,e - ,(build-libcall #t src sexpr fx* e `(immediate ,(fix 0)))))] - [(e1 e2) (go src sexpr e1 e2)] - ; TODO: 3-operand case requires 3-operand library routine - #;[(e1 e2 e3) - (let ([Llib (make-local-label 'Llib)]) - (bind #t (e1 e2 e3) - `(if ,(build-fixnums? (list e1 e2 e3)) - ,(bind #t ([t (build-fx* e1 e2 #t)]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (label ,Llib ,(build-libcall #t src sexpr fx* e1 e2 e3)) - ,(bind #t ([t (build-fx* t e3 #t)]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (goto ,Llib) - ,t)))) - (goto ,Llib))))] - [(e1 . e*) #f]) - (define-inline 2 r6rs:fx* ; limited to two arguments - [(e1 e2) (go src sexpr e1 e2)])) - (let () - (define build-fx/p2 - (lambda (e1 p2) - (bind #t (e1) - (build-fix - (%inline sra - ,(%inline + ,e1 - ,(%inline srl - ,(if (fx= p2 1) - e1 - (%inline sra ,e1 (immediate ,(fx- p2 1)))) - (immediate ,(fx- (constant fixnum-bits) p2)))) - (immediate ,(fx+ p2 (constant fixnum-offset)))))))) - - (define build-fx/ - (lambda (src sexpr e1 e2) - (or (nanopass-case (L7 Expr) e2 - [(quote ,d) - (let ([a (assv d fixnum-powers-of-two)]) - (and a (build-fx/p2 e1 (cdr a))))] - [else #f]) - (if (constant integer-divide-instruction) - (build-fix (%inline / ,e1 ,e2)) - `(call ,(make-info-call src sexpr #f #f #f) #f - ,(lookup-primref 3 '$fx/) - ,e1 ,e2))))) - - (define-inline 3 fx/ - [(e) (build-fx/ src sexpr `(quote 1) e)] - [(e1 e2) (build-fx/ src sexpr e1 e2)] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - - (define-inline 3 fxquotient - [(e) (build-fx/ src sexpr `(quote 1) e)] - [(e1 e2) (build-fx/ src sexpr e1 e2)] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - - (define-inline 3 fxremainder - [(e1 e2) - (bind #t (e1 e2) - (%inline - ,e1 - ,(build-fx* - (build-fx/ src sexpr e1 e2) - e2 #f)))])))) - (let () - (define do-fxsll - (lambda (e1 e2) - (nanopass-case (L7 Expr) e2 - [(quote ,d) - (%inline sll ,e1 (immediate ,d))] - [else - ; TODO: bind-uptr might be handy here and also a make-unfix - (let ([t (make-tmp 't 'uptr)]) - `(let ([,t ,(build-unfix e2)]) - ,(%inline sll ,e1 ,t)))]))) - (define-inline 3 fxsll - [(e1 e2) (do-fxsll e1 e2)]) - (define-inline 3 fxarithmetic-shift-left - [(e1 e2) (do-fxsll e1 e2)])) - (define-inline 3 fxsrl - [(e1 e2) - (%inline logand - ,(nanopass-case (L7 Expr) e2 - [(quote ,d) - (%inline srl ,e1 (immediate ,d))] - [else - (let ([t (make-tmp 't 'uptr)]) - `(let ([,t ,(build-unfix e2)]) - ,(%inline srl ,e1 ,t)))]) - (immediate ,(fx- (constant fixnum-factor))))]) - (let () - (define do-fxsra - (lambda (e1 e2) - (%inline logand - ,(nanopass-case (L7 Expr) e2 - [(quote ,d) - (%inline sra ,e1 (immediate ,d))] - [else - (let ([t (make-tmp 't 'uptr)]) - `(let ([,t ,(build-unfix e2)]) - ,(%inline sra ,e1 ,t)))]) - (immediate ,(fx- (constant fixnum-factor)))))) - (define-inline 3 fxsra - [(e1 e2) (do-fxsra e1 e2)]) - (define-inline 3 fxarithmetic-shift-right - [(e1 e2) (do-fxsra e1 e2)])) - (let () - (define-syntax %safe-shift - (syntax-rules () - [(_ src sexpr op libcall e1 e2 ?size) - (let ([size ?size]) - (if (constant? (lambda (x) (and (fixnum? x) (fx<= 0 x (fx- size 1)))) e2) - (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1)) - ,(%inline logand - ,(%inline op ,e1 (immediate ,(constant-value e2))) - (immediate ,(- (constant fixnum-factor)))) - ,(build-libcall #t src sexpr libcall e1 e2))) - (bind #t (e1 e2) - `(if ,(build-and - (build-fixnums? (list e1 e2)) - (%inline u< ,e2 (immediate ,(fix size)))) - ,(%inline logand - ,(%inline op ,e1 ,(build-unfix e2)) - (immediate ,(- (constant fixnum-factor)))) - ,(build-libcall #t src sexpr libcall e1 e2)))))])) - (define-inline 2 fxsrl - [(e1 e2) (%safe-shift src sexpr srl fxsrl e1 e2 (+ (constant fixnum-bits) 1))]) - (define-inline 2 fxsra - [(e1 e2) (%safe-shift src sexpr sra fxsra e1 e2 (+ (constant fixnum-bits) 1))]) - (define-inline 2 fxarithmetic-shift-right - [(e1 e2) (%safe-shift src sexpr sra fxarithmetic-shift-right e1 e2 (constant fixnum-bits))])) - (define-inline 3 fxarithmetic-shift - [(e1 e2) - (or (nanopass-case (L7 Expr) e2 - [(quote ,d) - (and (fixnum? d) - (if ($fxu< d (constant fixnum-bits)) - (%inline sll ,e1 (immediate ,d)) - (and (fx< (fx- (constant fixnum-bits)) d 0) - (%inline logand - ,(%inline sra ,e1 (immediate ,(fx- d))) - (immediate ,(- (constant fixnum-factor)))))))] - [else #f]) - (build-libcall #f src sexpr fxarithmetic-shift e1 e2))]) - (define-inline 2 fxarithmetic-shift - [(e1 e2) - (or (nanopass-case (L7 Expr) e2 - [(quote ,d) - (guard (fixnum? d) (fx< (fx- (constant fixnum-bits)) d 0)) - (bind #t (e1) - `(if ,(build-fixnums? (list e1)) - ,(%inline logand - ,(%inline sra ,e1 (immediate ,(fx- d))) - (immediate ,(- (constant fixnum-factor)))) - ,(build-libcall #t src sexpr fxarithmetic-shift e1 e2)))] - [else #f]) - (build-libcall #f src sexpr fxarithmetic-shift e1 e2))]) - (let () - (define dofxlogbit0 - (lambda (e1 e2) - (if (constant? (lambda (x) (and (fixnum? x) ($fxu< x (fx- (constant fixnum-bits) 1)))) e2) - (%inline logand ,e1 - (immediate ,(fix (lognot (ash 1 (constant-value e2)))))) - (%inline logand ,e1 - ,(%inline lognot - ,(%inline sll (immediate ,(fix 1)) - ,(build-unfix e2))))))) - (define dofxlogbit1 - (lambda (e1 e2) - (if (constant? (lambda (x) (and (fixnum? x) ($fxu< x (fx- (constant fixnum-bits) 1)))) e2) - (%inline logor ,e1 - (immediate ,(fix (ash 1 (constant-value e2))))) - (%inline logor ,e1 - ,(%inline sll (immediate ,(fix 1)) - ,(build-unfix e2)))))) - (define-inline 3 fxlogbit0 - [(e1 e2) (dofxlogbit0 e2 e1)]) - (define-inline 3 fxlogbit1 - [(e1 e2) (dofxlogbit1 e2 e1)]) - (define-inline 3 fxcopy-bit - [(e1 e2 e3) - (and (fixnum-constant? e3) - (case (constant-value e3) - [(0) (dofxlogbit0 e1 e2)] - [(1) (dofxlogbit1 e1 e2)] - [else #f]))])) - (let () - (define dofxlogbit0 - (lambda (e1 e2 libcall) - (if (constant? (lambda (x) (and (fixnum? x) ($fxu< x (fx- (constant fixnum-bits) 1)))) e2) - (bind #t (e1) - `(if ,(build-fixnums? (list e1)) - ,(%inline logand ,e1 - (immediate ,(fix (lognot (ash 1 (constant-value e2)))))) - ,(libcall e1 e2))) - (bind #t (e1 e2) - `(if ,(build-and - (build-fixnums? (list e1 e2)) - (%inline u< ,e2 (immediate ,(fix (fx- (constant fixnum-bits) 1))))) - ,(%inline logand ,e1 - ,(%inline lognot - ,(%inline sll (immediate ,(fix 1)) - ,(build-unfix e2)))) - ,(libcall e1 e2)))))) - (define dofxlogbit1 - (lambda (e1 e2 libcall) - (if (constant? (lambda (x) (and (fixnum? x) ($fxu< x (fx- (constant fixnum-bits) 1)))) e2) - (bind #t (e1) - `(if ,(build-fixnums? (list e1)) - ,(%inline logor ,e1 - (immediate ,(fix (ash 1 (constant-value e2))))) - ,(libcall e1 e2))) - (bind #t (e1 e2) - `(if ,(build-and - (build-fixnums? (list e1 e2)) - (%inline u< ,e2 (immediate ,(fix (fx- (constant fixnum-bits) 1))))) - ,(%inline logor ,e1 - ,(%inline sll (immediate ,(fix 1)) - ,(build-unfix e2))) - ,(libcall e1 e2)))))) - (define-inline 2 fxlogbit0 - [(e1 e2) (dofxlogbit0 e2 e1 - (lambda (e2 e1) - (build-libcall #t src sexpr fxlogbit0 e1 e2)))]) - (define-inline 2 fxlogbit1 - [(e1 e2) (dofxlogbit1 e2 e1 - (lambda (e2 e1) - (build-libcall #t src sexpr fxlogbit1 e1 e2)))]) - (define-inline 2 fxcopy-bit - [(e1 e2 e3) - (and (fixnum-constant? e3) - (case (constant-value e3) - [(0) (dofxlogbit0 e1 e2 - (lambda (e1 e2) - (build-libcall #t src sexpr fxcopy-bit e1 e2)))] - [(1) (dofxlogbit1 e1 e2 - (lambda (e1 e2) - (build-libcall #t src sexpr fxcopy-bit e1 e2)))] - [else #f]))])) - (define-inline 3 fxzero? - [(e) (or (relop-length RELOP= e) (%inline eq? ,e (immediate 0)))]) - (define-inline 3 fxpositive? - [(e) (or (relop-length RELOP> e) (%inline > ,e (immediate 0)))]) - (define-inline 3 fxnonnegative? - [(e) (or (relop-length RELOP>= e) (%inline >= ,e (immediate 0)))]) - (define-inline 3 fxnegative? - [(e) (or (relop-length RELOP< e) (%inline < ,e (immediate 0)))]) - (define-inline 3 fxnonpositive? - [(e) (or (relop-length RELOP<= e) (%inline <= ,e (immediate 0)))]) - (define-inline 3 fxeven? - [(e) (%inline eq? - ,(%inline logand ,e (immediate ,(fix 1))) - (immediate ,(fix 0)))]) - (define-inline 3 fxodd? - [(e) (%inline eq? - ,(%inline logand ,e (immediate ,(fix 1))) - (immediate ,(fix 1)))]) - - (define-inline 2 fxzero? - [(e) (or (relop-length RELOP= e) - (bind #t (e) - (build-simple-or - (%inline eq? ,e (immediate 0)) - `(if ,(build-fixnums? (list e)) - ,(%constant sfalse) - ,(build-libcall #t src sexpr fxzero? e)))))]) - (define-inline 2 fxpositive? - [(e) (or (relop-length RELOP> e) - (bind #t (e) - `(if ,(build-fixnums? (list e)) - ,(%inline > ,e (immediate 0)) - ,(build-libcall #t src sexpr fxpositive? e))))]) - (define-inline 2 fxnonnegative? - [(e) (or (relop-length RELOP>= e) - (bind #t (e) - `(if ,(build-fixnums? (list e)) - ,(%inline >= ,e (immediate 0)) - ,(build-libcall #t src sexpr fxnonnegative? e))))]) - (define-inline 2 fxnegative? - [(e) (or (relop-length RELOP< e) - (bind #t (e) - `(if ,(build-fixnums? (list e)) - ,(%inline < ,e (immediate 0)) - ,(build-libcall #t src sexpr fxnegative? e))))]) - (define-inline 2 fxnonpositive? - [(e) (or (relop-length RELOP<= e) - (bind #t (e) - `(if ,(build-fixnums? (list e)) - ,(%inline <= ,e (immediate 0)) - ,(build-libcall #t src sexpr fxnonpositive? e))))]) - (define-inline 2 fxeven? - [(e) (bind #t (e) - `(if ,(build-fixnums? (list e)) - ,(%inline eq? - ,(%inline logand ,e (immediate ,(fix 1))) - (immediate ,(fix 0))) - ,(build-libcall #t src sexpr fxeven? e)))]) - (define-inline 2 fxodd? - [(e) (bind #t (e) - `(if ,(build-fixnums? (list e)) - ,(%inline eq? - ,(%inline logand ,e (immediate ,(fix 1))) - (immediate ,(fix 1))) - ,(build-libcall #t src sexpr fxodd? e)))]) - (let () - (define dofxlogbit? - (lambda (e1 e2) - (cond - [(constant? (lambda (x) (and (fixnum? x) (fx<= 0 x (fx- (constant fixnum-bits) 2)))) e1) - (%inline logtest ,e2 (immediate ,(fix (ash 1 (constant-value e1)))))] - [(constant? (lambda (x) (and (target-fixnum? x) (> x (fx- (constant fixnum-bits) 2)))) e1) - (%inline < ,e2 (immediate ,(fix 0)))] - [(fixnum-constant? e2) - (bind #t (e1) - `(if ,(%inline < (immediate ,(fix (fx- (constant fixnum-bits) 2))) ,e1) - ,(if (< (constant-value e2) 0) (%constant strue) (%constant sfalse)) - ,(%inline logtest - ,(%inline sra ,e2 ,(build-unfix e1)) - (immediate ,(fix 1)))))] - [else - (bind #t (e1 e2) - `(if ,(%inline < (immediate ,(fix (fx- (constant fixnum-bits) 2))) ,e1) - ,(%inline < ,e2 (immediate ,(fix 0))) - ,(%inline logtest - ,(%inline sra ,e2 ,(build-unfix e1)) - (immediate ,(fix 1)))))]))) - - (define-inline 3 fxbit-set? - [(e1 e2) (dofxlogbit? e2 e1)]) - - (define-inline 3 fxlogbit? - [(e1 e2) (dofxlogbit? e1 e2)])) - - (let () - (define dofxlogbit? - (lambda (e1 e2 libcall) - (cond - [(constant? (lambda (x) (and (fixnum? x) (fx<= 0 x (fx- (constant fixnum-bits) 2)))) e1) - (bind #t (e2) - `(if ,(build-fixnums? (list e2)) - ,(%inline logtest ,e2 - (immediate ,(fix (ash 1 (constant-value e1))))) - ,(libcall e1 e2)))] - [(constant? (lambda (x) (and (target-fixnum? x) (> x (fx- (constant fixnum-bits) 2)))) e1) - (bind #t (e2) - `(if ,(build-fixnums? (list e2)) - ,(%inline < ,e2 (immediate ,(fix 0))) - ,(libcall e1 e2)))] - [else - (bind #t (e1 e2) - `(if ,(build-and - (build-fixnums? (list e1 e2)) - (%inline u< ,e1 (immediate ,(fix (constant fixnum-bits))))) - ,(%inline logtest - ,(%inline sra ,e2 ,(build-unfix e1)) - (immediate ,(fix 1))) - ,(libcall e1 e2)))]))) - - (define-inline 2 fxbit-set? - [(e1 e2) (dofxlogbit? e2 e1 - (lambda (e2 e1) - (build-libcall #t src sexpr fxbit-set? e1 e2)))]) - (define-inline 2 fxlogbit? - [(e1 e2) (dofxlogbit? e1 e2 - (lambda (e1 e2) - (build-libcall #t src sexpr fxlogbit? e1 e2)))])) - - ; can avoid if in fxabs with: - ; t = sra(x, k) ; where k is ptr-bits - 1 - ; ; t is now -1 if x's sign bit set, otherwise 0 - ; x = xor(x, t) ; logical not if x negative, otherwise leave x alone - ; x = x - t ; add 1 to complete two's complement negation if - ; ; x was negative, otherwise leave x alone - ; tests on i3le indicate that the if is actually faster, even in a loop - ; where input alternates between positive and negative to defeat branch - ; prediction. - (define-inline 3 fxabs - [(e) (bind #t (e) - `(if ,(%inline < ,e (immediate ,(fix 0))) - ,(%inline - (immediate ,(fix 0)) ,e) - ,e))]) - - ;(define-inline 3 min ; needs library min - ; ; must take care to be inexactness-preserving - ; [(e0) e0] - ; [(e0 e1) - ; (bind #t (e0 e1) - ; `(if ,(build-fixnums? (list e0 e1)) - ; (if ,(%inline < ,e0 ,e1) ,e0 ,e1) - ; ,(build-libcall #t src sexpr min e0 e1)))] - ; [(e0 . e*) (reduce src sexpr moi e1 e*)]) - ; - ;(define-inline 3 max ; needs library max - ; ; must take care to be inexactness-preserving - ; [(e0) e0] - ; [(e0 e1) - ; (bind #t (e0 e1) - ; `(if ,(build-fixnums? (list e0 e1)) - ; (if ,(%inline < ,e0 ,e1) ,e0 ,e1) - ; ,(build-libcall #t src sexpr max e0 e1)))] - ; [(e1 . e*) (reduce src sexpr moi e1 e*)]) - - (define-inline 3 fxmin - [(e) e] - [(e1 e2) (bind #t (e1 e2) - `(if ,(%inline < ,e1 ,e2) - ,e1 - ,e2))] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - - (define-inline 3 fxmax - [(e) e] - [(e1 e2) (bind #t (e1 e2) - `(if ,(%inline < ,e2 ,e1) - ,e1 - ,e2))] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - - (define-inline 3 fxif - [(e1 e2 e3) - (bind #t (e1) - (%inline logor - ,(%inline logand ,e2 ,e1) - ,(%inline logand ,e3 - ,(%inline lognot ,e1))))]) - - (define-inline 3 fxbit-field - [(e1 e2 e3) - (and (constant? fixnum? e2) (constant? fixnum? e3) - (let ([start (constant-value e2)] [end (constant-value e3)]) - (if (fx= end start) - (%seq ,e1 (immediate ,(fix 0))) - (and (and (fx>= start 0) (fx> end start) (fx< end (constant fixnum-bits))) - (extract-unsigned-bitfield #f start end e1)))))]) - - (define-inline 3 fxcopy-bit-field - [(e1 e2 e3 e4) - (and (constant? fixnum? e2) (constant? fixnum? e3) - (let ([start (constant-value e2)] [end (constant-value e3)]) - (if (fx= end start) - e1 - (and (and (fx>= start 0) (fx> end start) (fx< end (constant fixnum-bits))) - (insert-bitfield #f start end (constant fixnum-bits) e1 e4)))))]) - - ;; could be done with one mutable variable instead of two, but this seems to generate - ;; the same code as the existing compiler - (define-inline 3 fxlength - [(e) - (let ([t (make-assigned-tmp 't 'uptr)] [result (make-assigned-tmp 'result)]) - `(let ([,t ,(build-unfix e)]) - (seq - (if ,(%inline < ,t (immediate 0)) - (set! ,t ,(%inline lognot ,t)) - ,(%constant svoid)) - (let ([,result (immediate ,(fix 0))]) - ,((lambda (body) - (constant-case fixnum-bits - [(30) body] - [(61) - `(seq - (if ,(%inline < ,t (immediate #x100000000)) - ,(%constant svoid) - (seq - (set! ,t ,(%inline srl ,t (immediate 32))) - (set! ,result - ,(%inline + ,result (immediate ,(fix 32)))))) - ,body)])) - (%seq - (if ,(%inline < ,t (immediate #x10000)) - ,(%constant svoid) - (seq - (set! ,t ,(%inline srl ,t (immediate 16))) - (set! ,result ,(%inline + ,result (immediate ,(fix 16)))))) - (if ,(%inline < ,t (immediate #x100)) - ,(%constant svoid) - (seq - (set! ,t ,(%inline srl ,t (immediate 8))) - (set! ,result ,(%inline + ,result (immediate ,(fix 8)))))) - ,(%inline + ,result - (inline ,(make-info-load 'unsigned-8 #f) ,%load - ,(%tc-ref fxlength-bv) ,t - ,(%constant bytevector-data-disp)))))))))]) - - (define-inline 3 fxfirst-bit-set - [(e) - (let ([t (make-assigned-tmp 't 'uptr)] [result (make-assigned-tmp 'result)]) - (bind #t (e) - `(if ,(%inline eq? ,e (immediate ,(fix 0))) - (immediate ,(fix -1)) - (let ([,t ,(build-unfix e)] [,result (immediate ,(fix 0))]) - ,((lambda (body) - (constant-case fixnum-bits - [(30) body] - [(61) - `(seq - (if ,(%inline logtest ,t (immediate #xffffffff)) - ,(%constant svoid) - (seq - (set! ,t ,(%inline srl ,t (immediate 32))) - (set! ,result ,(%inline + ,result (immediate ,(fix 32)))))) - ,body)])) - (%seq - (if ,(%inline logtest ,t (immediate #xffff)) - ,(%constant svoid) - (seq - (set! ,t ,(%inline srl ,t (immediate 16))) - (set! ,result ,(%inline + ,result (immediate ,(fix 16)))))) - (if ,(%inline logtest ,t (immediate #xff)) - ,(%constant svoid) - (seq - (set! ,t ,(%inline srl ,t (immediate 8))) - (set! ,result ,(%inline + ,result (immediate ,(fix 8)))))) - ,(%inline + ,result - (inline ,(make-info-load 'unsigned-8 #f) ,%load - ,(%tc-ref fxfirst-bit-set-bv) - ,(%inline logand ,t (immediate #xff)) - ,(%constant bytevector-data-disp)))))))))]) - - (let () - (define-syntax type-pred - (syntax-rules () - [(_ name? mask type) - (define-inline 2 name? - [(e) (%type-check mask type ,e)])])) - (define-syntax typed-object-pred - (syntax-rules () - [(_ name? mask type) - (define-inline 2 name? - [(e) - (bind #t (e) - (%typed-object-check mask type ,e))])])) - (type-pred boolean? mask-boolean type-boolean) - (type-pred bwp-object? mask-bwp sbwp) - (type-pred char? mask-char type-char) - (type-pred eof-object? mask-eof seof) - (type-pred fixnum? mask-fixnum type-fixnum) - (type-pred flonum? mask-flonum type-flonum) - (type-pred null? mask-nil snil) - (type-pred pair? mask-pair type-pair) - (type-pred procedure? mask-closure type-closure) - (type-pred symbol? mask-symbol type-symbol) - (type-pred $unbound-object? mask-unbound sunbound) - (typed-object-pred bignum? mask-bignum type-bignum) - (typed-object-pred box? mask-box type-box) - (typed-object-pred mutable-box? mask-mutable-box type-mutable-box) - (typed-object-pred immutable-box? mask-mutable-box type-immutable-box) - (typed-object-pred bytevector? mask-bytevector type-bytevector) - (typed-object-pred mutable-bytevector? mask-mutable-bytevector type-mutable-bytevector) - (typed-object-pred immutable-bytevector? mask-mutable-bytevector type-immutable-bytevector) - (typed-object-pred $code? mask-code type-code) - (typed-object-pred $exactnum? mask-exactnum type-exactnum) - (typed-object-pred fxvector? mask-fxvector type-fxvector) - (typed-object-pred mutable-fxvector? mask-mutable-fxvector type-mutable-fxvector) - (typed-object-pred immutable-fxvector? mask-mutable-fxvector type-immutable-fxvector) - (typed-object-pred $inexactnum? mask-inexactnum type-inexactnum) - (typed-object-pred $rtd-counts? mask-rtd-counts type-rtd-counts) - (typed-object-pred input-port? mask-input-port type-input-port) - (typed-object-pred output-port? mask-output-port type-output-port) - (typed-object-pred port? mask-port type-port) - (typed-object-pred ratnum? mask-ratnum type-ratnum) - (typed-object-pred $record? mask-record type-record) - (typed-object-pred string? mask-string type-string) - (typed-object-pred mutable-string? mask-mutable-string type-mutable-string) - (typed-object-pred immutable-string? mask-mutable-string type-immutable-string) - (typed-object-pred $system-code? mask-system-code type-system-code) - (typed-object-pred $tlc? mask-tlc type-tlc) - (typed-object-pred vector? mask-vector type-vector) - (typed-object-pred mutable-vector? mask-mutable-vector type-mutable-vector) - (typed-object-pred immutable-vector? mask-mutable-vector type-immutable-vector) - (typed-object-pred thread? mask-thread type-thread)) - (define-inline 3 $bigpositive? - [(e) (%type-check mask-signed-bignum type-positive-bignum - ,(%mref ,e ,(constant bignum-type-disp)))]) - (define-inline 3 csv7:record-field-accessible? - [(e1 e2) (%seq ,e1 ,e2 ,(%constant strue))]) - - (define-inline 2 cflonum? - [(e) (bind #t (e) - `(if ,(%type-check mask-flonum type-flonum ,e) - ,(%constant strue) - ,(%typed-object-check mask-inexactnum type-inexactnum ,e)))]) - (define-inline 2 $immediate? - [(e) (bind #t (e) - `(if ,(%type-check mask-fixnum type-fixnum ,e) - ,(%constant strue) - ,(%type-check mask-immediate type-immediate ,e)))]) - - (define-inline 3 $inexactnum-real-part - [(e) (build-$inexactnum-real-part e)]) - (define-inline 3 $inexactnum-imag-part - [(e) (build-$inexactnum-imag-part e)]) - - (define-inline 3 cfl-real-part - [(e) (bind #t (e) - `(if ,(%type-check mask-flonum type-flonum ,e) - ,e - ,(build-$inexactnum-real-part e)))]) - - (define-inline 3 cfl-imag-part - [(e) (bind #t (e) - `(if ,(%type-check mask-flonum type-flonum ,e) - (quote 0.0) - ,(build-$inexactnum-imag-part e)))]) - - (define-inline 3 $closure-ref - [(e-v e-i) - (nanopass-case (L7 Expr) e-i - [(quote ,d) - (guard (target-fixnum? d)) - (%mref ,e-v ,(+ (fix d) (constant closure-data-disp)))] - [else (%mref ,e-v ,e-i ,(constant closure-data-disp))])]) - (define-inline 3 $closure-code - [(e) (%inline - - ,(%mref ,e ,(constant closure-code-disp)) - ,(%constant code-data-disp))]) - (define-inline 3 $code-free-count - [(e) (build-fix (%mref ,e ,(constant code-closure-length-disp)))]) - (define-inline 2 $unbound-object - [() `(quote ,($unbound-object))]) - (define-inline 2 void - [() `(quote ,(void))]) - (define-inline 2 eof-object - [() `(quote #!eof)]) - (define-inline 2 cons - [(e1 e2) - (bind #f (e1 e2) - (bind #t ([t (%constant-alloc type-pair (constant size-pair))]) - (%seq - (set! ,(%mref ,t ,(constant pair-car-disp)) ,e1) - (set! ,(%mref ,t ,(constant pair-cdr-disp)) ,e2) - ,t)))]) - (define-inline 2 box - [(e) - (bind #f (e) - (bind #t ([t (%constant-alloc type-typed-object (constant size-box))]) - (%seq - (set! ,(%mref ,t ,(constant box-type-disp)) ,(%constant type-box)) - (set! ,(%mref ,t ,(constant box-ref-disp)) ,e) - ,t)))]) - (define-inline 2 box-immutable - [(e) - (bind #f (e) - (bind #t ([t (%constant-alloc type-typed-object (constant size-box))]) - (%seq - (set! ,(%mref ,t ,(constant box-type-disp)) ,(%constant type-immutable-box)) - (set! ,(%mref ,t ,(constant box-ref-disp)) ,e) - ,t)))]) - (define-inline 3 $make-tlc - [(e-ht e-keyval e-next) - (bind #f (e-ht e-keyval e-next) - (bind #t ([t (%constant-alloc type-typed-object (constant size-tlc))]) - (%seq - (set! ,(%mref ,t ,(constant tlc-type-disp)) ,(%constant type-tlc)) - (set! ,(%mref ,t ,(constant tlc-ht-disp)) ,e-ht) - (set! ,(%mref ,t ,(constant tlc-keyval-disp)) ,e-keyval) - (set! ,(%mref ,t ,(constant tlc-next-disp)) ,e-next) - ,t)))]) - (define-inline 2 list - [e* (build-list e*)]) - (let () - (define (go e e*) - (bind #f (e) - (list-bind #f (e*) - (bind #t ([t (%constant-alloc type-pair (fx* (constant size-pair) (length e*)))]) - (let loop ([e e] [e* e*] [i 0]) - (let ([e2 (car e*)] [e* (cdr e*)]) - `(seq - (set! ,(%mref ,t ,(fx+ i (constant pair-car-disp))) ,e) - ,(if (null? e*) - `(seq - (set! ,(%mref ,t ,(fx+ i (constant pair-cdr-disp))) ,e2) - ,t) - (let ([next-i (fx+ i (constant size-pair))]) - `(seq - (set! ,(%mref ,t ,(fx+ i (constant pair-cdr-disp))) - ,(%inline + ,t (immediate ,next-i))) - ,(loop e2 e* next-i))))))))))) - (define-inline 2 list* - [(e) e] - [(e . e*) (go e e*)]) - (define-inline 2 cons* - [(e) e] - [(e . e*) (go e e*)])) - (define-inline 2 vector - [() `(quote #())] - [e* - (let ([n (length e*)]) - (list-bind #f (e*) - (bind #t ([t (%constant-alloc type-typed-object - (fx+ (constant header-size-vector) (fx* n (constant ptr-bytes))))]) - (let loop ([e* e*] [i 0]) - (if (null? e*) - `(seq - (set! ,(%mref ,t ,(constant vector-type-disp)) - (immediate ,(+ (fx* n (constant vector-length-factor)) - (constant type-vector)))) - ,t) - `(seq - (set! ,(%mref ,t ,(fx+ i (constant vector-data-disp))) ,(car e*)) - ,(loop (cdr e*) (fx+ i (constant ptr-bytes)))))))))]) - (let () - (define (go e*) - (let ([n (length e*)]) - (list-bind #f (e*) - (bind #t ([t (%constant-alloc type-typed-object - (fx+ (constant header-size-fxvector) (fx* n (constant ptr-bytes))))]) - (let loop ([e* e*] [i 0]) - (if (null? e*) - `(seq - (set! ,(%mref ,t ,(constant fxvector-type-disp)) - (immediate ,(+ (fx* n (constant fxvector-length-factor)) - (constant type-fxvector)))) - ,t) - `(seq - (set! ,(%mref ,t ,(fx+ i (constant fxvector-data-disp))) ,(car e*)) - ,(loop (cdr e*) (fx+ i (constant ptr-bytes)))))))))) - (define-inline 2 fxvector - [() `(quote #vfx())] - [e* (and (andmap (lambda (x) (constant? target-fixnum? x)) e*) (go e*))]) - (define-inline 3 fxvector - [() `(quote #vfx())] - [e* (go e*)])) - (let () - (define (go e*) - (let ([n (length e*)]) - (list-bind #f (e*) - (bind #t ([t (%constant-alloc type-typed-object - (fx+ (constant header-size-string) (fx* n (constant string-char-bytes))))]) - (let loop ([e* e*] [i 0]) - (if (null? e*) - `(seq - (set! ,(%mref ,t ,(constant string-type-disp)) - (immediate ,(+ (fx* n (constant string-length-factor)) - (constant type-string)))) - ,t) - `(seq - (inline ,(make-info-load (string-char-type) #f) ,%store ,t ,%zero - (immediate ,(fx+ i (constant string-data-disp))) - ,(car e*)) - ,(loop (cdr e*) (fx+ i (constant string-char-bytes)))))))))) - (define-inline 2 string - [() `(quote "")] - [e* (and (andmap (lambda (x) (constant? char? x)) e*) (go e*))]) - (define-inline 3 string - [() `(quote "")] - [e* (go e*)])) - (let () ; level 2 car, cdr, caar, etc. - (define-syntax def-c..r* - (lambda (x) - (define (go ad*) - (let ([id (datum->syntax #'* (string->symbol (format "c~{~a~}r" ad*)))]) - #`(define-inline 2 #,id - [(e) (let ([Lerr (make-local-label 'Lerr)]) - #,(let f ([ad* ad*]) - (let ([builder (if (char=? (car ad*) #\a) #'build-car #'build-cdr)] - [ad* (cdr ad*)]) - (if (null? ad*) - #`(bind #t (e) - `(if ,(build-pair? e) - ,(#,builder e) - (label ,Lerr ,(build-libcall #t src sexpr #,id e)))) - #`(bind #t ([t #,(f ad*)]) - `(if ,(build-pair? t) - ,(#,builder t) - (goto ,Lerr)))))))]))) - (let f ([n 4] [ad* '()]) - (let ([f (lambda (ad*) - (let ([defn (go ad*)]) - (if (fx= n 1) - defn - #`(begin #,defn #,(f (fx- n 1) ad*)))))]) - #`(begin - #,(f (cons #\a ad*)) - #,(f (cons #\d ad*))))))) - def-c..r*) - (let () ; level 3 car, cdr, caar, etc. - (define-syntax def-c..r* - (lambda (x) - (define (go ad*) - (let ([id (datum->syntax #'* (string->symbol (format "c~{~a~}r" ad*)))]) - #`(define-inline 3 #,id - [(e) #,(let f ([ad* ad*]) - (let ([builder (if (char=? (car ad*) #\a) #'build-car #'build-cdr)] - [ad* (cdr ad*)]) - (if (null? ad*) - #`(#,builder e) - #`(#,builder #,(f ad*)))))]))) - (let f ([n 4] [ad* '()]) - (let ([f (lambda (ad*) - (let ([defn (go ad*)]) - (if (fx= n 1) - defn - #`(begin #,defn #,(f (fx- n 1) ad*)))))]) - #`(begin - #,(f (cons #\a ad*)) - #,(f (cons #\d ad*))))))) - def-c..r*) - (let () ; level 3 simple accessors, e.g., unbox, vector-length - (define-syntax inline-accessor - (syntax-rules () - [(_ prim disp) - (define-inline 3 prim - [(e) (%mref ,e ,(constant disp))])])) - (inline-accessor unbox box-ref-disp) - (inline-accessor $symbol-name symbol-name-disp) - (inline-accessor $symbol-property-list symbol-plist-disp) - (inline-accessor $system-property-list symbol-splist-disp) - (inline-accessor $symbol-hash symbol-hash-disp) - (inline-accessor $ratio-numerator ratnum-numerator-disp) - (inline-accessor $ratio-denominator ratnum-denominator-disp) - (inline-accessor $exactnum-real-part exactnum-real-disp) - (inline-accessor $exactnum-imag-part exactnum-imag-disp) - (inline-accessor binary-port-input-buffer port-ibuffer-disp) - (inline-accessor textual-port-input-buffer port-ibuffer-disp) - (inline-accessor binary-port-output-buffer port-obuffer-disp) - (inline-accessor textual-port-output-buffer port-obuffer-disp) - (inline-accessor $code-name code-name-disp) - (inline-accessor $code-arity-mask code-arity-mask-disp) - (inline-accessor $code-info code-info-disp) - (inline-accessor $code-pinfo* code-pinfo*-disp) - (inline-accessor $continuation-link continuation-link-disp) - (inline-accessor $continuation-winders continuation-winders-disp) - (inline-accessor csv7:record-type-descriptor record-type-disp) - (inline-accessor $record-type-descriptor record-type-disp) - (inline-accessor record-rtd record-type-disp) - (inline-accessor $port-handler port-handler-disp) - (inline-accessor $port-info port-info-disp) - (inline-accessor port-name port-name-disp) - (inline-accessor $thread-tc thread-tc-disp) - ) - (define-inline 2 unbox - [(e) - (bind #t (e) - `(if ,(%typed-object-check mask-box type-box ,e) - ,(%mref ,e ,(constant box-ref-disp)) - ,(build-libcall #t src sexpr unbox e)))]) - (let () - (define-syntax def-len - (syntax-rules () - [(_ prim type-disp length-offset) - (define-inline 3 prim - [(e) (extract-length (%mref ,e ,(constant type-disp)) (constant length-offset))])])) - (def-len vector-length vector-type-disp vector-length-offset) - (def-len fxvector-length fxvector-type-disp fxvector-length-offset) - (def-len string-length string-type-disp string-length-offset) - (def-len bytevector-length bytevector-type-disp bytevector-length-offset) - (def-len $bignum-length bignum-type-disp bignum-length-offset)) - (let () - (define-syntax def-len - (syntax-rules () - [(_ prim mask type type-disp length-offset) - (define-inline 2 prim - [(e) (let ([Lerr (make-local-label 'Lerr)]) - (bind #t (e) - `(if ,(%type-check mask-typed-object type-typed-object ,e) - ,(bind #t ([t/l (%mref ,e ,(constant type-disp))]) - `(if ,(%type-check mask type ,t/l) - ,(extract-length t/l (constant length-offset)) - (goto ,Lerr))) - (label ,Lerr ,(build-libcall #t #f sexpr prim e)))))])])) - (def-len vector-length mask-vector type-vector vector-type-disp vector-length-offset) - (def-len fxvector-length mask-fxvector type-fxvector fxvector-type-disp fxvector-length-offset) - (def-len string-length mask-string type-string string-type-disp string-length-offset) - (def-len bytevector-length mask-bytevector type-bytevector bytevector-type-disp bytevector-length-offset)) - ; TODO: consider adding integer-valued?, rational?, rational-valued?, - ; real?, and real-valued? - (define-inline 2 integer? - [(e) (bind #t (e) - (build-simple-or - (%type-check mask-fixnum type-fixnum ,e) - (build-simple-or - (%typed-object-check mask-bignum type-bignum ,e) - (build-and - (%type-check mask-flonum type-flonum ,e) - `(call ,(make-info-call src sexpr #f #f #f) #f ,(lookup-primref 3 'flinteger?) ,e)))))]) - (let () - (define build-number? - (lambda (e) - (bind #t (e) - (build-simple-or - (%type-check mask-fixnum type-fixnum ,e) - (build-simple-or - (%type-check mask-flonum type-flonum ,e) - (build-and - (%type-check mask-typed-object type-typed-object ,e) - (%type-check mask-other-number type-other-number - ,(%mref ,e ,(constant bignum-type-disp))))))))) - (define-inline 2 number? - [(e) (build-number? e)]) - (define-inline 2 complex? - [(e) (build-number? e)])) - (define-inline 3 set-car! - [(e1 e2) (build-dirty-store e1 (constant pair-car-disp) e2)]) - (define-inline 3 set-cdr! - [(e1 e2) (build-dirty-store e1 (constant pair-cdr-disp) e2)]) - (define-inline 3 set-box! - [(e1 e2) (build-dirty-store e1 (constant box-ref-disp) e2)]) - (define-inline 3 box-cas! - [(e1 e2 e3) - (bind #t (e2) - (build-dirty-store e1 %zero (constant box-ref-disp) e3 (make-build-cas e2) build-cas-seq))]) - (define-inline 3 $set-symbol-name! - [(e1 e2) (build-dirty-store e1 (constant symbol-name-disp) e2)]) - (define-inline 3 $set-symbol-property-list! - [(e1 e2) (build-dirty-store e1 (constant symbol-plist-disp) e2)]) - (define-inline 3 $set-system-property-list! - [(e1 e2) (build-dirty-store e1 (constant symbol-splist-disp) e2)]) - (define-inline 3 $set-port-info! - [(e1 e2) (build-dirty-store e1 (constant port-info-disp) e2)]) - (define-inline 3 set-port-name! - [(e1 e2) (build-dirty-store e1 (constant port-name-disp) e2)]) - (define-inline 2 set-box! - [(e-box e-new) - (bind #t (e-box e-new) - `(if ,(%typed-object-check mask-mutable-box type-mutable-box ,e-box) - ,(build-dirty-store e-box (constant box-ref-disp) e-new) - ,(build-libcall #t src sexpr set-box! e-box e-new)))]) - (define-inline 2 box-cas! - [(e-box e-old e-new) - (bind #t (e-box e-old e-new) - `(if ,(%typed-object-check mask-mutable-box type-mutable-box ,e-box) - ,(build-dirty-store e-box %zero (constant box-ref-disp) e-new (make-build-cas e-old) build-cas-seq) - ,(build-libcall #t src sexpr box-cas! e-box e-old e-new)))]) - (define-inline 2 set-car! - [(e-pair e-new) - (bind #t (e-pair e-new) - `(if ,(%type-check mask-pair type-pair ,e-pair) - ,(build-dirty-store e-pair (constant pair-car-disp) e-new) - ,(build-libcall #t src sexpr set-car! e-pair e-new)))]) - (define-inline 2 set-cdr! - [(e-pair e-new) - (bind #t (e-pair e-new) - `(if ,(%type-check mask-pair type-pair ,e-pair) - ,(build-dirty-store e-pair (constant pair-cdr-disp) e-new) - ,(build-libcall #t src sexpr set-cdr! e-pair e-new)))]) - (define-inline 3 $set-symbol-hash! - ; no need for dirty store---e2 should be a fixnum - [(e1 e2) `(set! ,(%mref ,e1 ,(constant symbol-hash-disp)) ,e2)]) - (let () - (define-syntax define-tlc-parameter - (syntax-rules () - [(_ name disp) - (define-inline 3 name - [(e-x) (%mref ,e-x ,(constant disp))])] - [(_ name name! disp) - (begin - (define-tlc-parameter name disp) - (define-inline 3 name! - [(e-x e-new) (build-dirty-store e-x (constant disp) e-new)]))])) - (define-tlc-parameter $tlc-keyval tlc-keyval-disp) - (define-tlc-parameter $tlc-ht tlc-ht-disp) - (define-tlc-parameter $tlc-next $set-tlc-next! tlc-next-disp)) - (define-inline 2 $top-level-value - [(e) (nanopass-case (L7 Expr) e - [(quote ,d) - (guard (symbol? d)) - (if (any-set? (prim-mask (or primitive system)) ($sgetprop d '*flags* 0)) - (Symref d) - (bind #t (e) - (bind #t ([t (%mref ,e ,(constant symbol-value-disp))]) - `(if ,(%type-check mask-unbound sunbound ,t) - ,(build-libcall #t #f sexpr $top-level-value e) - ,t))))] - [else - (bind #t (e) - (let ([Lfail (make-local-label 'tlv-fail)]) - `(if ,(%type-check mask-symbol type-symbol ,e) - ,(bind #t ([t (%mref ,e ,(constant symbol-value-disp))]) - `(if ,(%type-check mask-unbound sunbound ,t) - (goto ,Lfail) - ,t)) - (label ,Lfail ,(build-libcall #t #f sexpr $top-level-value e)))))])]) - (define-inline 3 $top-level-value - [(e) (nanopass-case (L7 Expr) e - [(quote ,d) (guard (symbol? d)) (Symref d)] - [else (%mref ,e ,(constant symbol-value-disp))])]) - (let () - (define (go e-sym e-value) - (bind #t (e-sym) - `(seq - ,(build-dirty-store e-sym (constant symbol-value-disp) e-value) - (set! ,(%mref ,e-sym ,(constant symbol-pvalue-disp)) - (literal - ,(make-info-literal #f 'library - (lookup-libspec nonprocedure-code) - (constant code-data-disp))))))) - (define-inline 3 $set-top-level-value! - [(e-sym e-value) (go e-sym e-value)]) - (define-inline 2 $set-top-level-value! - [(e-sym e-value) (and (constant? symbol? e-sym) (go e-sym e-value))])) - (define-inline 3 $top-level-bound? - [(e-sym) - (build-not - (%type-check mask-unbound sunbound - ,(nanopass-case (L7 Expr) e-sym - [(quote ,d) (guard (symbol? d)) (Symref d)] - [else (%mref ,e-sym ,(constant symbol-value-disp))])))]) - (let () - (define parse-format - (lambda (who src cntl-arg args) - (nanopass-case (L7 Expr) cntl-arg - [(quote ,d) - (guard (c [(and (assertion-violation? c) - (format-condition? c) - (message-condition? c) - (irritants-condition? c)) - ($source-warning 'compile - src #t - "~? in call to ~s" - (condition-message c) - (condition-irritants c) - who) - #f]) - (#%$parse-format-string who d (length args)))] - [else #f]))) - (define fmt->expr - ($make-fmt->expr - (lambda (d) `(quote ,d)) - (lambda (e1 e2) `(seq ,e1 ,e2)) - (lambda (src sexpr prim arg*) - `(call ,(make-info-call src sexpr #f #f #f) #f - ,(lookup-primref 3 prim) - ,arg* ...)))) - (define build-format - (lambda (who src sexpr op-arg cntl-arg arg*) - (let ([x (parse-format who src cntl-arg arg*)]) - (and x - (cond - [(and (fx= (length x) 1) - (string? (car x)) - (nanopass-case (L7 Expr) op-arg - [(quote ,d) (eq? d #f)] - [else #f])) - (%primcall src sexpr string-copy (quote ,(car x)))] - [(and (nanopass-case (L7 Expr) op-arg - [(quote ,d) (not (eq? d #f))] - [else #t]) - (let-values ([(op-arg dobind) (binder #t 'ptr op-arg)] - [(arg* dobind*) (list-binder #t 'ptr arg*)]) - (let ([e (fmt->expr src sexpr x op-arg arg*)]) - (and e (dobind (dobind* e))))))] - [else - (%primcall src sexpr $dofmt (quote ,who) ,op-arg ,cntl-arg - (quote ,x) - ,(build-list arg*))]))))) - (define-inline 2 errorf - [(e-who e-str . e*) - (parse-format 'errorf src e-str e*) - `(seq (pariah) (call ,(make-info-call src sexpr #f #t #t) #f ,(Symref 'errorf) ,e-who ,e-str ,e* ...))]) - (define-inline 2 assertion-violationf - [(e-who e-str . e*) - (parse-format 'assertion-violationf src e-str e*) - `(seq (pariah) (call ,(make-info-call src sexpr #f #t #t) #f ,(Symref 'assertion-violationf) ,e-who ,e-str ,e* ...))]) - (define-inline 2 $oops - [(e-who e-str . e*) - (parse-format '$oops src e-str e*) - `(seq (pariah) (call ,(make-info-call src sexpr #f #t #t) #f ,(Symref '$oops) ,e-who ,e-str ,e* ...))]) - (define-inline 2 $impoops - [(e-who e-str . e*) - (parse-format '$impoops src e-str e*) - `(seq (pariah) (call ,(make-info-call src sexpr #f #t #t) #f ,(Symref '$impoops) ,e-who ,e-str ,e* ...))]) - (define-inline 2 warningf - [(e-who e-str . e*) - (parse-format 'warningf src e-str e*) - `(seq (pariah) (call ,(make-info-call src sexpr #f #t #f) #f ,(Symref 'warningf) ,e-who ,e-str ,e* ...))]) - (define-inline 2 $source-violation - [(e-who e-src e-start? e-str . e*) - (parse-format '$source-violation src e-str e*) - `(seq (pariah) (call ,(make-info-call src sexpr #f #t #t) #f ,(Symref '$source-violation) - ,e-who ,e-src ,e-start? ,e-str ,e* ...))]) - (define-inline 2 $source-warning - [(e-who e-src e-start? e-str . e*) - (parse-format '$source-warning src e-str e*) - `(seq (pariah) (call ,(make-info-call src sexpr #f #t #f) #f ,(Symref '$source-warning) - ,e-who ,e-src ,e-start? ,e-str ,e* ...))]) - (define-inline 2 fprintf - [(e-op e-str . e*) - (parse-format 'fprintf src e-str e*) - #f]) - (define-inline 3 fprintf - [(e-op e-str . e*) (build-format 'fprintf src sexpr e-op e-str e*)]) - (define-inline 2 printf - [(e-str . e*) - (build-format 'printf src sexpr (%tc-ref current-output) e-str e*)]) - (define-inline 2 format - [(e . e*) - (nanopass-case (L7 Expr) e - [(quote ,d) - (if (string? d) - (build-format 'format src sexpr `(quote #f) e e*) - (and (not (null? e*)) - (cond - [(eq? d #f) (build-format 'format src sexpr e (car e*) (cdr e*))] - [(eq? d #t) (build-format 'format src sexpr - (%tc-ref current-output) - (car e*) (cdr e*))] - [else #f])))] - [else #f])])) - (let () - (define hand-coded-closure? - (lambda (name) - (not (memq name '(nuate nonprocedure-code error-invoke invoke))))) - (define-inline 2 $hand-coded - [(name) - (nanopass-case (L7 Expr) name - [(quote ,d) - (guard (symbol? d)) - (let ([l (make-local-label 'hcl)]) - (set! new-l* (cons l new-l*)) - (set! new-le* (cons (with-output-language (L9 CaseLambdaExpr) `(hand-coded ,d)) new-le*)) - (if (hand-coded-closure? d) - `(literal ,(make-info-literal #f 'closure l 0)) - `(label-ref ,l 0)))] - [(seq (profile ,src) ,[e]) `(seq (profile ,src) ,e)] - [else ($oops '$hand-coded "~s is not a quoted symbol" name)])])) - (define-inline 2 $tc - [() %tc]) - (define-inline 3 $tc-field - [(e-fld e-tc) - (nanopass-case (L7 Expr) e-fld - [(quote ,d) - (let () - (define-syntax a - (lambda (x) - #`(case d - #,@(fold-left - (lambda (ls field) - (apply - (lambda (name type disp len) - (if (eq? type 'ptr) - (cons - (with-syntax ([name (datum->syntax #'* name)]) - #'[(name) (%tc-ref ,e-tc name)]) - ls) - ls)) - field)) - '() (getprop 'tc '*fields* '())) - [else #f]))) - a)] - [else #f])] - [(e-fld e-tc e-val) - (nanopass-case (L7 Expr) e-fld - [(quote ,d) - (let () - (define-syntax a - (lambda (x) - #`(case d - #,@(fold-left - (lambda (ls field) - (apply - (lambda (name type disp len) - (if (eq? type 'ptr) - (cons - (with-syntax ([name (datum->syntax #'* name)]) - #'[(name) `(set! ,(%tc-ref ,e-tc name) ,e-val)]) - ls) - ls)) - field)) - '() (getprop 'tc '*fields* '())) - [else #f]))) - a)] - [else #f])]) - (let () - (define-syntax define-tc-parameter - (syntax-rules () - [(_ name tc-name) - (begin - (define-inline 2 name - [() (%tc-ref tc-name)] - [(x) #f]) - (define-inline 3 name - [() (%tc-ref tc-name)] - [(x) `(set! ,(%tc-ref tc-name) ,x)]))])) - - (define-tc-parameter current-input-port current-input) - (define-tc-parameter current-output-port current-output) - (define-tc-parameter current-error-port current-error) - (define-tc-parameter generate-inspector-information generate-inspector-information) - (define-tc-parameter generate-procedure-source-information generate-procedure-source-information) - (define-tc-parameter generate-profile-forms generate-profile-forms) - (define-tc-parameter $compile-profile compile-profile) - (define-tc-parameter optimize-level optimize-level) - (define-tc-parameter subset-mode subset-mode) - (define-tc-parameter $suppress-primitive-inlining suppress-primitive-inlining) - (define-tc-parameter $block-counter block-counter) - (define-tc-parameter $sfd sfd) - (define-tc-parameter $current-mso current-mso) - (define-tc-parameter $target-machine target-machine) - (define-tc-parameter $current-stack-link stack-link) - (define-tc-parameter $current-winders winders) - (define-tc-parameter default-record-equal-procedure default-record-equal-procedure) - (define-tc-parameter default-record-hash-procedure default-record-hash-procedure) - ) - - (define-inline 3 $install-guardian - [(e-obj e-rep e-tconc) - (bind #f (e-obj e-rep e-tconc) - (bind #t ([t (%constant-alloc typemod (constant size-guardian-entry))]) - (%seq - (set! ,(%mref ,t ,(constant guardian-entry-obj-disp)) ,e-obj) - (set! ,(%mref ,t ,(constant guardian-entry-rep-disp)) ,e-rep) - (set! ,(%mref ,t ,(constant guardian-entry-tconc-disp)) ,e-tconc) - (set! ,(%mref ,t ,(constant guardian-entry-next-disp)) ,(%tc-ref guardian-entries)) - (set! ,(%tc-ref guardian-entries) ,t))))]) - - (define-inline 3 $install-ftype-guardian - [(e-obj e-tconc) - (bind #f (e-obj e-tconc) - (bind #t ([t (%constant-alloc typemod (constant size-guardian-entry))]) - (%seq - (set! ,(%mref ,t ,(constant guardian-entry-obj-disp)) ,e-obj) - (set! ,(%mref ,t ,(constant guardian-entry-rep-disp)) (immediate ,(constant ftype-guardian-rep))) - (set! ,(%mref ,t ,(constant guardian-entry-tconc-disp)) ,e-tconc) - (set! ,(%mref ,t ,(constant guardian-entry-next-disp)) ,(%tc-ref guardian-entries)) - (set! ,(%tc-ref guardian-entries) ,t))))]) - - (define-inline 2 guardian? - [(e) - (bind #t (e) - (build-and - (%type-check mask-closure type-closure ,e) - (%type-check mask-guardian-code type-guardian-code - ,(%mref - ,(%inline - - ,(%mref ,e ,(constant closure-code-disp)) - ,(%constant code-data-disp)) - ,(constant code-type-disp)))))]) - - (define-inline 2 virtual-register-count - [() `(quote ,(constant virtual-register-count))]) - (let () - (define constant-ref - (lambda (e-idx) - (nanopass-case (L7 Expr) e-idx - [(quote ,d) - (guard (and (fixnum? d) ($fxu< d (constant virtual-register-count)))) - (%mref ,%tc ,(fx+ (constant tc-virtual-registers-disp) (fx* d (constant ptr-bytes))))] - [else #f]))) - (define constant-set - (lambda (e-idx e-val) - (let ([ref (constant-ref e-idx)]) - (and ref `(set! ,ref ,e-val))))) - (define index-check - (lambda (e-idx libcall e) - `(if (if ,(%type-check mask-fixnum type-fixnum ,e-idx) - ,(%inline u< ,e-idx (immediate ,(fix (constant virtual-register-count)))) - ,(%constant sfalse)) - ,e - ,libcall))) - (meta-assert (= (constant log2-ptr-bytes) (constant fixnum-offset))) - (define-inline 3 virtual-register - [(e-idx) - (or (constant-ref e-idx) - (%mref ,%tc ,e-idx ,(constant tc-virtual-registers-disp)))]) - (define-inline 2 virtual-register - [(e-idx) - (or (constant-ref e-idx) - (bind #t (e-idx) - (index-check e-idx - (build-libcall #t src sexpr virtual-register e-idx) - (%mref ,%tc ,e-idx ,(constant tc-virtual-registers-disp)))))]) - (define-inline 3 set-virtual-register! - [(e-idx e-val) - (or (constant-set e-idx e-val) - `(set! ,(%mref ,%tc ,e-idx ,(constant tc-virtual-registers-disp)) ,e-val))]) - (define-inline 2 set-virtual-register! - [(e-idx e-val) - (or (constant-set e-idx e-val) - (bind #t (e-idx) - (bind #f (e-val) - (index-check e-idx - (build-libcall #t src sexpr set-virtual-register! e-idx) - `(set! ,(%mref ,%tc ,e-idx ,(constant tc-virtual-registers-disp)) ,e-val)))))])) - - (define-inline 2 $thread-list - [() `(literal ,(make-info-literal #t 'entry (lookup-c-entry thread-list) 0))]) - (when-feature pthreads - (define-inline 2 $raw-tc-mutex - [() `(literal ,(make-info-literal #f 'entry (lookup-c-entry raw-tc-mutex) 0))]) - (define-inline 2 $raw-collect-cond - [() `(literal ,(make-info-literal #f 'entry (lookup-c-entry raw-collect-cond) 0))])) - (define-inline 2 not - [(e) `(if ,e ,(%constant sfalse) ,(%constant strue))]) - (define-inline 2 most-negative-fixnum - [() `(quote ,(constant most-negative-fixnum))]) - (define-inline 2 most-positive-fixnum - [() `(quote ,(constant most-positive-fixnum))]) - (define-inline 2 least-fixnum - [() `(quote ,(constant most-negative-fixnum))]) - (define-inline 2 greatest-fixnum - [() `(quote ,(constant most-positive-fixnum))]) - (define-inline 2 fixnum-width - [() `(quote ,(constant fixnum-bits))]) - (define-inline 2 native-endianness - [() `(quote ,(constant native-endianness))]) - (define-inline 2 directory-separator - [() `(quote ,(if-feature windows #\\ #\/))]) - (let () ; level 2 char=?, r6rs:char=?, etc. - (define-syntax char-pred - (syntax-rules () - [(_ op r6rs:op inline-op) - (let () - (define (go2 src sexpr e1 e2) - (bind #t (e1 e2) - `(if ,(build-chars? e1 e2) - ,(%inline inline-op ,e1 ,e2) - ,(build-libcall #t src sexpr op e1 e2)))) - (define (go3 src sexpr e1 e2 e3) - (and (constant? char? e1) - (constant? char? e3) - (bind #t (e2) - `(if ,(%type-check mask-char type-char ,e2) - ,(build-and - (%inline inline-op ,e1 ,e2) - (%inline inline-op ,e2 ,e3)) - ; could also pass e2 and e3: - ,(build-libcall #t src sexpr op e1 e2))))) - (define-inline 2 op - [(e1 e2) (go2 src sexpr e1 e2)] - [(e1 e2 e3) (go3 src sexpr e1 e2 e3)] - [(e1 . e*) #f]) - (define-inline 2 r6rs:op - [(e1 e2) (go2 src sexpr e1 e2)] - [(e1 e2 e3) (go3 src sexpr e1 e2 e3)] - [(e1 e2 . e*) #f]))])) - (char-pred char=? r6rs:char>=? >=) - (char-pred char>? r6rs:char>? >)) - (let () ; level 3 char=?, r6rs:char=?, etc. - (define-syntax char-pred - (syntax-rules () - [(_ op r6rs:op inline-op) - (let () - (define (go2 e1 e2) - (%inline inline-op ,e1 ,e2)) - (define (go3 e1 e2 e3) - (bind #t (e2) - (bind #f (e3) - (build-and - (go2 e1 e2) - (go2 e2 e3))))) - (define-inline 3 op - [(e) `(seq ,e ,(%constant strue))] - [(e1 e2) (go2 e1 e2)] - [(e1 e2 e3) (go3 e1 e2 e3)] - [(e1 . e*) #f]) - (define-inline 3 r6rs:op - [(e1 e2) (go2 e1 e2)] - [(e1 e2 e3) (go3 e1 e2 e3)] - [(e1 e2 . e*) #f]))])) - (char-pred char=? r6rs:char>=? >=) - (char-pred char>? r6rs:char>? >)) - (define-inline 3 map - [(e-proc e-ls) - (or (nanopass-case (L7 Expr) e-proc - [,pr - (and (all-set? (prim-mask unsafe) (primref-flags pr)) - (let ([name (primref-name pr)]) - (or (and (eq? name 'car) (build-libcall #f src sexpr map-car e-ls)) - (and (eq? name 'cdr) (build-libcall #f src sexpr map-cdr e-ls)))))] - [else #f]) - (build-libcall #f src sexpr map1 e-proc e-ls))] - [(e-proc e-ls1 e-ls2) - (or (nanopass-case (L7 Expr) e-proc - [,pr - (and (eq? (primref-name pr) 'cons) - (build-libcall #f src sexpr map-cons e-ls1 e-ls2))] - [else #f]) - (build-libcall #f src sexpr map2 e-proc e-ls1 e-ls2))] - [(e-proc e-ls . e-ls*) #f]) - (define-inline 3 andmap - [(e-proc e-ls) (build-libcall #f src sexpr andmap1 e-proc e-ls)] - [(e-proc e-ls . e-ls*) #f]) - (define-inline 3 for-all - [(e-proc e-ls) (build-libcall #f src sexpr andmap1 e-proc e-ls)] - [(e-proc e-ls . e-ls*) #f]) - (define-inline 3 ormap - [(e-proc e-ls) (build-libcall #f src sexpr ormap1 e-proc e-ls)] - [(e-proc e-ls . e-ls*) #f]) - (define-inline 3 exists - [(e-proc e-ls) (build-libcall #f src sexpr ormap1 e-proc e-ls)] - [(e-proc e-ls . e-ls*) #f]) - (define-inline 3 fold-left - [(e-proc e-base e-ls) (build-libcall #f src sexpr fold-left1 e-proc e-base e-ls)] - [(e-proc e-base e-ls1 e-ls2) (build-libcall #f src sexpr fold-left2 e-proc e-base e-ls1 e-ls2)] - [(e-proc e-base e-ls . e-ls*) #f]) - (define-inline 3 fold-right - [(e-proc e-base e-ls) (build-libcall #f src sexpr fold-right1 e-proc e-base e-ls)] - [(e-proc e-base e-ls1 e-ls2) (build-libcall #f src sexpr fold-right2 e-proc e-base e-ls1 e-ls2)] - [(e-proc e-base e-ls . e-ls*) #f]) - (define-inline 3 for-each - [(e-proc e-ls) (build-libcall #f src sexpr for-each1 e-proc e-ls)] - [(e-proc e-ls1 e-ls2) (build-libcall #f src sexpr for-each2 e-proc e-ls1 e-ls2)] - [(e-proc e-ls . e-ls*) #f]) - (define-inline 3 vector-map - [(e-proc e-ls) (build-libcall #f src sexpr vector-map1 e-proc e-ls)] - [(e-proc e-ls1 e-ls2) (build-libcall #f src sexpr vector-map2 e-proc e-ls1 e-ls2)] - [(e-proc e-ls . e-ls*) #f]) - (define-inline 3 vector-for-each - [(e-proc e-ls) (build-libcall #f src sexpr vector-for-each1 e-proc e-ls)] - [(e-proc e-ls1 e-ls2) (build-libcall #f src sexpr vector-for-each2 e-proc e-ls1 e-ls2)] - [(e-proc e-ls . e-ls*) #f]) - (define-inline 3 string-for-each - [(e-proc e-ls) (build-libcall #f src sexpr string-for-each1 e-proc e-ls)] - [(e-proc e-ls1 e-ls2) (build-libcall #f src sexpr string-for-each2 e-proc e-ls1 e-ls2)] - [(e-proc e-ls . e-ls*) #f]) - (define-inline 3 reverse - [(e) (build-libcall #f src sexpr reverse e)]) - (let () - (define inline-getprop - (lambda (plist-offset e-sym e-key e-dflt) - (let ([t-ls (make-assigned-tmp 't-ls)] [t-cdr (make-tmp 't-cdr)] [Ltop (make-local-label 'Ltop)]) - (bind #t (e-key e-dflt) - ; indirect symbol after evaluating e-key and e-dflt - `(let ([,t-ls ,(%mref ,e-sym ,plist-offset)]) - (label ,Ltop - (if ,(%inline eq? ,t-ls ,(%constant snil)) - ,e-dflt - (let ([,t-cdr ,(%mref ,t-ls ,(constant pair-cdr-disp))]) - (if ,(%inline eq? ,(%mref ,t-ls ,(constant pair-car-disp)) ,e-key) - ,(%mref ,t-cdr ,(constant pair-car-disp)) - (seq - (set! ,t-ls ,(%mref ,t-cdr ,(constant pair-cdr-disp))) - (goto ,Ltop))))))))))) - (define-inline 3 getprop - [(e-sym e-key) (inline-getprop (constant symbol-plist-disp) e-sym e-key (%constant sfalse))] - [(e-sym e-key e-dflt) (inline-getprop (constant symbol-plist-disp) e-sym e-key e-dflt)]) - (define-inline 3 $sgetprop - [(e-sym e-key e-dflt) (inline-getprop (constant symbol-splist-disp) e-sym e-key e-dflt)])) - (define-inline 3 assq - [(e-key e-ls) - (let ([t-ls (make-assigned-tmp 't-ls)] [Ltop (make-local-label 'Ltop)]) - (bind #t (e-key) - `(let ([,t-ls ,e-ls]) - (label ,Ltop - (if ,(%inline eq? ,t-ls ,(%constant snil)) - ,(%constant sfalse) - ,(bind #t ([t-a (%mref ,t-ls ,(constant pair-car-disp))]) - `(if ,(%inline eq? ,(%mref ,t-a ,(constant pair-car-disp)) ,e-key) - ,t-a - (seq - (set! ,t-ls ,(%mref ,t-ls ,(constant pair-cdr-disp))) - (goto ,Ltop)))))))))]) - (define-inline 3 length - [(e-ls) - (let ([t-ls (make-assigned-tmp 't-ls)] - [t-n (make-assigned-tmp 't-n)] - [Ltop (make-local-label 'Ltop)]) - (bind #t (e-ls) - `(if ,(%inline eq? ,e-ls ,(%constant snil)) - (immediate ,(fix 0)) - (let ([,t-ls ,e-ls] [,t-n (immediate ,(fix 0))]) - (label ,Ltop - ,(%seq - (set! ,t-ls ,(%mref ,t-ls ,(constant pair-cdr-disp))) - (set! ,t-n ,(%inline + ,t-n (immediate ,(fix 1)))) - (if ,(%inline eq? ,t-ls ,(%constant snil)) - ,t-n - (goto ,Ltop))))))))]) - (define-inline 3 append - ; TODO: hand-coded library routine that allocates the new pairs in a block - [() (%constant snil)] - [(e-ls) e-ls] - [(e-ls1 e-ls2) (build-libcall #f src sexpr append e-ls1 e-ls2)] - [(e-ls1 e-ls2 e-ls3) - (build-libcall #f src sexpr append e-ls1 - (build-libcall #f #f sexpr append e-ls2 e-ls3))] - [(e-ls . e-ls*) #f]) - (define-inline 3 apply - [(e0 e1) (build-libcall #f src sexpr apply0 e0 e1)] - [(e0 e1 e2) (build-libcall #f src sexpr apply1 e0 e1 e2)] - [(e0 e1 e2 e3) (build-libcall #f src sexpr apply2 e0 e1 e2 e3)] - [(e0 e1 e2 e3 e4) (build-libcall #f src sexpr apply3 e0 e1 e2 e3 e4)] - [(e0 e1 . e*) #f]) - (define-inline 2 fxsll - [(e0 e1) (build-libcall #f src sexpr fxsll e0 e1)]) - (define-inline 2 fxarithmetic-shift-left - [(e0 e1) (build-libcall #f src sexpr fxarithmetic-shift-left e0 e1)]) - (define-inline 3 display-string - [(e-s) (build-libcall #f src sexpr display-string e-s (%tc-ref current-output))] - [(e-s e-op) (build-libcall #f src sexpr display-string e-s e-op)]) - (define-inline 3 call-with-current-continuation - [(e) (build-libcall #f src sexpr callcc e)]) - (define-inline 3 call/cc - [(e) (build-libcall #f src sexpr callcc e)]) - (define-inline 3 call/1cc - [(e) (build-libcall #f src sexpr call1cc e)]) - (define-inline 2 $event - [() (build-libcall #f src sexpr event)]) - (define-inline 3 eq-hashtable-ref - [(e1 e2 e3) (build-libcall #f src sexpr eq-hashtable-ref e1 e2 e3)]) - (define-inline 3 eq-hashtable-contains? - [(e1 e2) (build-libcall #f src sexpr eq-hashtable-contains? e1 e2)]) - (define-inline 3 eq-hashtable-set! - [(e1 e2 e3) (build-libcall #f src sexpr eq-hashtable-set! e1 e2 e3)]) - (define-inline 3 eq-hashtable-update! - [(e1 e2 e3 e4) (build-libcall #f src sexpr eq-hashtable-update! e1 e2 e3 e4)]) - (define-inline 3 eq-hashtable-cell - [(e1 e2 e3) (build-libcall #f src sexpr eq-hashtable-cell e1 e2 e3)]) - (define-inline 3 eq-hashtable-delete! - [(e1 e2) (build-libcall #f src sexpr eq-hashtable-delete! e1 e2)]) - (define-inline 3 symbol-hashtable-ref - [(e1 e2 e3) (build-libcall #f src sexpr symbol-hashtable-ref e1 e2 e3)]) - (define-inline 3 symbol-hashtable-contains? - [(e1 e2) (build-libcall #f src sexpr symbol-hashtable-contains? e1 e2)]) - (define-inline 3 symbol-hashtable-set! - [(e1 e2 e3) (build-libcall #f src sexpr symbol-hashtable-set! e1 e2 e3)]) - (define-inline 3 symbol-hashtable-update! - [(e1 e2 e3 e4) (build-libcall #f src sexpr symbol-hashtable-update! e1 e2 e3 e4)]) - (define-inline 3 symbol-hashtable-cell - [(e1 e2 e3) (build-libcall #f src sexpr symbol-hashtable-cell e1 e2 e3)]) - (define-inline 3 symbol-hashtable-delete! - [(e1 e2) (build-libcall #f src sexpr symbol-hashtable-delete! e1 e2)]) - (define-inline 2 bytevector-s8-set! - [(e1 e2 e3) (build-libcall #f src sexpr bytevector-s8-set! e1 e2 e3)]) - (define-inline 2 bytevector-u8-set! - [(e1 e2 e3) (build-libcall #f src sexpr bytevector-u8-set! e1 e2 e3)]) - (define-inline 3 bytevector=? - [(e1 e2) (build-libcall #f src sexpr bytevector=? e1 e2)]) - (let () - (define eqok-help? - (lambda (obj) - (or (symbol? obj) - (char? obj) - (target-fixnum? obj) - (null? obj) - (boolean? obj) - (eqv? obj "") - (eqv? obj ($tc-field 'null-immutable-string ($tc))) - (eqv? obj '#()) - (eqv? obj ($tc-field 'null-immutable-vector ($tc))) - (eqv? obj '#vu8()) - (eqv? obj ($tc-field 'null-immutable-bytevector ($tc))) - (eqv? obj '#vfx()) - (eqv? obj ($tc-field 'null-immutable-fxvector ($tc))) - (eq? obj (void)) - (eof-object? obj) - (bwp-object? obj) - (eq? obj '#6=#6#) - ($unbound-object? obj)))) - (define eqvok-help? number?) - (define e*ok? - (lambda (e*ok-help?) - (lambda (e) - (nanopass-case (L7 Expr) e - [(quote ,d) (e*ok-help? d)] - [else #f])))) - (define eqok? (e*ok? eqok-help?)) - (define eqvok? (e*ok? eqvok-help?)) - (define-inline 2 eqv? - [(e1 e2) (or (eqvop-null-fptr e1 e2) - (relop-length RELOP= e1 e2) - (if (or (eqok? e1) (eqok? e2)) - (build-eq? e1 e2) - (build-eqv? src sexpr e1 e2)))]) - (let () - (define xform-equal? - (lambda (src sexpr e1 e2) - (nanopass-case (L7 Expr) e1 - [(quote ,d1) - (let xform ([d1 d1] [e2 e2] [n 3] [k (lambda (e n) e)]) - (if (eqok-help? d1) - (k (build-eq? `(quote ,d1) e2) n) - (if (eqvok-help? d1) - (k (build-eqv? src sexpr `(quote ,d1) e2) n) - (and (fx> n 0) - (pair? d1) - (let-values ([(e2 dobind) (binder #t 'ptr e2)]) - (xform (car d1) (build-car e2) (fx- n 1) - (lambda (a n) - (xform (cdr d1) (build-cdr e2) n - (lambda (d n) - (k (dobind - (build-and - (build-pair? e2) - (build-and a d))) - n))))))))))] - [else #f]))) - (define-inline 2 equal? - [(e1 e2) (or (eqvop-null-fptr e1 e2) - (relop-length RELOP= e1 e2) - (xform-equal? src sexpr e1 e2) - (xform-equal? src sexpr e2 e1))])) - (let () - (define mem*ok? - (lambda (e*ok-help?) - (lambda (x) - (nanopass-case (L7 Expr) x - [(quote ,d) - (and (list? d) - (let f ([d d]) - (or (null? d) - (and (e*ok-help? (car d)) - (f (cdr d))))))] - [else #f])))) - (define memqok? (mem*ok? eqok-help?)) - (define memvok? (mem*ok? eqvok-help?)) - (define mem*->e*?s - (lambda (build-e*? limit) - (lambda (e-key e-ls) - (nanopass-case (L7 Expr) e-ls - [(quote ,d) - (and (let f ([d d] [n 0]) - (or (null? d) - (and (pair? d) - (fx< n limit) - (f (cdr d) (fx1+ n))))) - (bind #t (e-key) - (let f ([ls d]) - (if (null? ls) - `(quote #f) - `(if ,(build-e*? e-key `(quote ,(car ls))) - (quote ,ls) - ,(f (cdr ls)))))))] - [else #f])))) - (define memq->eq?s (mem*->e*?s build-eq? 8)) - (define (memv->eqv?s src sexpr) (mem*->e*?s (make-build-eqv? src sexpr) 4)) - (define do-memq - (lambda (src sexpr e-key e-ls) - (or (memq->eq?s e-key e-ls) - (let ([t-ls (make-assigned-tmp 't-ls)] [Ltop (make-local-label 'Ltop)]) - (bind #t (e-key) - `(let ([,t-ls ,e-ls]) - (label ,Ltop - (if ,(%inline eq? ,t-ls ,(%constant snil)) - ,(%constant sfalse) - (if ,(%inline eq? ,(%mref ,t-ls ,(constant pair-car-disp)) ,e-key) - ,t-ls - (seq - (set! ,t-ls ,(%mref ,t-ls ,(constant pair-cdr-disp))) - (goto ,Ltop))))))))))) - (define do-memv - (lambda (src sexpr e-key e-ls) - (or ((memv->eqv?s src sexpr) e-key e-ls) - (build-libcall #f src sexpr memv e-key e-ls)))) - (define-inline 3 memq - [(e-key e-ls) (do-memq src sexpr e-key e-ls)]) - (define-inline 3 memv - [(e-key e-ls) - (if (or (eqok? e-key) (memqok? e-ls)) - (do-memq src sexpr e-key e-ls) - (do-memv src sexpr e-key e-ls))]) - (define-inline 3 member - [(e-key e-ls) - (if (or (eqok? e-key) (memqok? e-ls)) - (do-memq src sexpr e-key e-ls) - (and (or (eqvok? e-key) (memvok? e-ls)) - (do-memv src sexpr e-key e-ls)))]) - (define-inline 2 memq - [(e-key e-ls) (memq->eq?s e-key e-ls)]) - (define-inline 2 memv - [(e-key e-ls) (or (and (memqok? e-ls) (memq->eq?s e-key e-ls)) - ((memv->eqv?s src sexpr) e-key e-ls))]) - (define-inline 2 member - [(e-key e-ls) (or (and (memqok? e-ls) (memq->eq?s e-key e-ls)) - (and (memvok? e-ls) ((memv->eqv?s src sexpr) e-key e-ls)))]))) - ; NB: for all of the I/O routines, consider putting optimize-level 2 code out-of-line - ; w/o going all the way to the port handler, i.e., always defer to library routine but - ; have library routine do the checks and run the optimize-level 3 version...this could - ; save a lot of code - ; NB: verify that the inline checks don't always fail, i.e., don't always send us to the - ; library routine - (let () - (define (go src sexpr e-p check? update? do-libcall) - (let ([Llib (and check? (make-local-label 'Llib))]) - (define maybe-add-port-check - (lambda (e-p body) - (if Llib - `(if (if ,(%type-check mask-typed-object type-typed-object ,e-p) - ,(%type-check mask-binary-input-port type-binary-input-port - ,(%mref ,e-p ,(constant typed-object-type-disp))) - ,(%constant sfalse)) - ,body - (goto ,Llib)) - body))) - (define maybe-add-update - (lambda (t0 e-icount body) - (if update? - `(seq - (set! ,e-icount ,(%inline + ,t0 (immediate 1))) - ,body) - body))) - (bind #t (e-p) - (let ([e-icount (%mref ,e-p ,(constant port-icount-disp))]) - (maybe-add-port-check e-p - (bind #t ([t0 e-icount]) - `(if ,(%inline eq? ,t0 (immediate 0)) - ,(maybe-add-label Llib (do-libcall src sexpr e-p)) - ,(maybe-add-update t0 e-icount - ; TODO: this doesn't completely fall away when used in effect context - (build-fix - `(inline ,(make-info-load 'unsigned-8 #f) ,%load - ,t0 - ,(%mref ,e-p ,(constant port-ilast-disp)) - (immediate 0))))))))))) - (define (unsafe-lookahead-u8-libcall src sexpr e-p) (build-libcall #t src sexpr unsafe-lookahead-u8 e-p)) - (define (safe-lookahead-u8-libcall src sexpr e-p) (build-libcall #t src sexpr safe-lookahead-u8 e-p)) - (define (unsafe-get-u8-libcall src sexpr e-p) (build-libcall #t src sexpr unsafe-get-u8 e-p)) - (define (safe-get-u8-libcall src sexpr e-p) (build-libcall #t src sexpr safe-get-u8 e-p)) - (define-inline 3 lookahead-u8 - [(e-p) (go src sexpr e-p #f #f unsafe-lookahead-u8-libcall)]) - (define-inline 2 lookahead-u8 - [(e-p) (go src sexpr e-p #t #f safe-lookahead-u8-libcall)]) - (define-inline 3 get-u8 - [(e-p) (go src sexpr e-p #f #t unsafe-get-u8-libcall)]) - (define-inline 2 get-u8 - [(e-p) (go src sexpr e-p #t #t safe-get-u8-libcall)])) - (let () - (define (go src sexpr e-p check? update? do-libcall) - (let ([Llib (and check? (make-local-label 'Llib))]) - (define maybe-add-port-check - (lambda (e-p body) - (if Llib - `(if (if ,(%type-check mask-typed-object type-typed-object ,e-p) - ,(%type-check mask-textual-input-port type-textual-input-port - ,(%mref ,e-p ,(constant typed-object-type-disp))) - ,(%constant sfalse)) - ,body - (goto ,Llib)) - body))) - (define maybe-add-update - (lambda (t0 e-icount body) - (if update? - `(seq - (set! ,e-icount ,(%inline + ,t0 ,(%constant string-char-bytes))) - ,body) - body))) - (bind #t (e-p) - (let ([e-icount (%mref ,e-p ,(constant port-icount-disp))]) - (maybe-add-port-check e-p - (bind #t ([t0 e-icount]) - `(if ,(%inline eq? ,t0 (immediate 0)) - ,(maybe-add-label Llib (do-libcall src sexpr e-p)) - ,(maybe-add-update t0 e-icount - ; TODO: this doesn't completely fall away when used in effect context - `(inline ,(make-info-load (string-char-type) #f) ,%load - ,t0 - ,(%mref ,e-p ,(constant port-ilast-disp)) - (immediate 0)))))))))) - (define (unsafe-lookahead-char-libcall src sexpr e-p) (build-libcall #t src sexpr unsafe-lookahead-char e-p)) - (define (safe-lookahead-char-libcall src sexpr e-p) (build-libcall #t src sexpr safe-lookahead-char e-p)) - (define (unsafe-peek-char-libcall src sexpr e-p) (build-libcall #t src sexpr unsafe-peek-char e-p)) - (define (safe-peek-char-libcall src sexpr e-p) (build-libcall #t src sexpr safe-peek-char e-p)) - (define (unsafe-get-char-libcall src sexpr e-p) (build-libcall #t src sexpr unsafe-get-char e-p)) - (define (safe-get-char-libcall src sexpr e-p) (build-libcall #t src sexpr safe-get-char e-p)) - (define (unsafe-read-char-libcall src sexpr e-p) (build-libcall #t src sexpr unsafe-read-char e-p)) - (define (safe-read-char-libcall src sexpr e-p) (build-libcall #t src sexpr safe-read-char e-p)) - (define-inline 3 lookahead-char - [(e-p) (go src sexpr e-p #f #f unsafe-lookahead-char-libcall)]) - (define-inline 2 lookahead-char - [(e-p) (go src sexpr e-p #t #f safe-lookahead-char-libcall)]) - (define-inline 3 peek-char - [() (go src sexpr (%tc-ref current-input) #f #f unsafe-peek-char-libcall)] - [(e-p) (go src sexpr e-p #f #f unsafe-peek-char-libcall)]) - (define-inline 2 peek-char - [() (go src sexpr (%tc-ref current-input) #f #f unsafe-peek-char-libcall)] - [(e-p) (go src sexpr e-p #t #f safe-peek-char-libcall)]) - (define-inline 3 get-char - [(e-p) (go src sexpr e-p #f #t unsafe-get-char-libcall)]) - (define-inline 2 get-char - [(e-p) (go src sexpr e-p #t #t safe-get-char-libcall)]) - (define-inline 3 read-char - [() (go src sexpr (%tc-ref current-input) #f #t unsafe-read-char-libcall)] - [(e-p) (go src sexpr e-p #f #t unsafe-read-char-libcall)]) - (define-inline 2 read-char - [() (go src sexpr (%tc-ref current-input) #f #t unsafe-read-char-libcall)] - [(e-p) (go src sexpr e-p #t #t safe-read-char-libcall)])) - (let () - (define (go src sexpr e-p e-c check-port? check-char? do-libcall) - (let ([const-char? (constant? char? e-c)]) - (let ([Llib (and (or check-char? check-port? (not const-char?)) (make-local-label 'Llib))]) - (define maybe-add-port-check - (lambda (e-p body) - (if check-port? - `(if (if ,(%type-check mask-typed-object type-typed-object ,e-p) - ,(%type-check mask-textual-input-port type-textual-input-port - ,(%mref ,e-p ,(constant typed-object-type-disp))) - ,(%constant sfalse)) - ,body - (goto ,Llib)) - body))) - (define maybe-add-eof-check - (lambda (e-c body) - (if const-char? - body - `(if ,(%inline eq? ,e-c ,(%constant seof)) - (goto ,Llib) - ,body)))) - (define maybe-add-char-check - (lambda (e-c body) - (if check-char? - `(if ,(%type-check mask-char type-char ,e-c) - ,body - (goto ,Llib)) - body))) - (bind #t (e-c e-p) - (let ([e-icount (%mref ,e-p ,(constant port-icount-disp))]) - (maybe-add-port-check e-p - (maybe-add-eof-check e-c - (maybe-add-char-check e-c - (bind #t ([t0 e-icount]) - `(if ,(%inline eq? ,t0 - ,(%inline - - ,(%inline + - ,(%mref ,e-p ,(constant port-ibuffer-disp)) - ,(%constant string-data-disp)) - ,(%mref ,e-p ,(constant port-ilast-disp)))) - ,(maybe-add-label Llib (do-libcall src sexpr e-p e-c)) - (set! ,e-icount ,(%inline - ,t0 ,(%constant string-char-bytes))))))))))))) - (define (unsafe-unget-char-libcall src sexpr e-p e-c) (build-libcall #t src sexpr unsafe-unget-char e-p e-c)) - (define (safe-unget-char-libcall src sexpr e-p e-c) (build-libcall #t src sexpr safe-unget-char e-p e-c)) - (define (unsafe-unread-char-libcall src sexpr e-p e-c) (build-libcall #t src sexpr unsafe-unread-char e-c e-p)) - (define (safe-unread-char-libcall src sexpr e-p e-c) (build-libcall #t src sexpr safe-unread-char e-c e-p)) - (define-inline 3 unget-char - [(e-p e-c) (go src sexpr e-p e-c #f #f unsafe-unget-char-libcall)]) - (define-inline 2 unget-char - [(e-p e-c) (go src sexpr e-p e-c #t (not (constant? char? e-c)) safe-unget-char-libcall)]) - (define-inline 3 unread-char - [(e-c) (go src sexpr (%tc-ref current-input) e-c #f #f unsafe-unread-char-libcall)] - [(e-c e-p) (go src sexpr e-p e-c #f #f unsafe-unread-char-libcall)]) - (define-inline 2 unread-char - [(e-c) (if (constant? char? e-c) - (go src sexpr (%tc-ref current-input) e-c #f #f unsafe-unread-char-libcall) - (go src sexpr (%tc-ref current-input) e-c #f #t safe-unread-char-libcall))] - [(e-c e-p) (go src sexpr e-p e-c #t (not (constant? char? e-c)) safe-unread-char-libcall)])) - (let () - (define octet? - (lambda (x) - (and (fixnum? x) (fx<= 0 x 255)))) - (define maybe-add-octet-check - (lambda (check-octet? Llib e-o body) - (if check-octet? - `(if ,(%type-check mask-octet type-octet ,e-o) - ,body - (goto ,Llib)) - body))) - (let () - (define (go src sexpr e-p e-o check-port? check-octet? do-libcall) - (let ([const-octet? (constant? octet? e-o)]) - (let ([Llib (and (or check-octet? check-port? (not const-octet?)) (make-local-label 'Llib))]) - (define maybe-add-port-check - (lambda (e-p body) - (if check-port? - `(if (if ,(%type-check mask-typed-object type-typed-object ,e-p) - ,(%type-check mask-binary-input-port type-binary-input-port - ,(%mref ,e-p ,(constant typed-object-type-disp))) - ,(%constant sfalse)) - ,body - (goto ,Llib)) - body))) - (define maybe-add-eof-check - (lambda (e-o body) - (if const-octet? - body - `(if ,(%inline eq? ,e-o ,(%constant seof)) - (goto ,Llib) - ,body)))) - (bind #t (e-o e-p) - (let ([e-icount (%mref ,e-p ,(constant port-icount-disp))]) - (maybe-add-port-check e-p - (maybe-add-eof-check e-o - (maybe-add-octet-check check-octet? Llib e-o - (bind #t ([t0 e-icount]) - `(if ,(%inline eq? ,t0 - ,(%inline - - ,(%inline + - ,(%mref ,e-p ,(constant port-ibuffer-disp)) - ,(%constant bytevector-data-disp)) - ,(%mref ,e-p ,(constant port-ilast-disp)))) - ,(maybe-add-label Llib (do-libcall src sexpr e-p e-o)) - (set! ,e-icount ,(%inline - ,t0 (immediate 1))))))))))))) - (define (unsafe-unget-u8-libcall src sexpr e-p e-o) (build-libcall #t src sexpr unsafe-unget-u8 e-p e-o)) - (define (safe-unget-u8-libcall src sexpr e-p e-o) (build-libcall #t src sexpr safe-unget-u8 e-p e-o)) - (define-inline 3 unget-u8 - [(e-p e-o) (go src sexpr e-p e-o #f #f unsafe-unget-u8-libcall)]) - (define-inline 2 unget-u8 - [(e-p e-o) (go src sexpr e-p e-o #t (not (constant? octet? e-o)) safe-unget-u8-libcall)])) - (let () - (define (go src sexpr e-p e-o check-port? check-octet? do-libcall) - (let ([Llib (and (or check-octet? check-port?) (make-local-label 'Llib))]) - (define maybe-add-port-check - (lambda (e-p body) - (if check-port? - `(if (if ,(%type-check mask-typed-object type-typed-object ,e-p) - ,(%type-check mask-binary-output-port type-binary-output-port - ,(%mref ,e-p ,(constant typed-object-type-disp))) - ,(%constant sfalse)) - ,body - (goto ,Llib)) - body))) - (define add-update - (lambda (t0 e-ocount body) - `(seq - (set! ,e-ocount ,(%inline + ,t0 (immediate 1))) - ,body))) - (bind check-octet? (e-o) - (bind #t (e-p) - (let ([e-ocount (%mref ,e-p ,(constant port-ocount-disp))]) - (maybe-add-octet-check check-octet? Llib e-o - (maybe-add-port-check e-p - (bind #t ([t0 e-ocount]) - `(if ,(%inline eq? ,t0 (immediate 0)) - ,(maybe-add-label Llib (do-libcall src sexpr e-o e-p)) - ,(add-update t0 e-ocount - `(inline ,(make-info-load 'unsigned-8 #f) ,%store - ,t0 - ,(%mref ,e-p ,(constant port-olast-disp)) - (immediate 0) - ,(build-unfix e-o)))))))))))) - (define (unsafe-put-u8-libcall src sexpr e-o e-p) (build-libcall #t src sexpr unsafe-put-u8 e-p e-o)) - (define (safe-put-u8-libcall src sexpr e-o e-p) (build-libcall #t src sexpr safe-put-u8 e-p e-o)) - (define-inline 3 put-u8 - [(e-p e-o) (go src sexpr e-p e-o #f #f unsafe-put-u8-libcall)]) - (define-inline 2 put-u8 - [(e-p e-o) (go src sexpr e-p e-o #t (not (constant? octet? e-o)) safe-put-u8-libcall)]))) - (let () - (define (go src sexpr e-p e-c check-port? check-char? do-libcall) - (let ([Llib (and (or check-char? check-port?) (make-local-label 'Llib))]) - (define maybe-add-char-check - (lambda (e-c body) - (if check-char? - `(if ,(%type-check mask-char type-char ,e-c) - ,body - (goto ,Llib)) - body))) - (define maybe-add-port-check - (lambda (e-p body) - (if check-port? - `(if (if ,(%type-check mask-typed-object type-typed-object ,e-p) - ,(%type-check mask-textual-output-port type-textual-output-port - ,(%mref ,e-p ,(constant typed-object-type-disp))) - ,(%constant sfalse)) - ,body - (goto ,Llib)) - body))) - (define add-update - (lambda (t0 e-ocount body) - `(seq - (set! ,e-ocount ,(%inline + ,t0 ,(%constant string-char-bytes))) - ,body))) - (bind check-char? (e-c) - (bind #t (e-p) - (let ([e-ocount (%mref ,e-p ,(constant port-ocount-disp))]) - (maybe-add-char-check e-c - (maybe-add-port-check e-p - (bind #t ([t0 e-ocount]) - `(if ,(%inline eq? ,t0 (immediate 0)) - ,(maybe-add-label Llib (do-libcall src sexpr e-c e-p)) - ,(add-update t0 e-ocount - `(inline ,(make-info-load (string-char-type) #f) ,%store - ,t0 - ,(%mref ,e-p ,(constant port-olast-disp)) - (immediate 0) - ,e-c))))))))))) - (define (unsafe-put-char-libcall src sexpr e-c e-p) (build-libcall #t src sexpr unsafe-put-char e-p e-c)) - (define (safe-put-char-libcall src sexpr e-c e-p) (build-libcall #t src sexpr safe-put-char e-p e-c)) - (define (unsafe-write-char-libcall src sexpr e-c e-p) (build-libcall #t src sexpr unsafe-write-char e-c e-p)) - (define (safe-write-char-libcall src sexpr e-c e-p) (build-libcall #t src sexpr safe-write-char e-c e-p)) - (define (unsafe-newline-libcall src sexpr e-c e-p) (build-libcall #t src sexpr unsafe-newline e-p)) - (define (safe-newline-libcall src sexpr e-c e-p) (build-libcall #t src sexpr safe-newline e-p)) - (define-inline 3 put-char - [(e-p e-c) (go src sexpr e-p e-c #f #f unsafe-put-char-libcall)]) - (define-inline 2 put-char - [(e-p e-c) (go src sexpr e-p e-c #t (not (constant? char? e-c)) safe-put-char-libcall)]) - (define-inline 3 write-char - [(e-c) (go src sexpr (%tc-ref current-output) e-c #f #f unsafe-write-char-libcall)] - [(e-c e-p) (go src sexpr e-p e-c #f #f unsafe-write-char-libcall)]) - (define-inline 2 write-char - [(e-c) (if (constant? char? e-c) - (go src sexpr (%tc-ref current-output) e-c #f #f unsafe-write-char-libcall) - (go src sexpr (%tc-ref current-output) e-c #f #t safe-write-char-libcall))] - [(e-c e-p) (go src sexpr e-p e-c #t (not (constant? char? e-c)) safe-write-char-libcall)]) - (define-inline 3 newline - [() (go src sexpr (%tc-ref current-output) `(quote #\newline) #f #f unsafe-newline-libcall)] - [(e-p) (go src sexpr e-p `(quote #\newline) #f #f unsafe-newline-libcall)]) - (define-inline 2 newline - [() (go src sexpr (%tc-ref current-output) `(quote #\newline) #f #f unsafe-newline-libcall)] - [(e-p) (go src sexpr e-p `(quote #\newline) #t #f safe-newline-libcall)])) - (let () - (define build-fxop? - (lambda (op overflow-flag e1 e2 adjust k) - (let ([Lfail (make-local-label 'Lfail)]) - (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(bind #f ([t `(inline ,null-info ,op ,e1 ,(adjust e2))]) - `(if (inline ,(make-info-condition-code overflow-flag #f #t) ,%condition-code) - (label ,Lfail ,(k e1 e2)) - ,t)) - (goto ,Lfail)))))) - (define-inline 2 + - [() `(immediate ,(fix 0))] - [(e) (build-fxop? %+/ovfl 'overflow e `(quote 0) values (lambda (e1 e2) (build-libcall #t src sexpr + e1 e2)))] - [(e1 e2) (build-fxop? %+/ovfl 'overflow e1 e2 values (lambda (e1 e2) (build-libcall #t src sexpr + e1 e2)))] - ; TODO: handle 3-operand case ala fx+, w/3-operand library + - [(e1 . e*) #f]) - (define-inline 2 * - [() `(immediate ,(fix 1))] - [(e) (build-fxop? %*/ovfl 'multiply-overflow e `(quote 1) build-unfix (lambda (e1 e2) (build-libcall #t src sexpr * e1 e2)))] - ; TODO: swap e1 & e2 if e1 is constant - [(e1 e2) (build-fxop? %*/ovfl 'multiply-overflow e1 e2 build-unfix (lambda (e1 e2) (build-libcall #t src sexpr * e1 e2)))] - ; TODO: handle 3-operand case ala fx+, w/3-operand library * - [(e1 . e*) #f]) - (define-inline 2 - - [(e) (build-fxop? %-/ovfl 'overflow `(quote 0) e values (lambda (e1 e2) (build-libcall #t src sexpr - e1 e2)))] - [(e1 e2) (build-fxop? %-/ovfl 'overflow e1 e2 values (lambda (e1 e2) (build-libcall #t src sexpr - e1 e2)))] - ; TODO: handle 3-operand case ala fx+, w/3-operand library - - [(e1 e2 . e*) #f])) - (let () - (define build-fxop? - (lambda (op e k) - (let ([Lfail (make-local-label 'Lfail)]) - (bind #t (e) - `(if ,(%type-check mask-fixnum type-fixnum ,e) - ,(bind #f ([t `(inline ,null-info ,op ,e (immediate ,(fix 1)))]) - `(if (inline ,(make-info-condition-code 'overflow #f #t) ,%condition-code) - (label ,Lfail ,(k e)) - ,t)) - (goto ,Lfail)))))) - - (define-syntax define-inline-1op - (syntax-rules () - [(_ op name) - (define-inline 2 name - [(e) (build-fxop? op e (lambda (e) (build-libcall #t src sexpr name e)))])])) - - (define-inline-1op %-/ovfl 1-) - (define-inline-1op %-/ovfl -1+) - (define-inline-1op %-/ovfl sub1) - (define-inline-1op %+/ovfl 1+) - (define-inline-1op %+/ovfl add1)) - - (define-inline 2 / - [(e) (build-libcall #f src sexpr / `(immediate ,(fix 1)) e)] - [(e1 e2) (build-libcall #f src sexpr / e1 e2)] - [(e1 . e*) #f]) - - (let () - (define (zgo src sexpr e e1 e2) - (build-simple-or - (%inline eq? ,e (immediate 0)) - `(if ,(build-fixnums? (list e)) - ,(%constant sfalse) - ,(build-libcall #t src sexpr = e1 e2)))) - (define (go src sexpr e1 e2) - (or (eqvop-null-fptr e1 e2) - (relop-length RELOP= e1 e2) - (cond - [(constant? (lambda (x) (eqv? x 0)) e1) - (bind #t (e2) (zgo src sexpr e2 e1 e2))] - [(constant? (lambda (x) (eqv? x 0)) e2) - (bind #t (e1) (zgo src sexpr e1 e1 e2))] - [else (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(%inline eq? ,e1 ,e2) - ,(build-libcall #t src sexpr = e1 e2)))]))) - (define-inline 2 = - [(e1 e2) (go src sexpr e1 e2)] - [(e1 . e*) #f]) - (define-inline 2 r6rs:= - [(e1 e2) (go src sexpr e1 e2)] - [(e1 e2 . e*) #f])) - (let () - (define-syntax define-relop-inline - (syntax-rules () - [(_ name r6rs:name relop op) - (let () - (define builder - (lambda (e1 e2 libcall) - (or (relop-length relop e1 e2) - (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(%inline op ,e1 ,e2) - ,(libcall e1 e2)))))) - (define-inline 2 name - [(e1 e2) - (builder e1 e2 - (lambda (e1 e2) (build-libcall #t src sexpr name e1 e2)))] - ; TODO: handle 3-operand case w/3-operand library routine - [(e1 . e*) #f]) - (define-inline 2 r6rs:name - [(e1 e2) - (builder e1 e2 - (lambda (e1 e2) (build-libcall #t src sexpr name e1 e2)))] - ; TODO: handle 3-operand case w/3-operand library routine - [(e1 e2 . e*) #f]))])) - (define-relop-inline < r6rs:< RELOP< <) - (define-relop-inline <= r6rs:<= RELOP<= <=) - (define-relop-inline >= r6rs:>= RELOP>= >=) - (define-relop-inline > r6rs:> RELOP> >)) - (define-inline 3 positive? ; 3 so opt-level 2 errors come from positive? - [(e) (handle-prim src sexpr 3 '> (list e `(quote 0)))]) - (define-inline 3 nonnegative? ; 3 so opt-level 2 errors come from nonnegative? - [(e) (handle-prim src sexpr 3 '>= (list e `(quote 0)))]) - (define-inline 3 negative? ; 3 so opt-level 2 errors come from negative? - [(e) (handle-prim src sexpr 3 '< (list e `(quote 0)))]) - (define-inline 3 nonpositive? ; 3 so opt-level 2 errors come from nonpositive? - [(e) (handle-prim src sexpr 3 '<= (list e `(quote 0)))]) - (define-inline 2 zero? - [(e) - (or (relop-length RELOP= e) - (nanopass-case (L7 Expr) e - [(call ,info ,mdcl ,pr ,e) - (guard - (eq? (primref-name pr) 'ftype-pointer-address) - (all-set? (prim-mask unsafe) (primref-flags pr))) - (make-ftype-pointer-null? e)] - [else - (bind #t (e) - (build-simple-or - (%inline eq? ,e (immediate ,(fix 0))) - `(if ,(%type-check mask-fixnum type-fixnum ,e) - ,(%constant sfalse) - ,(build-libcall #t src sexpr zero? e))))]))]) - (define-inline 2 positive? [(e) (relop-length RELOP> e)]) - (define-inline 2 nonnegative? [(e) (relop-length RELOP>= e)]) - (define-inline 2 negative? [(e) (relop-length RELOP< e)]) - (define-inline 2 nonpositive? [(e) (relop-length RELOP<= e)]) - (let () - (define-syntax define-logorop-inline - (syntax-rules () - [(_ name ...) - (let () - (define build-logop - (lambda (src sexpr e1 e2 libcall) - (bind #t (e1 e2) - (bind #t ([t (%inline logor ,e1 ,e2)]) - `(if ,(%type-check mask-fixnum type-fixnum ,t) - ,t - ,(libcall src sexpr e1 e2)))))) - (let () - (define libcall (lambda (src sexpr e1 e2) (build-libcall #t src sexpr name e1 e2))) - (define-inline 2 name - [() `(immediate ,(fix 0))] - [(e) (build-logop src sexpr e `(immediate ,(fix 0)) libcall)] - [(e1 e2) (build-logop src sexpr e1 e2 libcall)] - [(e1 . e*) #f])) - ...)])) - (define-logorop-inline logor logior bitwise-ior)) - (let () - (define-syntax define-logop-inline - (syntax-rules () - [(_ op unit name ...) - (let () - (define build-logop - (lambda (src sexpr e1 e2 libcall) - (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(%inline op ,e1 ,e2) - ,(libcall src sexpr e1 e2))))) - (let () - (define libcall (lambda (src sexpr e1 e2) (build-libcall #t src sexpr name e1 e2))) - (define-inline 2 name - [() `(immediate ,(fix unit))] - [(e) (build-logop src sexpr e `(immediate ,(fix unit)) libcall)] - [(e1 e2) (build-logop src sexpr e1 e2 libcall)] - [(e1 . e*) #f])) - ...)])) - (define-logop-inline logand -1 logand bitwise-and) - (define-logop-inline logxor 0 logxor bitwise-xor)) - (let () - (define build-lognot - (lambda (e libcall) - (bind #t (e) - `(if ,(%type-check mask-fixnum type-fixnum ,e) - ,(%inline logxor ,e (immediate ,(fxlognot (constant mask-fixnum)))) - ,(libcall e))))) - - (define-inline 2 lognot - [(e) (build-lognot e (lambda (e) (build-libcall #t src sexpr lognot e)))]) - (define-inline 2 bitwise-not - [(e) (build-lognot e (lambda (e) (build-libcall #t src sexpr bitwise-not e)))])) - - (let () - (define build-logbit? - (lambda (e1 e2 libcall) - (or (nanopass-case (L7 Expr) e1 - [(quote ,d) - (or (and (and (fixnum? d) (fx<= 0 d (fx- (constant fixnum-bits) 2))) - (bind #t (e2) - `(if ,(%type-check mask-fixnum type-fixnum ,e2) - ,(%inline logtest ,e2 (immediate ,(fix (ash 1 d)))) - ,(libcall e1 e2)))) - (and (and (target-fixnum? d) (> d (fx- (constant fixnum-bits) 2))) - (bind #t (e2) - `(if ,(%type-check mask-fixnum type-fixnum ,e2) - ,(%inline < ,e2 (immediate ,(fix 0))) - ,(libcall e1 e2)))))] - [else #f]) - (bind #t (e1 e2) - `(if ,(build-and - (build-fixnums? (list e1 e2)) - (%inline u< ,e1 (immediate ,(fix (constant fixnum-bits))))) - ,(%inline logtest - ,(%inline sra ,e2 ,(build-unfix e1)) - (immediate ,(fix 1))) - ,(libcall e1 e2)))))) - - (define-inline 2 logbit? - [(e1 e2) (build-logbit? e1 e2 (lambda (e1 e2) (build-libcall #t src sexpr logbit? e1 e2)))]) - (define-inline 2 bitwise-bit-set? - [(e1 e2) (build-logbit? e2 e1 (lambda (e2 e1) (build-libcall #t src sexpr bitwise-bit-set? e1 e2)))])) - - (define-inline 2 logbit1 - [(e1 e2) (or (nanopass-case (L7 Expr) e1 - [(quote ,d) - (and (and (fixnum? d) (fx<= 0 d (fx- (constant fixnum-bits) 2))) - (bind #t (e2) - `(if ,(%type-check mask-fixnum type-fixnum ,e2) - ,(%inline logor ,e2 (immediate ,(fix (ash 1 d)))) - ,(build-libcall #t src sexpr logbit1 e1 e2))))] - [else #f]) - (bind #t (e1 e2) - `(if ,(build-and - (build-fixnums? (list e1 e2)) - (%inline u< ,e1 (immediate ,(fix (fx- (constant fixnum-bits) 1))))) - ,(%inline logor ,e2 - ,(%inline sll (immediate ,(fix 1)) ,(build-unfix e1))) - ,(build-libcall #t src sexpr logbit1 e1 e2))))]) - (define-inline 2 logbit0 - [(e1 e2) (or (nanopass-case (L7 Expr) e1 - [(quote ,d) - (and (and (fixnum? d) (fx<= 0 d (fx- (constant fixnum-bits) 2))) - (bind #t (e2) - `(if ,(%type-check mask-fixnum type-fixnum ,e2) - ,(%inline logand ,e2 (immediate ,(fix (lognot (ash 1 d))))) - ,(build-libcall #t src sexpr logbit0 e1 e2))))] - [else #f]) - (bind #t (e1 e2) - `(if ,(build-and - (build-fixnums? (list e1 e2)) - (%inline u< ,e1 (immediate ,(fix (fx- (constant fixnum-bits) 1))))) - ,(%inline logand ,e2 - ,(%inline lognot - ,(%inline sll (immediate ,(fix 1)) ,(build-unfix e1)))) - ,(build-libcall #t src sexpr logbit0 e1 e2))))]) - (define-inline 2 logtest - [(e1 e2) (bind #t (e1 e2) - `(if ,(build-fixnums? (list e1 e2)) - ,(%inline logtest ,e1 ,e2) - ,(build-libcall #t src sexpr logtest e1 e2)))]) - (define-inline 3 $flhash - [(e) (bind #t (e) - (%inline logand - ,(%inline srl - ,(constant-case ptr-bits - [(32) (%inline + - ,(%mref ,e ,(constant flonum-data-disp)) - ,(%mref ,e ,(fx+ (constant flonum-data-disp) 4)))] - [(64) (%mref ,e ,(constant flonum-data-disp))]) - (immediate 1)) - (immediate ,(- (constant fixnum-factor)))))]) - (let () - (define build-flonum-extractor - (lambda (pos size e1) - (let ([cnt (- pos (constant fixnum-offset))] - [mask (* (- (expt 2 size) 1) (expt 2 (constant fixnum-offset)))]) - (%inline logand - ,(let ([body `(inline ,(make-info-load 'integer-32 #f) ,%load ,e1 ,%zero - (immediate ,(constant-case native-endianness - [(little) (fx+ (constant flonum-data-disp) 4)] - [(big) (constant flonum-data-disp)])))]) - (let ([body (if (fx> cnt 0) - (%inline srl ,body (immediate ,cnt)) - body)]) - (if (fx< cnt 0) - (%inline sll ,body (immediate ,(fx- 0 cnt))) - body))) - (immediate ,mask))))) - - (define-inline 3 fllp - [(e) (build-flonum-extractor 19 12 e)]) - - (define-inline 3 $flonum-sign - [(e) (build-flonum-extractor 31 1 e)]) - - (define-inline 3 $flonum-exponent - [(e) (build-flonum-extractor 20 11 e)])) - - (define-inline 3 $fleqv? - [(e1 e2) - (constant-case ptr-bits - [(32) (build-and - (%inline eq? - ,(%mref ,e1 ,(constant flonum-data-disp)) - ,(%mref ,e2 ,(constant flonum-data-disp))) - (%inline eq? - ,(%mref ,e1 ,(fx+ (constant flonum-data-disp) 4)) - ,(%mref ,e2 ,(fx+ (constant flonum-data-disp) 4))))] - [(64) (%inline eq? - ,(%mref ,e1 ,(constant flonum-data-disp)) - ,(%mref ,e2 ,(constant flonum-data-disp)))] - [else ($oops 'compiler-internal - "$fleqv doesn't handle ptr-bits = ~s" - (constant ptr-bits))])]) - - - (let () - (define build-flop-1 - ; NB: e must be bound - (lambda (op e) - (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))]) - `(seq (inline ,null-info ,op ,e ,t) ,t)))) - (define build-flop-2 - ; NB: e1 and e2 must be bound - (lambda (op e1 e2) - (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))]) - `(seq (inline ,null-info ,op ,e1 ,e2 ,t) ,t)))) - (define build-flabs - (lambda (e) - (bind (constant-case ptr-bits [(32) #t] [(64) #f]) (e) - (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))]) - (%seq - ,(constant-case ptr-bits - [(64) - `(set! ,(%mref ,t ,(constant flonum-data-disp)) - ,(%inline logand - ,(%mref ,e ,(constant flonum-data-disp)) - ,(%inline srl (immediate -1) (immediate 1))))] - [(32) - (let () - (constant-case native-endianness - [(big) - (begin - (define disp-high (constant flonum-data-disp)) - (define disp-low (fx+ (constant flonum-data-disp) 4)))] - [(little) - (begin - (define disp-low (constant flonum-data-disp)) - (define disp-high (fx+ (constant flonum-data-disp) 4)))]) - (%seq - (set! ,(%mref ,t ,disp-high) - ,(%inline logand - ,(%mref ,e ,disp-high) - ,(%inline srl (immediate -1) (immediate 1)))) - (set! ,(%mref ,t ,disp-low) - ,(%mref ,e ,disp-low))))]) - ,t))))) - (define build-flneg - (lambda (e) - (bind (constant-case ptr-bits [(32) #t] [(64) #f]) (e) - (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))]) - (%seq - ,(constant-case ptr-bits - [(64) - `(set! ,(%mref ,t ,(constant flonum-data-disp)) - ,(%inline logxor - ,(%mref ,e ,(constant flonum-data-disp)) - ,(%inline sll (immediate 1) (immediate 63))))] - [(32) - (let () - (constant-case native-endianness - [(big) - (begin - (define disp-high (constant flonum-data-disp)) - (define disp-low (fx+ (constant flonum-data-disp) 4)))] - [(little) - (begin - (define disp-low (constant flonum-data-disp)) - (define disp-high (fx+ (constant flonum-data-disp) 4)))]) - (%seq - (set! ,(%mref ,t ,disp-high) - ,(%inline logxor - ,(%mref ,e ,disp-high) - ,(%inline sll (immediate 1) (immediate 31)))) - (set! ,(%mref ,t ,disp-low) - ,(%mref ,e ,disp-low))))]) - ,t))))) - - ;; TODO: Rather then reducing here, (which will allocate a new flonum for each interim result) - ;; we could allocate a single flonum and reuse it until the final result is calculated. - ;; Better yet, we could do this across nested fl operations, so that only one flonum is - ;; allocated across nested fl+, fl*, fl-, fl/ etc. operation - (define-inline 3 fl+ - [() `(quote 0.0)] - [(e) e] - [(e1 e2) (bind #f (e1 e2) (build-flop-2 %fl+ e1 e2))] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - - (define-inline 3 fl* - [() `(quote 1.0)] - [(e) e] - [(e1 e2) (bind #f (e1 e2) (build-flop-2 %fl* e1 e2))] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - - (define-inline 3 fl- - [(e) (build-flneg e)] - [(e1 e2) (bind #f (e1 e2) (build-flop-2 %fl- e1 e2))] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - - (define-inline 3 fl/ - [(e) (bind #f (e) (build-flop-2 %fl/ `(quote 1.0) e))] - [(e1 e2) (bind #f (e1 e2) (build-flop-2 %fl/ e1 e2))] - [(e1 . e*) (reduce src sexpr moi e1 e*)]) - - (define-inline 3 flsqrt - [(e) - (constant-case architecture - [(x86 x86_64 arm32) (bind #f (e) (build-flop-1 %flsqrt e))] - [(ppc32) #f])]) - - (define-inline 3 flround - ; NB: there is no support in SSE2 for flround, though this was added in SSE4.1 - [(e) (build-libcall #f src sexpr flround e)]) - - (define-inline 3 flabs - [(e) (build-flabs e)]) - - (let () - (define build-fl-make-rectangular - (lambda (e1 e2) - (bind #f (e1 e2) - (bind #t ([t (%constant-alloc type-typed-object (constant size-inexactnum))]) - `(seq - (set! ,(%mref ,t ,(constant inexactnum-type-disp)) - ,(%constant type-inexactnum)) - ,(%seq - (inline ,(make-info-loadfl %flreg1) ,%load-double - ,e1 ,%zero ,(%constant flonum-data-disp)) - (inline ,(make-info-loadfl %flreg1) ,%store-double - ,t ,%zero ,(%constant inexactnum-real-disp)) - (inline ,(make-info-loadfl %flreg1) ,%load-double - ,e2 ,%zero ,(%constant flonum-data-disp)) - (inline ,(make-info-loadfl %flreg1) ,%store-double - ,t ,%zero ,(%constant inexactnum-imag-disp)) - ,t)))))) - - (define-inline 3 fl-make-rectangular - [(e1 e2) (build-fl-make-rectangular e1 e2)]) - - (define-inline 3 cfl- - [(e) (bind #t (e) - `(if ,(%type-check mask-flonum type-flonum ,e) - ,(build-flneg e) - ,(build-fl-make-rectangular - (build-flneg (build-$inexactnum-real-part e)) - (build-flneg (build-$inexactnum-imag-part e)))))] - [(e1 e2) (build-libcall #f src sexpr cfl- e1 e2)] - ; TODO: add 3 argument version of cfl- library function - #;[(e1 e2 e3) (build-libcall #f src sexpr cfl- e1 e2 e3)] - [(e1 e2 . e*) #f]) - - (define-inline 3 cfl+ - [() `(quote 0.0)] - [(e) e] - [(e1 e2) (build-libcall #f src sexpr cfl+ e1 e2)] - ; TODO: add 3 argument version of cfl+ library function - #;[(e1 e2 e3) (build-libcall #f src sexpr cfl+ e1 e2 e3)] - [(e1 e2 . e*) #f]) - - (define-inline 3 cfl* - [() `(quote 1.0)] - [(e) e] - [(e1 e2) (build-libcall #f src sexpr cfl* e1 e2)] - ; TODO: add 3 argument version of cfl* library function - #;[(e1 e2 e3) (build-libcall #f src sexpr cfl* e1 e2 e3)] - [(e1 e2 . e*) #f]) - - (define-inline 3 cfl/ - [(e) (build-libcall #f src sexpr cfl/ `(quote 1.0) e)] - [(e1 e2) (build-libcall #f src sexpr cfl/ e1 e2)] - ; TODO: add 3 argument version of cfl/ library function - #;[(e1 e2 e3) (build-libcall #f src sexpr cfl/ e1 e2 e3)] - [(e1 e2 . e*) #f]) - - (define-inline 3 cfl-conjugate - [(e) (bind #t (e) - `(if ,(%type-check mask-flonum type-flonum ,e) - ,e - ,(build-fl-make-rectangular - (build-$inexactnum-real-part e) - (build-flneg (build-$inexactnum-imag-part e)))))])) - - (define-inline 3 $make-exactnum - [(e1 e2) (bind #f (e1 e2) - (bind #t ([t (%constant-alloc type-typed-object (constant size-exactnum))]) - (%seq - (set! ,(%mref ,t ,(constant exactnum-type-disp)) - ,(%constant type-exactnum)) - (set! ,(%mref ,t ,(constant exactnum-real-disp)) ,e1) - (set! ,(%mref ,t ,(constant exactnum-imag-disp)) ,e2) - ,t)))]) - - (let () - (define (build-fl< e1 e2) (%inline fl< ,e1 ,e2)) - (define (build-fl= e1 e2) (%inline fl= ,e1 ,e2)) - (define (build-fl<= e1 e2) (%inline fl<= ,e1 ,e2)) - - (let () - (define-syntax define-fl-cmp-inline - (lambda (x) - (syntax-case x () - [(_ op r6rs:op builder inequality? swapped?) - (with-syntax ([(args ...) (if (datum swapped?) #'(e2 e1) #'(e1 e2))] - [reducer (if (datum inequality?) - #'reduce-inequality - #'reduce-equality)]) - #'(begin - (define-inline 3 op - [(e) (bind #t (e) (build-fl= e e))] - [(e1 e2) (builder args ...)] - [(e1 e2 . e*) (reducer src sexpr moi e1 e2 e*)]) - (define-inline 3 r6rs:op - [(e1 e2) (builder args ...)] - [(e1 e2 . e*) (reducer src sexpr moi e1 e2 e*)])))]))) - - (define-fl-cmp-inline fl= fl=? build-fl= #f #f) - (define-fl-cmp-inline fl< fl fl>? build-fl< #t #t) - (define-fl-cmp-inline fl<= fl<=? build-fl<= #t #f) - (define-fl-cmp-inline fl>= fl>=? build-fl<= #t #t)) - (let () - (define-syntax build-bind-and-check - (syntax-rules () - [(_ src sexpr op e1 e2 body) - (bind #t (e1 e2) - `(if ,(build-and - (%type-check mask-flonum type-flonum ,e1) - (%type-check mask-flonum type-flonum ,e2)) - ,body - ,(build-libcall #t src sexpr op e1 e2)))])) - (define-syntax define-fl-cmp-inline - (lambda (x) - (syntax-case x () - [(_ op r6rs:op builder inequality? swapped?) - (with-syntax ([(args ...) (if (datum swapped?) #'(e2 e1) #'(e1 e2))]) - #'(begin - (define-inline 2 op - [(e) #f] - [(e1 e2) (build-bind-and-check src sexpr op e1 e2 (builder args ...))] - [(e1 e2 . e*) #f]) - (define-inline 2 r6rs:op - [(e1 e2) (build-bind-and-check src sexpr r6rs:op e1 e2 (builder args ...))] - [(e1 e2 . e*) #f])))]))) - - (define-fl-cmp-inline fl= fl=? build-fl= #f #f) - (define-fl-cmp-inline fl< fl fl>? build-fl< #t #t) - (define-fl-cmp-inline fl<= fl<=? build-fl<= #t #f) - (define-fl-cmp-inline fl>= fl>=? build-fl<= #t #t)) - (let () - (define build-cfl= - ; NB: e1 and e2 must be bound - (lambda (e1 e2) - `(if ,(%type-check mask-flonum type-flonum ,e1) - (if ,(%type-check mask-flonum type-flonum ,e2) - ,(build-fl= e1 e2) - ,(build-and - (build-fl= `(quote 0.0) (build-$inexactnum-imag-part e2)) - (build-fl= e1 (build-$inexactnum-real-part e2)))) - (if ,(%type-check mask-flonum type-flonum ,e2) - ,(build-and - (build-fl= `(quote 0.0) (build-$inexactnum-imag-part e1)) - (build-fl= e2 (build-$inexactnum-real-part e1))) - ,(build-and - (build-fl= - (build-$inexactnum-imag-part e1) - (build-$inexactnum-imag-part e2)) - (build-fl= - (build-$inexactnum-real-part e1) - (build-$inexactnum-real-part e2))))))) - (define-inline 3 cfl= - [(e) (bind #f (e) (build-cfl= e e))] ; this is weird, why not just true? - [(e1 e2) (bind #f (e1 e2) (build-cfl= e1 e2))] - ; TODO: should we avoid building for more then the 3 item case? - [(e1 e2 . e*) (reduce-equality src sexpr moi e1 e2 e*)]))) - - (let () - (define build-flop-3 - ; NB: e1, e2, and e3 must be bound - (lambda (op e1 e2 e3) - (build-flop-2 op e1 - (build-flop-2 op e2 e3)))) - (define build-checked-flop - (case-lambda - [(e k) - (bind #t (e) - `(if ,(build-flonums? (list e)) - ,e - ,(k e)))] - [(e1 e2 op k) - (bind #t (e1 e2) - `(if ,(build-flonums? (list e1 e2)) - ,(build-flop-2 op e1 e2) - ,(k e1 e2)))] - [(e1 e2 e3 op k) - (bind #f (e1 e2 e3) - `(if ,(build-flonums? (list e1 e2 e3)) - ,(build-flop-3 op e1 e2 e3) - ,(k e1 e2 e3)))])) - - (define-inline 2 fl+ - [() `(quote 0.0)] - [(e) (build-checked-flop e - (lambda (e) - (build-libcall #t src sexpr fl+ e `(quote 0.0))))] - [(e1 e2) (build-checked-flop e1 e2 %fl+ - (lambda (e1 e2) - (build-libcall #t src sexpr fl+ e1 e2)))] - ; TODO: add 3 argument fl+ library function - #;[(e1 e2 e3) (build-checked flop e1 e2 e3 %fl+ - (lambda (e1 e2 e3) - (build-libcall #t src sexpr fl+ e1 e2 e3)))] - [(e1 . e*) #f]) - - (define-inline 2 fl* - [() `(quote 1.0)] - [(e) (build-checked-flop e - (lambda (e) - (build-libcall #t src sexpr fl* e `(quote 1.0))))] - [(e1 e2) (build-checked-flop e1 e2 %fl* - (lambda (e1 e2) - (build-libcall #t src sexpr fl* e1 e2)))] - ; TODO: add 3 argument fl* library function - #;[(e1 e2 e3) (build-checked flop e1 e2 e3 %fl* - (lambda (e1 e2 e3) - (build-libcall #t src sexpr fl* e1 e2 e3)))] - [(e1 . e*) #f]) - - (define-inline 2 fl- - [(e) - (bind #t (e) - `(if ,(build-flonums? (list e)) - ,(build-flneg e) - ,(build-libcall #t src sexpr flnegate e)))] - [(e1 e2) (build-checked-flop e1 e2 %fl- - (lambda (e1 e2) - (build-libcall #t src sexpr fl- e1 e2)))] - ; TODO: add 3 argument fl- library function - #;[(e1 e2 e3) (build-checked flop e1 e2 e3 %fl- - (lambda (e1 e2 e3) - (build-libcall #t src sexpr fl- e1 e2 e3)))] - [(e1 . e*) #f]) - - (define-inline 2 fl/ - [(e) (build-checked-flop `(quote 1.0) e %fl/ - (lambda (e1 e2) - (build-libcall #t src sexpr fl/ e1 e2)))] - [(e1 e2) (build-checked-flop e1 e2 %fl/ - (lambda (e1 e2) - (build-libcall #t src sexpr fl/ e1 e2)))] - ; TODO: add 3 argument fl/ library function - #;[(e1 e2 e3) (build-checked flop e1 e2 e3 %fl/ - (lambda (e1 e2 e3) - (build-libcall #t src sexpr fl/ e1 e2 e3)))] - [(e1 . e*) #f]))) - - ; NB: assuming that we have a trunc instruction for now, will need to change to support Sparc - (define-inline 3 flonum->fixnum - [(e-x) (bind #f (e-x) - (build-fix - (%inline trunc ,e-x)))]) - (let () - (define build-fixnum->flonum - ; NB: x must already be bound in order to ensure it is done before the flonum is allocated - (lambda (e-x) - (bind #t ([t (%constant-alloc type-flonum (constant size-flonum))]) - (%seq - ,(%inline flt ,(build-unfix e-x) ,t) - ,t)))) - (define-inline 3 fixnum->flonum - [(e-x) (bind #f (e-x) (build-fixnum->flonum e-x))]) - (define-inline 2 real->flonum - [(e-x) - (if (constant? flonum? e-x) - e-x - (bind #t (e-x) - `(if ,(%type-check mask-fixnum type-fixnum ,e-x) - ,(build-fixnum->flonum e-x) - (if ,(%type-check mask-flonum type-flonum ,e-x) - ,e-x - ,(build-libcall #t src sexpr real->flonum e-x `(quote real->flonum))))))])) - (define-inline 3 $real->flonum - [(x who) (build-$real->flonum src sexpr x who)]) - (define-inline 2 $record - [(tag . args) (build-$record tag args)]) - (define-inline 3 $object-address - [(e-ptr e-offset) - (unsigned->ptr - (%inline + ,e-ptr ,(build-unfix e-offset)) - (type->width ptr-type))]) - (define-inline 3 $address->object - [(e-addr e-roffset) - (bind #f (e-roffset) - (%inline - - ,(ptr->integer e-addr (type->width ptr-type)) - ,(build-unfix e-roffset)))]) - (define-inline 2 $object-ref - [(type base offset) - (nanopass-case (L7 Expr) type - [(quote ,d) - (let ([type (filter-foreign-type d)]) - (and (memq type (record-datatype list)) - (not (memq type '(char wchar boolean))) - (build-object-ref #f type base offset)))] - [else #f])]) - (define-inline 2 $swap-object-ref - [(type base offset) - (nanopass-case (L7 Expr) type - [(quote ,d) - (let ([type (filter-foreign-type d)]) - (and (memq type (record-datatype list)) - (not (memq type '(char wchar boolean))) - (build-object-ref #t type base offset)))] - [else #f])]) - (define-inline 3 foreign-ref - [(e-type e-addr e-offset) - (nanopass-case (L7 Expr) e-type - [(quote ,d) - (let ([type (filter-foreign-type d)]) - (and (memq type (record-datatype list)) - (not (memq type '(char wchar boolean))) - (bind #f (e-offset) - (build-object-ref #f type - (ptr->integer e-addr (constant ptr-bits)) - e-offset))))] - [else #f])]) - (define-inline 2 $object-set! - [(type base offset value) - (nanopass-case (L7 Expr) type - [(quote ,d) - (let ([type (filter-foreign-type d)]) - (and (memq type (record-datatype list)) - (not (memq type '(char wchar boolean))) - (or (>= (constant ptr-bits) (type->width type)) (eq? type 'double-float)) - (build-object-set! type base offset value)))] - [else #f])]) - (define-inline 3 foreign-set! - [(e-type e-addr e-offset e-value) - (nanopass-case (L7 Expr) e-type - [(quote ,d) - (let ([type (filter-foreign-type d)]) - (and (memq type (record-datatype list)) - (not (memq type '(char wchar boolean))) - (or (>= (constant ptr-bits) (type->width type)) (eq? type 'double-float)) - (bind #f (e-offset e-value) - (build-object-set! type - (ptr->integer e-addr (constant ptr-bits)) - e-offset - e-value))))] - [else #f])]) - (define-inline 2 $make-fptr - [(e-ftype e-addr) - (nanopass-case (L7 Expr) e-addr - [(call ,info ,mdcl ,pr ,e1) - (guard - (eq? (primref-name pr) 'ftype-pointer-address) - (all-set? (prim-mask unsafe) (primref-flags pr))) - (bind #f (e-ftype e1) - (bind #t ([t (%constant-alloc type-typed-object (fx* 2 (constant ptr-bytes)))]) - (%seq - (set! ,(%mref ,t ,(constant record-type-disp)) ,e-ftype) - (set! ,(%mref ,t ,(constant record-data-disp)) - ,(%mref ,e1 ,(constant record-data-disp))) - ,t)))] - [else - (bind #f (e-ftype e-addr) - (bind #t ([t (%constant-alloc type-typed-object (fx* 2 (constant ptr-bytes)))]) - (%seq - (set! ,(%mref ,t ,(constant record-type-disp)) ,e-ftype) - (set! ,(%mref ,t ,(constant record-data-disp)) - ,(ptr->integer e-addr (constant ptr-bits))) - ,t)))])]) - (define-inline 3 ftype-pointer-address - [(e-fptr) - (build-object-ref #f - (constant-case ptr-bits - [(64) 'unsigned-64] - [(32) 'unsigned-32]) - e-fptr %zero (constant record-data-disp))]) - (define-inline 3 ftype-pointer-null? - [(e-fptr) (make-ftype-pointer-null? e-fptr)]) - (define-inline 3 ftype-pointer=? - [(e1 e2) (make-ftype-pointer-equal? e1 e2)]) - (let () - (define build-fx+raw - (lambda (fx-arg raw-arg) - (if (constant? (lambda (x) (eqv? x 0)) fx-arg) - raw-arg - (%inline + ,raw-arg ,(build-unfix fx-arg))))) - (define $extract-fptr-address - (lambda (e-fptr) - (define suppress-unsafe-cast - (lambda (e-fptr) - (nanopass-case (L7 Expr) e-fptr - [(call ,info1 ,mdcl1 ,pr1 (quote ,d) (call ,info2 ,mdcl2 ,pr2 ,e)) - (guard - (eq? (primref-name pr1) '$make-fptr) - (all-set? (prim-mask unsafe) (primref-flags pr2)) - (eq? (primref-name pr2) 'ftype-pointer-address) - (all-set? (prim-mask unsafe) (primref-flags pr2))) - e] - [else e-fptr]))) - (nanopass-case (L7 Expr) e-fptr - ; skip allocation and dereference of ftype-pointer for $fptr-fptr-ref - [(call ,info ,mdcl ,pr ,e1 ,e2 ,e3) ; e1, e2, e3 = fptr, offset, ftd - (guard - (eq? (primref-name pr) '$fptr-fptr-ref) - (all-set? (prim-mask unsafe) (primref-flags pr))) - (let-values ([(e-index imm-offset) (offset-expr->index+offset e2)]) - (bind #f (e-index e3) - `(inline ,(make-info-load ptr-type #f) ,%load - ,($extract-fptr-address e1) - ,e-index (immediate ,imm-offset))))] - ; skip allocation and dereference of ftype-pointer for $fptr-&ref - [(call ,info ,mdcl ,pr ,e1 ,e2 ,e3) ; e1, e2, e3 = fptr, offset, ftd - (guard - (eq? (primref-name pr) '$fptr-&ref) - (all-set? (prim-mask unsafe) (primref-flags pr))) - (build-fx+raw e2 ($extract-fptr-address e1))] - ; skip allocation and dereference of ftype-pointer for $make-fptr - [(call ,info ,mdcl ,pr ,e1 ,e2) ; e1, e2 = ftd, (ptr) addr - (guard - (eq? (primref-name pr) '$make-fptr) - (all-set? (prim-mask unsafe) (primref-flags pr))) - (nanopass-case (L7 Expr) e2 - [(call ,info ,mdcl ,pr ,e3) - (guard - (eq? (primref-name pr) 'ftype-pointer-address) - (all-set? (prim-mask unsafe) (primref-flags pr))) - (bind #f (e1) - (%mref ,e3 ,(constant record-data-disp)))] - [else - (bind #f (e1) - (ptr->integer e2 (constant ptr-bits)))])] - [else - `(inline ,(make-info-load ptr-type #f) ,%load ,(suppress-unsafe-cast e-fptr) ,%zero - ,(%constant record-data-disp))]))) - (let () - (define-inline 3 $fptr-offset-addr - [(e-fptr e-offset) - ; bind offset before doing the load (a) to maintain applicative order---the - ; load can cause an invalid memory reference---and (b) so that the raw value - ; isn't live across any calls - (bind #f (e-offset) - (build-fx+raw e-offset - ($extract-fptr-address e-fptr)))]) - (define-inline 3 $fptr-&ref - [(e-fptr e-offset e-ftd) - ; see comment in $fptr-offset-addr - (bind #f (e-offset e-ftd) - (build-$record e-ftd - (list (build-fx+raw e-offset ($extract-fptr-address e-fptr)))))])) - (define-inline 3 $fptr-fptr-ref - [(e-fptr e-offset e-ftd) - (let-values ([(e-index imm-offset) (offset-expr->index+offset e-offset)]) - (bind #f (e-index) - (build-$record e-ftd - (list `(inline ,(make-info-load ptr-type #f) ,%load - ,($extract-fptr-address e-fptr) - ,e-index (immediate ,imm-offset))))))]) - (define-inline 3 $fptr-fptr-set! - [(e-fptr e-offset e-val) - (let-values ([(e-index imm-offset) (offset-expr->index+offset e-offset)]) - (bind #f ([e-addr ($extract-fptr-address e-fptr)] e-index e-val) - `(inline ,(make-info-load ptr-type #f) ,%store ,e-addr ,e-index (immediate ,imm-offset) - (inline ,(make-info-load ptr-type #f) ,%load ,e-val ,%zero - ,(%constant record-data-disp)))))]) - (let () - (define $do-fptr-ref-inline - (lambda (swapped? type e-fptr e-offset) - (bind #f (e-offset) - (build-object-ref swapped? type ($extract-fptr-address e-fptr) e-offset)))) - (define-syntax define-fptr-ref-inline - (lambda (x) - (define build-inline - (lambda (name type ref maybe-k) - #`(define-inline 3 #,name - [(e-fptr e-offset) - #,((lambda (body) (if maybe-k #`(#,maybe-k #,body) body)) - #`($do-fptr-ref-inline #,ref #,type e-fptr e-offset))]))) - (syntax-case x () - [(_ name ?type ref) (build-inline #'name #'?type #'ref #f)] - [(_ name ?type ref ?k) (build-inline #'name #'?type #'ref #'?k)]))) - - (define-fptr-ref-inline $fptr-ref-integer-8 'integer-8 #f) - (define-fptr-ref-inline $fptr-ref-unsigned-8 'unsigned-8 #f) - - (define-fptr-ref-inline $fptr-ref-integer-16 'integer-16 #f) - (define-fptr-ref-inline $fptr-ref-unsigned-16 'unsigned-16 #f) - (define-fptr-ref-inline $fptr-ref-swap-integer-16 'integer-16 #t) - (define-fptr-ref-inline $fptr-ref-swap-unsigned-16 'unsigned-16 #t) - - (define-fptr-ref-inline $fptr-ref-integer-24 'integer-24 #f) - (define-fptr-ref-inline $fptr-ref-unsigned-24 'unsigned-24 #f) - (define-fptr-ref-inline $fptr-ref-swap-integer-24 'integer-24 #t) - (define-fptr-ref-inline $fptr-ref-swap-unsigned-24 'unsigned-24 #t) - - (define-fptr-ref-inline $fptr-ref-integer-32 'integer-32 #f) - (define-fptr-ref-inline $fptr-ref-unsigned-32 'unsigned-32 #f) - (define-fptr-ref-inline $fptr-ref-swap-integer-32 'integer-32 #t) - (define-fptr-ref-inline $fptr-ref-swap-unsigned-32 'unsigned-32 #t) - - (define-fptr-ref-inline $fptr-ref-integer-40 'integer-40 #f) - (define-fptr-ref-inline $fptr-ref-unsigned-40 'unsigned-40 #f) - (define-fptr-ref-inline $fptr-ref-swap-integer-40 'integer-40 #t) - (define-fptr-ref-inline $fptr-ref-swap-unsigned-40 'unsigned-40 #t) - - (define-fptr-ref-inline $fptr-ref-integer-48 'integer-48 #f) - (define-fptr-ref-inline $fptr-ref-unsigned-48 'unsigned-48 #f) - (define-fptr-ref-inline $fptr-ref-swap-integer-48 'integer-48 #t) - (define-fptr-ref-inline $fptr-ref-swap-unsigned-48 'unsigned-48 #t) - - (define-fptr-ref-inline $fptr-ref-integer-56 'integer-56 #f) - (define-fptr-ref-inline $fptr-ref-unsigned-56 'unsigned-56 #f) - (define-fptr-ref-inline $fptr-ref-swap-integer-56 'integer-56 #t) - (define-fptr-ref-inline $fptr-ref-swap-unsigned-56 'unsigned-56 #t) - - (define-fptr-ref-inline $fptr-ref-integer-64 'integer-64 #f) - (define-fptr-ref-inline $fptr-ref-unsigned-64 'unsigned-64 #f) - (define-fptr-ref-inline $fptr-ref-swap-integer-64 'integer-64 #t) - (define-fptr-ref-inline $fptr-ref-swap-unsigned-64 'unsigned-64 #t) - - (define-fptr-ref-inline $fptr-ref-double-float 'double-float #f) - (define-fptr-ref-inline $fptr-ref-swap-double-float 'double-float #t) - - (define-fptr-ref-inline $fptr-ref-single-float 'single-float #f) - (define-fptr-ref-inline $fptr-ref-swap-single-float 'single-float #t) - - (define-fptr-ref-inline $fptr-ref-char 'unsigned-8 #f - (lambda (x) (build-integer->char x))) - - (define-fptr-ref-inline $fptr-ref-wchar - (constant-case wchar-bits [(16) 'unsigned-16] [(32) 'unsigned-32]) - #f - (lambda (x) (build-integer->char x))) - (define-fptr-ref-inline $fptr-ref-swap-wchar - (constant-case wchar-bits [(16) 'unsigned-16] [(32) 'unsigned-32]) - #t - (lambda (x) (build-integer->char x))) - - (define-fptr-ref-inline $fptr-ref-boolean - (constant-case int-bits [(32) 'unsigned-32] [(64) 'unsigned-64]) - #f - (lambda (x) - `(if ,(%inline eq? ,x (immediate 0)) - ,(%constant sfalse) - ,(%constant strue)))) - (define-fptr-ref-inline $fptr-ref-swap-boolean - (constant-case int-bits [(32) 'unsigned-32] [(64) 'unsigned-64]) - #t - (lambda (x) - `(if ,(%inline eq? ,x (immediate 0)) - ,(%constant sfalse) - ,(%constant strue)))) - - (define-fptr-ref-inline $fptr-ref-fixnum 'fixnum #f) - (define-fptr-ref-inline $fptr-ref-swap-fixnum 'fixnum #t)) - (let () - (define $do-fptr-set!-inline - (lambda (set type e-fptr e-offset e-val) - (bind #f (e-offset) - (set type ($extract-fptr-address e-fptr) e-offset e-val)))) - (define-syntax define-fptr-set!-inline - (lambda (x) - (define build-body - (lambda (type set maybe-massage-val) - #``(seq ,e-info - #,(let ([body #`($do-fptr-set!-inline #,set #,type e-fptr e-offset e-val)]) - (if maybe-massage-val - #`,(bind #f (e-offset [e-val (#,maybe-massage-val e-val)]) #,body) - #`,(bind #f (e-offset e-val) #,body)))))) - (define build-inline - (lambda (name check-64? body) - #`(define-inline 3 #,name - [(e-info e-fptr e-offset e-val) - #,(if check-64? - #`(and (fx>= (constant ptr-bits) 64) #,body) - body)]))) - (syntax-case x () - [(_ check-64? name ?type set) - (build-inline #'name (datum check-64?) (build-body #'?type #'set #f))] - [(_ check-64? name ?type set ?massage-value) - (build-inline #'name (datum check-64?) (build-body #'?type #'set #'?massage-value))]))) - - (define-fptr-set!-inline #f $fptr-set-integer-8! 'integer-8 build-object-set!) - (define-fptr-set!-inline #f $fptr-set-unsigned-8! 'unsigned-8 build-object-set!) - - (define-fptr-set!-inline #f $fptr-set-integer-16! 'integer-16 build-object-set!) - (define-fptr-set!-inline #f $fptr-set-unsigned-16! 'unsigned-16 build-object-set!) - (define-fptr-set!-inline #f $fptr-set-swap-integer-16! 'integer-16 build-swap-object-set!) - (define-fptr-set!-inline #f $fptr-set-swap-unsigned-16! 'unsigned-16 build-swap-object-set!) - - (define-fptr-set!-inline #f $fptr-set-integer-24! 'integer-24 build-object-set!) - (define-fptr-set!-inline #f $fptr-set-unsigned-24! 'unsigned-24 build-object-set!) - (define-fptr-set!-inline #f $fptr-set-swap-integer-24! 'integer-24 build-swap-object-set!) - (define-fptr-set!-inline #f $fptr-set-swap-unsigned-24! 'unsigned-24 build-swap-object-set!) - - (define-fptr-set!-inline #f $fptr-set-integer-32! 'integer-32 build-object-set!) - (define-fptr-set!-inline #f $fptr-set-unsigned-32! 'unsigned-32 build-object-set!) - (define-fptr-set!-inline #f $fptr-set-swap-integer-32! 'integer-32 build-swap-object-set!) - (define-fptr-set!-inline #f $fptr-set-swap-unsigned-32! 'unsigned-32 build-swap-object-set!) - - (define-fptr-set!-inline #t $fptr-set-integer-40! 'integer-40 build-object-set!) - (define-fptr-set!-inline #t $fptr-set-unsigned-40! 'unsigned-40 build-object-set!) - (define-fptr-set!-inline #t $fptr-set-swap-integer-40! 'integer-40 build-swap-object-set!) - (define-fptr-set!-inline #t $fptr-set-swap-unsigned-40! 'unsigned-40 build-swap-object-set!) - - (define-fptr-set!-inline #t $fptr-set-integer-48! 'integer-48 build-object-set!) - (define-fptr-set!-inline #t $fptr-set-unsigned-48! 'unsigned-48 build-object-set!) - (define-fptr-set!-inline #t $fptr-set-swap-integer-48! 'integer-48 build-swap-object-set!) - (define-fptr-set!-inline #t $fptr-set-swap-unsigned-48! 'unsigned-48 build-swap-object-set!) - - (define-fptr-set!-inline #t $fptr-set-integer-56! 'integer-56 build-object-set!) - (define-fptr-set!-inline #t $fptr-set-unsigned-56! 'unsigned-56 build-object-set!) - (define-fptr-set!-inline #t $fptr-set-swap-integer-56! 'integer-56 build-swap-object-set!) - (define-fptr-set!-inline #t $fptr-set-swap-unsigned-56! 'unsigned-56 build-swap-object-set!) - - (define-fptr-set!-inline #t $fptr-set-integer-64! 'integer-64 build-object-set!) - (define-fptr-set!-inline #t $fptr-set-unsigned-64! 'unsigned-64 build-object-set!) - (define-fptr-set!-inline #t $fptr-set-swap-integer-64! 'integer-64 build-swap-object-set!) - (define-fptr-set!-inline #t $fptr-set-swap-unsigned-64! 'unsigned-64 build-swap-object-set!) - - (define-fptr-set!-inline #f $fptr-set-double-float! 'double-float build-object-set!) - (define-fptr-set!-inline #t $fptr-set-swap-double-float! 'double-float build-swap-object-set!) - - (define-fptr-set!-inline #f $fptr-set-single-float! 'single-float build-object-set!) - - (define-fptr-set!-inline #f $fptr-set-char! 'unsigned-8 build-object-set! - (lambda (z) (build-char->integer z))) - - (define-fptr-set!-inline #f $fptr-set-wchar! - (constant-case wchar-bits - [(16) 'unsigned-16] - [(32) 'unsigned-32]) - build-object-set! - (lambda (z) (build-char->integer z))) - (define-fptr-set!-inline #f $fptr-set-swap-wchar! - (constant-case wchar-bits - [(16) 'unsigned-16] - [(32) 'unsigned-32]) - build-swap-object-set! - (lambda (z) (build-char->integer z))) - - (define-fptr-set!-inline #f $fptr-set-boolean! - (constant-case int-bits - [(32) 'unsigned-32] - [(64) 'unsigned-64]) - build-object-set! - (lambda (z) `(if ,z (immediate ,(fix 1)) (immediate ,(fix 0))))) - (define-fptr-set!-inline #f $fptr-set-swap-boolean! - (constant-case int-bits - [(32) 'unsigned-32] - [(64) 'unsigned-64]) - build-swap-object-set! - (lambda (z) `(if ,z (immediate ,(fix 1)) (immediate ,(fix 0))))) - - (define-fptr-set!-inline #f $fptr-set-fixnum! 'fixnum build-object-set!) - (define-fptr-set!-inline #f $fptr-set-swap-fixnum! 'fixnum build-swap-object-set!)) - (let () - (define-syntax define-fptr-bits-ref-inline - (lambda (x) - (syntax-case x () - [(_ name signed? type swapped?) - #'(define-inline 3 name - [(e-fptr e-offset e-start e-end) - (and (fixnum-constant? e-start) (fixnum-constant? e-end) - (let ([imm-start (constant-value e-start)] [imm-end (constant-value e-end)]) - (and (<= (type->width 'type) (constant ptr-bits)) - (and (fx>= imm-start 0) (fx> imm-end imm-start) (fx<= imm-end (constant ptr-bits))) - ((if signed? fx<= fx<) (fx- imm-end imm-start) (constant fixnum-bits)) - (let-values ([(e-index imm-offset) (offset-expr->index+offset e-offset)]) - (bind #f (e-index) - (build-int-load swapped? 'type ($extract-fptr-address e-fptr) e-index imm-offset - (lambda (x) - ((if signed? extract-signed-bitfield extract-unsigned-bitfield) #t imm-start imm-end x))))))))])]))) - - (define-fptr-bits-ref-inline $fptr-ref-ibits-unsigned-8 #t unsigned-8 #f) - (define-fptr-bits-ref-inline $fptr-ref-ubits-unsigned-8 #f unsigned-8 #f) - - (define-fptr-bits-ref-inline $fptr-ref-ibits-unsigned-16 #t unsigned-16 #f) - (define-fptr-bits-ref-inline $fptr-ref-ubits-unsigned-16 #f unsigned-16 #f) - (define-fptr-bits-ref-inline $fptr-ref-ibits-swap-unsigned-16 #t unsigned-16 #t) - (define-fptr-bits-ref-inline $fptr-ref-ubits-swap-unsigned-16 #f unsigned-16 #t) - - (define-fptr-bits-ref-inline $fptr-ref-ibits-unsigned-24 #t unsigned-24 #f) - (define-fptr-bits-ref-inline $fptr-ref-ubits-unsigned-24 #f unsigned-24 #f) - (define-fptr-bits-ref-inline $fptr-ref-ibits-swap-unsigned-24 #t unsigned-24 #t) - (define-fptr-bits-ref-inline $fptr-ref-ubits-swap-unsigned-24 #f unsigned-24 #t) - - (define-fptr-bits-ref-inline $fptr-ref-ibits-unsigned-32 #t unsigned-32 #f) - (define-fptr-bits-ref-inline $fptr-ref-ubits-unsigned-32 #f unsigned-32 #f) - (define-fptr-bits-ref-inline $fptr-ref-ibits-swap-unsigned-32 #t unsigned-32 #t) - (define-fptr-bits-ref-inline $fptr-ref-ubits-swap-unsigned-32 #f unsigned-32 #t) - - (define-fptr-bits-ref-inline $fptr-ref-ibits-unsigned-40 #t unsigned-40 #f) - (define-fptr-bits-ref-inline $fptr-ref-ubits-unsigned-40 #f unsigned-40 #f) - (define-fptr-bits-ref-inline $fptr-ref-ibits-swap-unsigned-40 #t unsigned-40 #t) - (define-fptr-bits-ref-inline $fptr-ref-ubits-swap-unsigned-40 #f unsigned-40 #t) - - (define-fptr-bits-ref-inline $fptr-ref-ibits-unsigned-48 #t unsigned-48 #f) - (define-fptr-bits-ref-inline $fptr-ref-ubits-unsigned-48 #f unsigned-48 #f) - (define-fptr-bits-ref-inline $fptr-ref-ibits-swap-unsigned-48 #t unsigned-48 #t) - (define-fptr-bits-ref-inline $fptr-ref-ubits-swap-unsigned-48 #f unsigned-48 #t) - - (define-fptr-bits-ref-inline $fptr-ref-ibits-unsigned-56 #t unsigned-56 #f) - (define-fptr-bits-ref-inline $fptr-ref-ubits-unsigned-56 #f unsigned-56 #f) - (define-fptr-bits-ref-inline $fptr-ref-ibits-swap-unsigned-56 #t unsigned-56 #t) - (define-fptr-bits-ref-inline $fptr-ref-ubits-swap-unsigned-56 #f unsigned-56 #t) - - (define-fptr-bits-ref-inline $fptr-ref-ibits-unsigned-64 #t unsigned-64 #f) - (define-fptr-bits-ref-inline $fptr-ref-ubits-unsigned-64 #f unsigned-64 #f) - (define-fptr-bits-ref-inline $fptr-ref-ibits-swap-unsigned-64 #t unsigned-64 #t) - (define-fptr-bits-ref-inline $fptr-ref-ubits-swap-unsigned-64 #f unsigned-64 #t)) - (let () - (define-syntax define-fptr-bits-set-inline - (lambda (x) - (syntax-case x () - [(_ check-64? name type swapped?) - (with-syntax ([(checks ...) #'((fixnum-constant? e-start) (fixnum-constant? e-end))]) - (with-syntax ([(checks ...) (if (datum check-64?) - #'((fx>= (constant ptr-bits) 64) checks ...) - #'(checks ...))]) - #`(define-inline 3 name - [(e-fptr e-offset e-start e-end e-val) - (and - checks ... - (let ([imm-start (constant-value e-start)] [imm-end (constant-value e-end)]) - (and (<= (type->width 'type) (constant ptr-bits)) - (and (fx>= imm-start 0) (fx> imm-end imm-start) (fx<= imm-end (constant ptr-bits))) - (fx< (fx- imm-end imm-start) (constant fixnum-bits)) - (let-values ([(e-index imm-offset) (offset-expr->index+offset e-offset)]) - (bind #t (e-index) - (bind #f (e-val) - (bind #t ([e-addr ($extract-fptr-address e-fptr)]) - (build-int-load swapped? 'type e-addr e-index imm-offset - (lambda (x) - (build-int-store swapped? 'type e-addr e-index imm-offset - (insert-bitfield #t imm-start imm-end (type->width 'type) x - e-val)))))))))))])))]))) - - (define-fptr-bits-set-inline #f $fptr-set-bits-unsigned-8! unsigned-8 #f) - - (define-fptr-bits-set-inline #f $fptr-set-bits-unsigned-16! unsigned-16 #f) - (define-fptr-bits-set-inline #f $fptr-set-bits-swap-unsigned-16! unsigned-16 #t) - - (define-fptr-bits-set-inline #f $fptr-set-bits-unsigned-24! unsigned-24 #f) - (define-fptr-bits-set-inline #f $fptr-set-bits-swap-unsigned-24! unsigned-24 #t) - - (define-fptr-bits-set-inline #f $fptr-set-bits-unsigned-32! unsigned-32 #f) - (define-fptr-bits-set-inline #f $fptr-set-bits-swap-unsigned-32! unsigned-32 #t) - - (define-fptr-bits-set-inline #f $fptr-set-bits-unsigned-40! unsigned-40 #f) - (define-fptr-bits-set-inline #f $fptr-set-bits-swap-unsigned-40! unsigned-40 #t) - - (define-fptr-bits-set-inline #f $fptr-set-bits-unsigned-48! unsigned-48 #f) - (define-fptr-bits-set-inline #f $fptr-set-bits-swap-unsigned-48! unsigned-48 #t) - - (define-fptr-bits-set-inline #f $fptr-set-bits-unsigned-56! unsigned-56 #f) - (define-fptr-bits-set-inline #f $fptr-set-bits-swap-unsigned-56! unsigned-56 #t) - - (define-fptr-bits-set-inline #t $fptr-set-bits-unsigned-64! unsigned-64 #f) - (define-fptr-bits-set-inline #t $fptr-set-bits-swap-unsigned-64! unsigned-64 #t)) - (define-inline 3 $fptr-locked-decr! - [(e-fptr e-offset) - `(seq - ,(let-values ([(e-index imm-offset) (offset-expr->index+offset e-offset)]) - (%inline locked-decr! - ,($extract-fptr-address e-fptr) - ,e-index (immediate ,imm-offset))) - (inline ,(make-info-condition-code 'eq? #f #t) ,%condition-code))]) - (define-inline 3 $fptr-locked-incr! - [(e-fptr e-offset) - `(seq - ,(let-values ([(e-index imm-offset) (offset-expr->index+offset e-offset)]) - (%inline locked-incr! - ,($extract-fptr-address e-fptr) - ,e-index (immediate ,imm-offset))) - (inline ,(make-info-condition-code 'eq? #f #t) ,%condition-code))]) - (let () - (define clear-lock - (lambda (e-fptr e-offset) - (let ([lock-type (constant-case ptr-bits [(32) 'integer-32] [(64) 'integer-64])]) - (let-values ([(e-index imm-offset) (offset-expr->index+offset e-offset)]) - `(inline ,(make-info-load lock-type #f) ,%store - ,($extract-fptr-address e-fptr) - ,e-index (immediate ,imm-offset) (immediate 0)))))) - (define-inline 3 $fptr-init-lock! - [(e-fptr e-offset) (clear-lock e-fptr e-offset)]) - (define-inline 3 $fptr-unlock! - [(e-fptr e-offset) (clear-lock e-fptr e-offset)])) - (define-inline 3 $fptr-lock! - [(e-fptr e-offset) - (let-values ([(e-index imm-offset) (offset-expr->index+offset e-offset)]) - (bind #t ([e-base ($extract-fptr-address e-fptr)]) - (%inline lock! ,e-base ,e-index (immediate ,imm-offset))))]) - (define-inline 3 $fptr-spin-lock! - [(e-fptr e-offset) - (let-values ([(e-index imm-offset) (offset-expr->index+offset e-offset)]) - (bind #t ([e-base ($extract-fptr-address e-fptr)]) - (bind #t (e-index) - (let ([L1 (make-local-label 'L1)] [L2 (make-local-label 'L2)]) - `(label ,L1 - (if ,(%inline lock! ,e-base ,e-index (immediate ,imm-offset)) - ,(%constant svoid) - (seq - (pariah) - (label ,L2 - (seq - ,(%inline pause) - (if ,(%inline eq? (mref ,e-base ,e-index ,imm-offset) (immediate 0)) - (goto ,L1) - (goto ,L2)))))))))))])) - (let () - (define build-port-flags-set? - (lambda (e-p e-flags) - (%inline logtest - ,(%mref ,e-p ,(constant port-type-disp)) - ,(nanopass-case (L7 Expr) e-flags - [(quote ,d) `(immediate ,(ash d (constant port-flags-offset)))] - [else (%inline sll ,e-flags - (immediate ,(fx- (constant port-flags-offset) (constant fixnum-offset))))])))) - (define build-port-input-empty? - (lambda (e-p) - (%inline eq? - ,(%mref ,e-p ,(constant port-icount-disp)) - (immediate 0)))) - (define-inline 3 binary-port? - [(e-p) (build-port-flags-set? e-p `(quote ,(constant port-flag-binary)))]) - (define-inline 3 textual-port? - [(e-p) (build-not (build-port-flags-set? e-p `(quote ,(constant port-flag-binary))))]) - (define-inline 3 port-closed? - [(e-p) (build-port-flags-set? e-p `(quote ,(constant port-flag-closed)))]) - (define-inline 3 $port-flags-set? - [(e-p e-flags) (build-port-flags-set? e-p e-flags)]) - (define-inline 3 port-eof? - [(e-p) - (bind #t (e-p) - `(if ,(build-port-input-empty? e-p) - (if ,(build-port-flags-set? e-p `(quote ,(constant port-flag-eof))) - (immediate ,(constant strue)) - ,(build-libcall #t src sexpr unsafe-port-eof? e-p)) - (immediate ,(constant sfalse))))]) - (define-inline 2 port-eof? - [(e-p) - (let ([Llib (make-local-label 'Llib)]) - (bind #t (e-p) - `(if ,(%type-check mask-typed-object type-typed-object ,e-p) - ,(bind #t ([t0 (%mref ,e-p ,(constant typed-object-type-disp))]) - `(if ,(%type-check mask-input-port type-input-port ,t0) - (if ,(build-port-input-empty? e-p) - (if ,(%inline logtest ,t0 - (immediate ,(ash (constant port-flag-eof) (constant port-flags-offset)))) - (immediate ,(constant strue)) - (label ,Llib ,(build-libcall #t src sexpr safe-port-eof? e-p))) - (immediate ,(constant sfalse))) - (goto ,Llib))) - (goto ,Llib))))]) - (define-inline 3 port-input-empty? - [(e-p) (build-port-input-empty? e-p)]) - (define-inline 3 port-output-full? - [(e-p) - (%inline eq? - ,(%mref ,e-p ,(constant port-ocount-disp)) - (immediate 0))])) - (let () - (define build-set-port-flags! - (lambda (e-p e-flags) - (bind #t (e-p) - `(set! ,(%mref ,e-p ,(constant port-type-disp)) - ,(%inline logor - ,(%mref ,e-p ,(constant port-type-disp)) - ,(nanopass-case (L7 Expr) e-flags - [(quote ,d) `(immediate ,(ash d (constant port-flags-offset)))] - [else - (translate e-flags - (constant fixnum-offset) - (constant port-flags-offset))])))))) - (define build-reset-port-flags! - (lambda (e-p e-flags) - (bind #t (e-p) - `(set! ,(%mref ,e-p ,(constant port-type-disp)) - ,(%inline logand - ,(%mref ,e-p ,(constant port-type-disp)) - ,(nanopass-case (L7 Expr) e-flags - [(quote ,d) `(immediate ,(lognot (ash d (constant port-flags-offset))))] - [else - (%inline lognot - ,(translate e-flags - (constant fixnum-offset) - (constant port-flags-offset)))])))))) - (define-inline 3 $set-port-flags! - [(e-p e-flags) (build-set-port-flags! e-p e-flags)]) - (define-inline 3 $reset-port-flags! - [(e-p e-flags) (build-reset-port-flags! e-p e-flags)]) - (define-inline 3 mark-port-closed! - [(e-p) (build-set-port-flags! e-p `(quote ,(constant port-flag-closed)))]) - (let () - (define (go e-p e-bool flag) - (let ([e-flags `(quote ,flag)]) - (nanopass-case (L7 Expr) e-bool - [(quote ,d) - ((if d build-set-port-flags! build-reset-port-flags!) e-p e-flags)] - [else - (bind #t (e-p) - `(if ,e-bool - ,(build-set-port-flags! e-p e-flags) - ,(build-reset-port-flags! e-p e-flags)))]))) - (define-inline 3 set-port-bol! - [(e-p e-bool) (go e-p e-bool (constant port-flag-bol))]) - (define-inline 3 set-port-eof! - [(e-p e-bool) (go e-p e-bool (constant port-flag-eof))]))) - (let () - (define (build-port-input-size port-type e-p) - (bind #t (e-p) - (translate - (%inline - - ,(%inline - - ,(%mref ,e-p ,(constant port-ilast-disp)) - ,(%mref ,e-p ,(constant port-ibuffer-disp))) - (immediate - ,(if (eq? port-type 'textual) - (constant string-data-disp) - (constant bytevector-data-disp)))) - (if (eq? port-type 'textual) (constant string-char-offset) 0) - (constant fixnum-offset)))) - (define-inline 3 textual-port-input-size - [(e-p) (build-port-input-size 'textual e-p)]) - (define-inline 3 binary-port-input-size - [(e-p) (build-port-input-size 'binary e-p)])) - (let () - (define (build-port-output-size port-type e-p) - (bind #t (e-p) - (translate - (%inline - - ,(%inline - - ,(%mref ,e-p ,(constant port-olast-disp)) - ,(%mref ,e-p ,(constant port-obuffer-disp))) - (immediate - ,(if (eq? port-type 'textual) - (constant string-data-disp) - (constant bytevector-data-disp)))) - (if (eq? port-type 'textual) (constant string-char-offset) 0) - (constant fixnum-offset)))) - (define-inline 3 textual-port-output-size - [(e-p) (build-port-output-size 'textual e-p)]) - (define-inline 3 binary-port-output-size - [(e-p) (build-port-output-size 'binary e-p)])) - (let () - (define (build-port-input-index port-type e-p) - (bind #t (e-p) - (translate - ; TODO: use lea2? - (%inline + - ,(%inline - - ,(%inline - - ,(%mref ,e-p ,(constant port-ilast-disp)) - ,(%mref ,e-p ,(constant port-ibuffer-disp))) - (immediate - ,(if (eq? port-type 'textual) - (constant string-data-disp) - (constant bytevector-data-disp)))) - ,(%mref ,e-p ,(constant port-icount-disp))) - (if (eq? port-type 'textual) (constant string-char-offset) 0) - (constant fixnum-offset)))) - (define-inline 3 textual-port-input-index - [(e-p) (build-port-input-index 'textual e-p)]) - (define-inline 3 binary-port-input-index - [(e-p) (build-port-input-index 'binary e-p)])) - (let () - (define (build-port-output-index port-type e-p) - (bind #t (e-p) - (translate - (%inline + - ,(%inline - - ,(%inline - - ,(%mref ,e-p ,(constant port-olast-disp)) - ,(%mref ,e-p ,(constant port-obuffer-disp))) - (immediate - ,(if (eq? port-type 'textual) - (constant string-data-disp) - (constant bytevector-data-disp)))) - ,(%mref ,e-p ,(constant port-ocount-disp))) - (if (eq? port-type 'textual) (constant string-char-offset) 0) - (constant fixnum-offset)))) - (define-inline 3 textual-port-output-index - [(e-p) (build-port-output-index 'textual e-p)]) - (define-inline 3 binary-port-output-index - [(e-p) (build-port-output-index 'binary e-p)])) - (let () - (define (build-port-input-count port-type e-p) - (bind #t (e-p) - (translate - (%inline - - (immediate 0) - ,(%mref ,e-p ,(constant port-icount-disp))) - (if (eq? port-type 'textual) (constant string-char-offset) 0) - (constant fixnum-offset)))) - (define-inline 3 textual-port-input-count - [(e-p) (build-port-input-count 'textual e-p)]) - (define-inline 3 binary-port-input-count - [(e-p) (build-port-input-count 'binary e-p)])) - (let () - (define (build-port-output-count port-type e-p) - (bind #t (e-p) - (translate - (%inline - - (immediate 0) - ,(%mref ,e-p ,(constant port-ocount-disp))) - (if (eq? port-type 'textual) (constant string-char-offset) 0) - (constant fixnum-offset)))) - (define-inline 3 textual-port-output-count - [(e-p) (build-port-output-count 'textual e-p)]) - (define-inline 3 binary-port-output-count - [(e-p) (build-port-output-count 'binary e-p)])) - (let () - (define (build-set-port-input-size! port-type e-p e-x) - ; actually, set last to buffer[0] + size; count to size - (bind #t (e-p) - (bind #t ([e-x (translate e-x - (constant fixnum-offset) - (if (eq? port-type 'textual) (constant string-char-offset) 0))]) - `(seq - (set! ,(%mref ,e-p ,(constant port-icount-disp)) - ,(%inline - (immediate 0) ,e-x)) - (set! ,(%mref ,e-p ,(constant port-ilast-disp)) - ,(%inline + - ,(%inline + - ,(%mref ,e-p ,(constant port-ibuffer-disp)) - (immediate - ,(if (eq? port-type 'textual) - (constant string-data-disp) - (constant bytevector-data-disp)))) - ,e-x)))))) - (define-inline 3 set-textual-port-input-size! - [(e-p e-x) (build-set-port-input-size! 'textual e-p e-x)]) - (define-inline 3 set-binary-port-input-size! - [(e-p e-x) (build-set-port-input-size! 'binary e-p e-x)])) - (let () - (define (build-set-port-output-size! port-type e-p e-x) - ; actually, set last to buffer[0] + size; count to size - (bind #t (e-p) - (bind #t ([e-x (translate e-x - (constant fixnum-offset) - (if (eq? port-type 'textual) (constant string-char-offset) 0))]) - `(seq - (set! ,(%mref ,e-p ,(constant port-ocount-disp)) - ,(%inline - (immediate 0) ,e-x)) - (set! ,(%mref ,e-p ,(constant port-olast-disp)) - ,(%inline + - ,(%inline + - ,(%mref ,e-p ,(constant port-obuffer-disp)) - (immediate - ,(if (eq? port-type 'textual) - (constant string-data-disp) - (constant bytevector-data-disp)))) - ,e-x)))))) - (define-inline 3 set-textual-port-output-size! - [(e-p e-x) (build-set-port-output-size! 'textual e-p e-x)]) - (define-inline 3 set-binary-port-output-size! - [(e-p e-x) (build-set-port-output-size! 'binary e-p e-x)])) - (let () - (define (build-set-port-input-index! port-type e-p e-x) - ; actually, set count to index - size, where size = last - buffer[0] - (bind #t (e-p) - `(set! ,(%mref ,e-p ,(constant port-icount-disp)) - ,(%inline - - ,(translate e-x - (constant fixnum-offset) - (if (eq? port-type 'textual) (constant string-char-offset) 0)) - ,(%inline - - ,(%mref ,e-p ,(constant port-ilast-disp)) - ,(%inline + - ,(%mref ,e-p ,(constant port-ibuffer-disp)) - (immediate - ,(if (eq? port-type 'textual) - (constant string-data-disp) - (constant bytevector-data-disp))))))))) - (define-inline 3 set-textual-port-input-index! - [(e-p e-x) (build-set-port-input-index! 'textual e-p e-x)]) - (define-inline 3 set-binary-port-input-index! - [(e-p e-x) (build-set-port-input-index! 'binary e-p e-x)])) - (let () - (define (build-set-port-output-index! port-type e-p e-x) - ; actually, set count to index - size, where size = last - buffer[0] - (bind #t (e-p) - `(set! ,(%mref ,e-p ,(constant port-ocount-disp)) - ,(%inline - - ,(translate e-x - (constant fixnum-offset) - (if (eq? port-type 'textual) (constant string-char-offset) 0)) - ,(%inline - - ,(%mref ,e-p ,(constant port-olast-disp)) - ,(%inline + - ,(%mref ,e-p ,(constant port-obuffer-disp)) - (immediate - ,(if (eq? port-type 'textual) - (constant string-data-disp) - (constant bytevector-data-disp))))))))) - (define-inline 3 set-textual-port-output-index! - [(e-p e-x) (build-set-port-output-index! 'textual e-p e-x)]) - (define-inline 3 set-binary-port-output-index! - [(e-p e-x) (build-set-port-output-index! 'binary e-p e-x)])) - (let () - (define (make-build-set-port-buffer! port-type ibuffer-disp icount-disp ilast-disp) - (lambda (e-p e-b new?) - (bind #t (e-p e-b) - `(seq - ,(if new? - `(set! ,(%mref ,e-p ,ibuffer-disp) ,e-b) - (build-dirty-store e-p ibuffer-disp e-b)) - ,(bind #t ([e-length (if (eq? port-type 'textual) - (translate - (%inline logand - ,(%mref ,e-b ,(constant string-type-disp)) - (immediate ,(fx- (expt 2 (constant string-length-offset))))) - (constant string-length-offset) - (constant string-char-offset)) - (%inline srl - ,(%mref ,e-b ,(constant bytevector-type-disp)) - ,(%constant bytevector-length-offset)))]) - `(seq - (set! ,(%mref ,e-p ,icount-disp) - ,(%inline - (immediate 0) ,e-length)) - (set! ,(%mref ,e-p ,ilast-disp) - ,(%lea ,e-b ,e-length - (if (eq? port-type 'textual) - (constant string-data-disp) - (constant bytevector-data-disp)))))))))) - (define (make-port e-name e-handler e-ib e-ob e-info flags set-ibuf! set-obuf!) - (bind #f (e-name e-handler e-info e-ib e-ob) - (bind #t ([e-p (%constant-alloc type-typed-object (constant size-port))]) - (%seq - (set! ,(%mref ,e-p ,(constant port-type-disp)) (immediate ,flags)) - (set! ,(%mref ,e-p ,(constant port-handler-disp)) ,e-handler) - (set! ,(%mref ,e-p ,(constant port-name-disp)) ,e-name) - (set! ,(%mref ,e-p ,(constant port-info-disp)) ,e-info) - ,(set-ibuf! e-p e-ib #t) - ,(set-obuf! e-p e-ob #t) - ,e-p)))) - (define (make-build-clear-count count-disp) - (lambda (e-p e-b new?) - `(set! ,(%mref ,e-p ,count-disp) (immediate 0)))) - (let () - (define build-set-textual-port-input-buffer! - (make-build-set-port-buffer! 'textual - (constant port-ibuffer-disp) - (constant port-icount-disp) - (constant port-ilast-disp))) - (define build-set-textual-port-output-buffer! - (make-build-set-port-buffer! 'textual - (constant port-obuffer-disp) - (constant port-ocount-disp) - (constant port-olast-disp))) - (define-inline 3 set-textual-port-input-buffer! - [(e-p e-b) (build-set-textual-port-input-buffer! e-p e-b #f)]) - (define-inline 3 set-textual-port-output-buffer! - [(e-p e-b) (build-set-textual-port-output-buffer! e-p e-b #f)]) - (let () - (define (go e-name e-handler e-ib e-info) - (make-port e-name e-handler e-ib `(quote "") e-info - (fxlogor (constant type-input-port) (constant PORT-FLAG-INPUT-MODE)) - build-set-textual-port-input-buffer! - (make-build-clear-count (constant port-ocount-disp)))) - (define-inline 3 $make-textual-input-port - [(e-name e-handler e-ib) (go e-name e-handler e-ib `(quote #f))] - [(e-name e-handler e-ib e-info) (go e-name e-handler e-ib e-info)])) - (let () - (define (go e-name e-handler e-ob e-info) - (make-port e-name e-handler `(quote "") e-ob e-info - (constant type-output-port) - (make-build-clear-count (constant port-icount-disp)) - build-set-textual-port-output-buffer!)) - (define-inline 3 $make-textual-output-port - [(e-name e-handler e-ob) (go e-name e-handler e-ob `(quote #f))] - [(e-name e-handler e-ob e-info) (go e-name e-handler e-ob e-info)])) - (let () - (define (go e-name e-handler e-ib e-ob e-info) - (make-port e-name e-handler e-ib e-ob e-info - (constant type-io-port) - build-set-textual-port-input-buffer! - build-set-textual-port-output-buffer!)) - (define-inline 3 $make-textual-input/output-port - [(e-name e-handler e-ib e-ob) (go e-name e-handler e-ib e-ob `(quote #f))] - [(e-name e-handler e-ib e-ob e-info) (go e-name e-handler e-ib e-ob e-info)]))) - (let () - (define build-set-binary-port-input-buffer! - (make-build-set-port-buffer! 'binary - (constant port-ibuffer-disp) - (constant port-icount-disp) - (constant port-ilast-disp))) - (define build-set-binary-port-output-buffer! - (make-build-set-port-buffer! 'binary - (constant port-obuffer-disp) - (constant port-ocount-disp) - (constant port-olast-disp))) - (define-inline 3 set-binary-port-input-buffer! - [(e-p e-b) (build-set-binary-port-input-buffer! e-p e-b #f)]) - (define-inline 3 set-binary-port-output-buffer! - [(e-p e-b) (build-set-binary-port-output-buffer! e-p e-b #f)]) - (let () - (define (go e-name e-handler e-ib e-info) - (make-port e-name e-handler e-ib `(quote #vu8()) e-info - (fxlogor (constant type-input-port) (constant PORT-FLAG-INPUT-MODE) (constant PORT-FLAG-BINARY)) - build-set-binary-port-input-buffer! - (make-build-clear-count (constant port-ocount-disp)))) - (define-inline 3 $make-binary-input-port - [(e-name e-handler e-ib) (go e-name e-handler e-ib `(quote #f))] - [(e-name e-handler e-ib e-info) (go e-name e-handler e-ib e-info)])) - (let () - (define (go e-name e-handler e-ob e-info) - (make-port e-name e-handler `(quote #vu8()) e-ob e-info - (fxlogor (constant type-output-port) (constant PORT-FLAG-BINARY)) - (make-build-clear-count (constant port-icount-disp)) - build-set-binary-port-output-buffer!)) - (define-inline 3 $make-binary-output-port - [(e-name e-handler e-ob) (go e-name e-handler e-ob `(quote #f))] - [(e-name e-handler e-ob e-info) (go e-name e-handler e-ob e-info)])) - (let () - (define (go e-name e-handler e-ib e-ob e-info) - (make-port e-name e-handler e-ib e-ob e-info - (fxlogor (constant type-io-port) (constant PORT-FLAG-BINARY)) - build-set-binary-port-input-buffer! - build-set-binary-port-output-buffer!)) - (define-inline 3 $make-binary-input/output-port - [(e-name e-handler e-ib e-ob) (go e-name e-handler e-ib e-ob `(quote #f))] - [(e-name e-handler e-ib e-ob e-info) (go e-name e-handler e-ib e-ob e-info)])))) - (let () - (define build-fxvector-ref-check (build-ref-check fxvector-type-disp maximum-fxvector-length fxvector-length-offset type-fxvector mask-fxvector fxvector-immutable-flag)) - (define build-fxvector-set!-check (build-ref-check fxvector-type-disp maximum-fxvector-length fxvector-length-offset type-mutable-fxvector mask-mutable-fxvector fxvector-immutable-flag)) - (define-inline 2 $fxvector-ref-check? - [(e-fv e-i) (bind #t (e-fv e-i) (build-fxvector-ref-check e-fv e-i #f))]) - (define-inline 2 $fxvector-set!-check? - [(e-fv e-i) (bind #t (e-fv e-i) (build-fxvector-set!-check e-fv e-i #f))]) - (let () - (define (go e-fv e-i) - (cond - [(expr->index e-i 1 (constant maximum-fxvector-length)) => - (lambda (index) - (%mref ,e-fv - ,(+ (fix index) (constant fxvector-data-disp))))] - [else (%mref ,e-fv ,e-i ,(constant fxvector-data-disp))])) - (define-inline 3 fxvector-ref - [(e-fv e-i) (go e-fv e-i)]) - (define-inline 2 fxvector-ref - [(e-fv e-i) - (bind #t (e-fv e-i) - `(if ,(build-fxvector-ref-check e-fv e-i #f) - ,(go e-fv e-i) - ,(build-libcall #t src sexpr fxvector-ref e-fv e-i)))])) - (let () - (define (go e-fv e-i e-new) - `(set! - ,(cond - [(expr->index e-i 1 (constant maximum-fxvector-length)) => - (lambda (index) - (%mref ,e-fv - ,(+ (fix index) (constant fxvector-data-disp))))] - [else (%mref ,e-fv ,e-i ,(constant fxvector-data-disp))]) - ,e-new)) - (define-inline 3 fxvector-set! - [(e-fv e-i e-new) - (go e-fv e-i e-new)]) - (define-inline 2 fxvector-set! - [(e-fv e-i e-new) - (bind #t (e-fv e-i e-new) - `(if ,(build-fxvector-set!-check e-fv e-i e-new) - ,(go e-fv e-i e-new) - ,(build-libcall #t src sexpr fxvector-set! e-fv e-i e-new)))]) - (define-inline 3 $fxvector-set-immutable! - [(e-fv) ((build-set-immutable! fxvector-type-disp fxvector-immutable-flag) e-fv)]))) - (let () - (define build-string-ref-check - (lambda (e-s e-i) - ((build-ref-check string-type-disp maximum-string-length string-length-offset type-string mask-string string-immutable-flag) e-s e-i #f))) - (define build-string-set!-check - (lambda (e-s e-i) - ((build-ref-check string-type-disp maximum-string-length string-length-offset type-mutable-string mask-mutable-string string-immutable-flag) e-s e-i #f))) - (define-inline 2 $string-ref-check? - [(e-s e-i) (bind #t (e-s e-i) (build-string-ref-check e-s e-i))]) - (define-inline 2 $string-set!-check? - [(e-s e-i) (bind #t (e-s e-i) (build-string-set!-check e-s e-i))]) - (let () - (define (go e-s e-i) - (cond - [(expr->index e-i 1 (constant maximum-string-length)) => - (lambda (index) - `(inline ,(make-info-load (string-char-type) #f) ,%load ,e-s ,%zero - (immediate ,(+ (* (constant string-char-bytes) index) (constant string-data-disp)))))] - [else - `(inline ,(make-info-load (string-char-type) #f) ,%load ,e-s - ,(translate e-i - (constant fixnum-offset) - (constant string-char-offset)) - ,(%constant string-data-disp))])) - (define-inline 3 string-ref - [(e-s e-i) (go e-s e-i)]) - (define-inline 2 string-ref - [(e-s e-i) - (bind #t (e-s e-i) - `(if ,(build-string-ref-check e-s e-i) - ,(go e-s e-i) - ,(build-libcall #t src sexpr string-ref e-s e-i)))])) - (let () - (define (go e-s e-i e-new) - (cond - [(expr->index e-i 1 (constant maximum-string-length)) => - (lambda (index) - `(inline ,(make-info-load (string-char-type) #f) ,%store ,e-s ,%zero - (immediate ,(+ (* (constant string-char-bytes) index) (constant string-data-disp))) - ,e-new))] - [else - `(inline ,(make-info-load (string-char-type) #f) ,%store ,e-s - ,(translate e-i - (constant fixnum-offset) - (constant string-char-offset)) - ,(%constant string-data-disp) - ,e-new)])) - (define-inline 3 string-set! - [(e-s e-i e-new) (go e-s e-i e-new)]) - (define-inline 2 string-set! - [(e-s e-i e-new) - (bind #t (e-s e-i e-new) - `(if ,(let ([e-ref-check (build-string-set!-check e-s e-i)]) - (if (constant? char? e-new) - e-ref-check - (build-and e-ref-check (%type-check mask-char type-char ,e-new)))) - ,(go e-s e-i e-new) - ,(build-libcall #t src sexpr string-set! e-s e-i e-new)))]) - (define-inline 3 $string-set-immutable! - [(e-s) ((build-set-immutable! string-type-disp string-immutable-flag) e-s)]))) - (let () - (define build-vector-ref-check (build-ref-check vector-type-disp maximum-vector-length vector-length-offset type-vector mask-vector vector-immutable-flag)) - (define build-vector-set!-check (build-ref-check vector-type-disp maximum-vector-length vector-length-offset type-mutable-vector mask-mutable-vector vector-immutable-flag)) - (define-inline 2 $vector-ref-check? - [(e-v e-i) (bind #t (e-v e-i) (build-vector-ref-check e-v e-i #f))]) - (define-inline 2 $vector-set!-check? - [(e-v e-i) (bind #t (e-v e-i) (build-vector-set!-check e-v e-i #f))]) - (let () - (define (go e-v e-i) - (nanopass-case (L7 Expr) e-i - [(quote ,d) - (guard (target-fixnum? d)) - (%mref ,e-v ,(+ (fix d) (constant vector-data-disp)))] - [else (%mref ,e-v ,e-i ,(constant vector-data-disp))])) - (define-inline 3 vector-ref - [(e-v e-i) (go e-v e-i)]) - (define-inline 2 vector-ref - [(e-v e-i) - (bind #t (e-v e-i) - `(if ,(build-vector-ref-check e-v e-i #f) - ,(go e-v e-i) - ,(build-libcall #t src sexpr vector-ref e-v e-i)))])) - (let () - (define (go e-v e-i e-new) - (nanopass-case (L7 Expr) e-i - [(quote ,d) - (guard (target-fixnum? d)) - (build-dirty-store e-v (+ (fix d) (constant vector-data-disp)) e-new)] - [else (build-dirty-store e-v e-i (constant vector-data-disp) e-new)])) - (define-inline 3 vector-set! - [(e-v e-i e-new) (go e-v e-i e-new)]) - (define-inline 2 vector-set! - [(e-v e-i e-new) - (bind #t (e-v e-i e-new) - `(if ,(build-vector-set!-check e-v e-i #f) - ,(go e-v e-i e-new) - ,(build-libcall #t src sexpr vector-set! e-v e-i e-new)))]) - (define-inline 3 $vector-set-immutable! - [(e-fv) ((build-set-immutable! vector-type-disp vector-immutable-flag) e-fv)])) - (let () - (define (go e-v e-i e-old e-new) - (nanopass-case (L7 Expr) e-i - [(quote ,d) - (guard (target-fixnum? d)) - (build-dirty-store e-v %zero (+ (fix d) (constant vector-data-disp)) e-new (make-build-cas e-old) build-cas-seq)] - [else (build-dirty-store e-v e-i (constant vector-data-disp) e-new (make-build-cas e-old) build-cas-seq)])) - (define-inline 3 vector-cas! - [(e-v e-i e-old e-new) (go e-v e-i e-old e-new)]) - (define-inline 2 vector-cas! - [(e-v e-i e-old e-new) - (bind #t (e-v e-i e-old e-new) - `(if ,(build-vector-set!-check e-v e-i #f) - ,(go e-v e-i e-old e-new) - ,(build-libcall #t src sexpr vector-cas! e-v e-i e-old e-new)))])) - (let () - (define (go e-v e-i e-new) - `(set! - ,(nanopass-case (L7 Expr) e-i - [(quote ,d) - (guard (target-fixnum? d)) - (%mref ,e-v ,(+ (fix d) (constant vector-data-disp)))] - [else (%mref ,e-v ,e-i ,(constant vector-data-disp))]) - ,e-new)) - (define-inline 3 vector-set-fixnum! - [(e-v e-i e-new) (go e-v e-i e-new)]) - (define-inline 2 vector-set-fixnum! - [(e-v e-i e-new) - (bind #t (e-v e-i e-new) - `(if ,(build-vector-set!-check e-v e-i e-new) - ,(go e-v e-i e-new) - ,(build-libcall #t src sexpr vector-set-fixnum! e-v e-i e-new)))]))) - (let () - (define build-bytevector-ref-check - (lambda (e-bits e-bv e-i check-mutable?) - (nanopass-case (L7 Expr) e-bits - [(quote ,d) - (guard (and (fixnum? d) (fx> d 0) (fx= (* (fxquotient d 8) 8) d))) - (let ([bits d] [bytes (fxquotient d 8)]) - (bind #t (e-bv e-i) - (build-and - (%type-check mask-typed-object type-typed-object ,e-bv) - (bind #t ([t (%mref ,e-bv ,(constant bytevector-type-disp))]) - (build-and - (if check-mutable? - (%type-check mask-mutable-bytevector type-mutable-bytevector ,t) - (%type-check mask-bytevector type-bytevector ,t)) - (cond - [(expr->index e-i bytes (constant maximum-bytevector-length)) => - (lambda (index) - (%inline u< - (immediate ,(logor (ash (+ index (fx- bytes 1)) (constant bytevector-length-offset)) - (constant type-bytevector) (constant bytevector-immutable-flag))) - ,t))] - [else - (build-and - ($type-check (fxlogor (fix (fx- bytes 1)) (constant mask-fixnum)) (constant type-fixnum) e-i) - (%inline u< - ; NB. add cannot overflow or change negative to positive when - ; low-order (log2 bytes) bits of fixnum value are zero, as - ; guaranteed by type-check above - ,(if (fx= bytes 1) - e-i - (%inline + ,e-i (immediate ,(fix (fx- bytes 1))))) - ,(%inline logand - ,(translate t - (constant bytevector-length-offset) - (constant fixnum-offset)) - (immediate ,(- (constant fixnum-factor))))))]))))))] - [(seq (profile ,src) ,[e]) (and e `(seq (profile ,src) ,e))] - [else #f]))) - (define-inline 2 $bytevector-ref-check? - [(e-bits e-bv e-i) (build-bytevector-ref-check e-bits e-bv e-i #f)]) - (define-inline 2 $bytevector-set!-check? - [(e-bits e-bv e-i) (build-bytevector-ref-check e-bits e-bv e-i #t)])) - (let () - (define build-bytevector-fill - (let ([filler (make-build-fill 1 (constant bytevector-data-disp))]) - (lambda (e-bv e-bytes e-fill) - (bind #t uptr ([e-fill (build-unfix e-fill)]) - (filler e-bv e-bytes e-fill))))) - (let () - (define do-make-bytevector - (lambda (e-length maybe-e-fill) - ; NB: caller must bind maybe-e-fill - (safe-assert (or (not maybe-e-fill) (no-need-to-bind? #f maybe-e-fill))) - (if (constant? (lambda (x) (and (fixnum? x) (fx<= 0 x 10000))) e-length) - (let ([n (constant-value e-length)]) - (if (fx= n 0) - `(quote ,(bytevector)) - (bind #t ([t (%constant-alloc type-typed-object - (fx+ (constant header-size-bytevector) n))]) - `(seq - (set! ,(%mref ,t ,(constant bytevector-type-disp)) - (immediate ,(fx+ (fx* n (constant bytevector-length-factor)) - (constant type-bytevector)))) - ,(if maybe-e-fill - (build-bytevector-fill t `(immediate ,n) maybe-e-fill) - t))))) - (bind #t (e-length) - (let ([t-bytes (make-tmp 'tbytes 'uptr)] [t-vec (make-tmp 'tvec)]) - `(if ,(%inline eq? ,e-length (immediate 0)) - (quote ,(bytevector)) - (let ([,t-bytes ,(build-unfix e-length)]) - (let ([,t-vec (alloc ,(make-info-alloc (constant type-typed-object) #f #f) - ,(%inline logand - ,(%inline + ,t-bytes - (immediate ,(fx+ (constant header-size-bytevector) - (fx- (constant byte-alignment) 1)))) - (immediate ,(- (constant byte-alignment)))))]) - (seq - (set! ,(%mref ,t-vec ,(constant bytevector-type-disp)) - ,(build-type/length t-bytes - (constant type-bytevector) - 0 - (constant bytevector-length-offset))) - ,(if maybe-e-fill - (build-bytevector-fill t-vec t-bytes maybe-e-fill) - t-vec)))))))))) - (let () - (define valid-length? - (lambda (e-length) - (constant? - (lambda (x) - (and (or (fixnum? x) (bignum? x)) - (<= 0 x (constant maximum-bytevector-length)))) - e-length))) - (define-inline 2 make-bytevector - [(e-length) (and (valid-length? e-length) (do-make-bytevector e-length #f))] - [(e-length e-fill) - (and (valid-length? e-length) - (constant? (lambda (x) (and (fixnum? x) (fx<= -128 x 255))) e-fill) - (do-make-bytevector e-length e-fill))])) - (define-inline 3 make-bytevector - [(e-length) (do-make-bytevector e-length #f)] - [(e-length e-fill) (bind #f (e-fill) (do-make-bytevector e-length e-fill))])) - (define-inline 3 bytevector-fill! - [(e-bv e-fill) - (bind #t (e-bv e-fill) - `(seq - ,(build-bytevector-fill e-bv - (%inline srl - ,(%mref ,e-bv ,(constant bytevector-type-disp)) - ,(%constant bytevector-length-offset)) - e-fill) - ,(%constant svoid)))])) - - (let () - (define build-bytevector - (lambda (e*) - (define (find-k n) - (let loop ([bytes (constant-case ptr-bits [(32) 4] [(64) 8])] - [type* (constant-case ptr-bits - [(32) '(unsigned-32 unsigned-16 unsigned-8)] - [(64) '(unsigned-64 unsigned-32 unsigned-16 unsigned-8)])]) - (let ([bytes/2 (fxsrl bytes 1)]) - (if (fx<= n bytes/2) - (loop bytes/2 (cdr type*)) - (values bytes (car type*)))))) - (define (build-chunk k n e*) - (define (build-shift e shift) - (if (fx= shift 0) e (%inline sll ,e (immediate ,shift)))) - (let loop ([k (constant-case native-endianness - [(little) (fxmin k n)] - [(big) k])] - [e* (constant-case native-endianness - [(little) (reverse (if (fx<= n k) e* (list-head e* k)))] - [(big) e*])] - [constant-part 0] - [expression-part #f] - [expression-shift 0] - [mask? #f]) ; no need to mask the high-order byte - (if (fx= k 0) - (if expression-part - (let ([expression-part (build-shift expression-part expression-shift)]) - (if (= constant-part 0) - expression-part - (%inline logor ,expression-part (immediate ,constant-part)))) - `(immediate ,constant-part)) - (let ([k (fx- k 1)] - [constant-part (ash constant-part 8)] - [expression-shift (fx+ expression-shift 8)]) - (if (null? e*) - (loop k e* constant-part expression-part expression-shift #t) - (let ([e (car e*)] [e* (cdr e*)]) - (if (fixnum-constant? e) - (loop k e* (logor constant-part (logand (constant-value e) #xff)) expression-part expression-shift #t) - (loop k e* constant-part - (let* ([e (build-unfix e)] - [e (if mask? (%inline logand ,e (immediate #xff)) e)]) - (if expression-part - (%inline logor ,(build-shift expression-part expression-shift) ,e) - e)) - 0 #t)))))))) - (let ([len (length e*)]) - (if (fx= len 0) - `(quote ,(bytevector)) - (list-bind #f (e*) - (bind #t ([t (%constant-alloc type-typed-object - (fx+ (constant header-size-bytevector) len))]) - `(seq - (set! ,(%mref ,t ,(constant bytevector-type-disp)) - (immediate ,(+ (* len (constant bytevector-length-factor)) - (constant type-bytevector)))) - ; build and store k-octet (k = 4 on 32-bit machines, k = 8 on 64-bit - ; machines) chunks, taking endianness into account. for the last - ; chunk, set k = 1, 2, 4, or 8 depending on the number of octets - ; remaining, padding with zeros as necessary. - ,(let f ([e* e*] [n (length e*)] [offset (constant bytevector-data-disp)]) - (let-values ([(k type) (find-k n)]) - `(seq - (inline ,(make-info-load type #f) ,%store ,t ,%zero (immediate ,offset) - ,(build-chunk k n e*)) - ,(if (fx<= n k) - t - (f (list-tail e* k) (fx- n k) (fx+ offset k))))))))))))) - - (define-inline 2 bytevector - [e* (and (andmap - (lambda (x) - (constant? - (lambda (x) (and (fixnum? x) (fx<= -128 x 255))) - x)) - e*) - (build-bytevector e*))]) - - (define-inline 3 bytevector - [e* (build-bytevector e*)])) - - (let () - (define byte-offset - (lambda (off) - (cond - [(nanopass-case (L7 Expr) off - [(quote ,d) - (and (and (integer? d) (exact? d)) - (let ([n (+ d (constant bytevector-data-disp))]) - (and (target-fixnum? n) - `(quote ,n))))] - [else #f])] - [else (%inline + ,off - (quote ,(constant bytevector-data-disp)))]))) - - (define-inline 3 bytevector-copy! - [(bv1 off1 bv2 off2 n) - (%primcall src sexpr $byte-copy! ,bv1 ,(byte-offset off1) ,bv2 ,(byte-offset off2) ,n)])) - - (define-inline 3 bytevector-truncate! - [(bv len) - (if (fixnum-constant? len) - (let ([len (constant-value len)]) - (if (fx= len 0) - `(quote ,(bytevector)) - (bind #t (bv) - `(seq - (set! ,(%mref ,bv ,(constant bytevector-type-disp)) - (immediate ,(fx+ (fx* len (constant bytevector-length-factor)) - (constant type-bytevector)))) - ,bv)))) - (bind #t (bv len) - `(if ,(%inline eq? ,len (immediate 0)) - (quote ,(bytevector)) - (seq - (set! ,(%mref ,bv ,(constant bytevector-type-disp)) - ,(build-type/length len - (constant type-bytevector) - (constant fixnum-offset) - (constant bytevector-length-offset))) - ,bv))))]) - - (define-inline 3 $bytevector-set-immutable! - [(bv) ((build-set-immutable! bytevector-type-disp bytevector-immutable-flag) bv)]) - - (let () - (define bv-index-offset - (lambda (offset-expr) - (if (fixnum-constant? offset-expr) - (values %zero (+ (constant bytevector-data-disp) (constant-value offset-expr))) - (values (build-unfix offset-expr) (constant bytevector-data-disp))))) - - (define bv-offset-okay? - (lambda (x mask) - (constant? (lambda (x) (and (target-fixnum? x) (>= x 0) (eq? (logand x mask) 0))) x))) - - (let () - (define-syntax define-bv-8-inline - (syntax-rules () - [(_ name type) - (define-inline 2 name - [(e-bv e-offset) - (bind #t (e-bv e-offset) - `(if ,(handle-prim #f #f 3 '$bytevector-ref-check? (list `(quote 8) e-bv e-offset)) - ,(let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - (build-object-ref #f 'type e-bv e-index imm-offset)) - ,(build-libcall #t src sexpr name e-bv e-offset)))])])) - - (define-bv-8-inline bytevector-s8-ref integer-8) - (define-bv-8-inline bytevector-u8-ref unsigned-8)) - - (let () - (define-syntax define-bv-native-ref-inline - (lambda (x) - (syntax-case x () - [(_ name type) - #'(define-inline 3 name - [(e-bv e-offset) - (let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - (build-object-ref #f 'type e-bv e-index imm-offset))])]))) - - (define-bv-native-ref-inline bytevector-s8-ref integer-8) - (define-bv-native-ref-inline bytevector-u8-ref unsigned-8) - - (define-bv-native-ref-inline bytevector-s16-native-ref integer-16) - (define-bv-native-ref-inline bytevector-u16-native-ref unsigned-16) - - (define-bv-native-ref-inline bytevector-s32-native-ref integer-32) - (define-bv-native-ref-inline bytevector-u32-native-ref unsigned-32) - - (define-bv-native-ref-inline bytevector-s64-native-ref integer-64) - (define-bv-native-ref-inline bytevector-u64-native-ref unsigned-64) - - (define-bv-native-ref-inline bytevector-ieee-single-native-ref single-float) - (define-bv-native-ref-inline bytevector-ieee-double-native-ref double-float)) - - (let () - (define-syntax define-bv-native-int-set!-inline - (lambda (x) - (syntax-case x () - [(_ check-64? name type) - (with-syntax ([body #'(let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - (build-object-set! 'type e-bv e-index imm-offset e-val))]) - (with-syntax ([body (if (datum check-64?) - #'(and (>= (constant ptr-bits) 64) body) - #'body)]) - #'(define-inline 3 name - [(e-bv e-offset e-val) body])))]))) - - (define-bv-native-int-set!-inline #f bytevector-s8-set! integer-8) - (define-bv-native-int-set!-inline #f bytevector-u8-set! unsigned-8) - (define-bv-native-int-set!-inline #f $bytevector-set! unsigned-8) - - (define-bv-native-int-set!-inline #f bytevector-s16-native-set! integer-16) - (define-bv-native-int-set!-inline #f bytevector-u16-native-set! unsigned-16) - - (define-bv-native-int-set!-inline #f bytevector-s32-native-set! integer-32) - (define-bv-native-int-set!-inline #f bytevector-u32-native-set! unsigned-32) - - (define-bv-native-int-set!-inline #t bytevector-s64-native-set! integer-64) - (define-bv-native-int-set!-inline #t bytevector-u64-native-set! unsigned-64)) - - (let () - (define-syntax define-bv-native-ieee-set!-inline - (lambda (x) - (syntax-case x () - [(_ name type) - #'(define-inline 3 name - [(e-bv e-offset e-val) - (let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - (bind #f (e-bv e-index) - (build-object-set! 'type e-bv e-index imm-offset - (build-$real->flonum src sexpr e-val `(quote name)))))])]))) - - (define-bv-native-ieee-set!-inline bytevector-ieee-single-native-set! single-float) - (define-bv-native-ieee-set!-inline bytevector-ieee-double-native-set! double-float)) - - (let () - (define-syntax define-bv-int-ref-inline - (lambda (x) - (define p2? - (lambda (n) - (let f ([i 1]) - (or (fx= i n) - (and (not (fx> i n)) (f (fxsll i 1))))))) - (syntax-case x () - [(_ name type mask) - #`(define-inline 3 name - [(e-bv e-offset e-eness) - (and (or (constant unaligned-integers) - (and #,(p2? (fx+ (datum mask) 1)) (bv-offset-okay? e-offset mask))) - (constant? (lambda (x) (memq x '(big little))) e-eness) - (let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - (build-object-ref (not (eq? (constant-value e-eness) (constant native-endianness))) - 'type e-bv e-index imm-offset)))])]))) - - (define-bv-int-ref-inline bytevector-s16-ref integer-16 1) - (define-bv-int-ref-inline bytevector-u16-ref unsigned-16 1) - - (define-bv-int-ref-inline bytevector-s24-ref integer-24 1) - (define-bv-int-ref-inline bytevector-u24-ref unsigned-24 1) - - (define-bv-int-ref-inline bytevector-s32-ref integer-32 3) - (define-bv-int-ref-inline bytevector-u32-ref unsigned-32 3) - - (define-bv-int-ref-inline bytevector-s40-ref integer-40 3) - (define-bv-int-ref-inline bytevector-u40-ref unsigned-40 3) - - (define-bv-int-ref-inline bytevector-s48-ref integer-48 3) - (define-bv-int-ref-inline bytevector-u48-ref unsigned-48 3) - - (define-bv-int-ref-inline bytevector-s56-ref integer-56 7) - (define-bv-int-ref-inline bytevector-u56-ref unsigned-56 7) - - (define-bv-int-ref-inline bytevector-s64-ref integer-64 7) - (define-bv-int-ref-inline bytevector-u64-ref unsigned-64 7)) - - (let () - (define-syntax define-bv-ieee-ref-inline - (lambda (x) - (syntax-case x () - [(_ name type mask) - #'(define-inline 3 name - [(e-bv e-offset e-eness) - (and (or (constant unaligned-floats) - (bv-offset-okay? e-offset mask)) - (constant? (lambda (x) (eq? x (constant native-endianness))) e-eness) - (let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - (build-object-ref #f 'type e-bv e-index imm-offset)))])]))) - - (define-bv-ieee-ref-inline bytevector-ieee-single-ref single-float 3) - (define-bv-ieee-ref-inline bytevector-ieee-double-ref double-float 7)) - - (let () - (define-syntax define-bv-int-set!-inline - (lambda (x) - (syntax-case x () - [(_ check-64? name type mask) - (with-syntax ([body #'(and (or (constant unaligned-integers) - (and mask (bv-offset-okay? e-offset mask))) - (constant? (lambda (x) (memq x '(big little))) e-eness) - (let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - (if (eq? (constant-value e-eness) (constant native-endianness)) - (build-object-set! 'type e-bv e-index imm-offset e-value) - (build-swap-object-set! 'type e-bv e-index imm-offset e-value))))]) - (with-syntax ([body (if (datum check-64?) - #'(and (>= (constant ptr-bits) 64) body) - #'body)]) - #'(define-inline 3 name - [(e-bv e-offset e-value e-eness) body])))]))) - - (define-bv-int-set!-inline #f bytevector-s16-set! integer-16 1) - (define-bv-int-set!-inline #f bytevector-u16-set! unsigned-16 1) - - (define-bv-int-set!-inline #f bytevector-s24-set! integer-24 #f) - (define-bv-int-set!-inline #f bytevector-u24-set! unsigned-24 #f) - - (define-bv-int-set!-inline #f bytevector-s32-set! integer-32 3) - (define-bv-int-set!-inline #f bytevector-u32-set! unsigned-32 3) - - (define-bv-int-set!-inline #t bytevector-s40-set! integer-40 #f) - (define-bv-int-set!-inline #t bytevector-u40-set! unsigned-40 #f) - - (define-bv-int-set!-inline #t bytevector-s48-set! integer-48 #f) - (define-bv-int-set!-inline #t bytevector-u48-set! unsigned-48 #f) - - (define-bv-int-set!-inline #t bytevector-s56-set! integer-56 #f) - (define-bv-int-set!-inline #t bytevector-u56-set! unsigned-56 #f) - - (define-bv-int-set!-inline #t bytevector-s64-set! integer-64 7) - (define-bv-int-set!-inline #t bytevector-u64-set! unsigned-64 7)) - - (let () - (define-syntax define-bv-ieee-set!-inline - (lambda (x) - (syntax-case x () - [(_ name type mask) - #'(define-inline 3 name - [(e-bv e-offset e-value e-eness) - (and (or (constant unaligned-floats) (bv-offset-okay? e-offset mask)) - (constant? (lambda (x) (eq? x (constant native-endianness))) e-eness) - (let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - (bind #f (e-bv e-index) - (build-object-set! 'type e-bv e-index imm-offset - (build-$real->flonum src sexpr e-value - `(quote name))))))])]))) - - (define-bv-ieee-set!-inline bytevector-ieee-single-set! single-float 3) - (define-bv-ieee-set!-inline bytevector-ieee-double-set! double-float 7)) - - (let () - (define anyint-ref-helper - (lambda (type mask e-bv e-offset e-eness) - (and (or (constant unaligned-integers) (bv-offset-okay? e-offset mask)) - (constant? (lambda (x) (memq x '(big little))) e-eness) - (let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - (build-object-ref (not (eq? (constant-value e-eness) (constant native-endianness))) - type e-bv e-index imm-offset))))) - (define-syntax define-bv-anyint-ref-inline - (syntax-rules () - [(_ name type8 type16 type32 type64) - (define-inline 3 name - [(e-bv e-offset e-eness e-size) - (and (fixnum-constant? e-size) - (case (constant-value e-size) - [(1) (let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - `(seq - ,e-eness - ,(build-object-ref #f 'type8 e-bv e-index imm-offset)))] - [(2) (anyint-ref-helper 'type16 #b1 e-bv e-offset e-eness)] - [(4) (anyint-ref-helper 'type32 #b11 e-bv e-offset e-eness)] - [(8) (anyint-ref-helper 'type64 #b111 e-bv e-offset e-eness)] - [else #f]))])])) - - (define-bv-anyint-ref-inline bytevector-sint-ref - integer-8 integer-16 integer-32 integer-64) - (define-bv-anyint-ref-inline bytevector-uint-ref - unsigned-8 unsigned-16 unsigned-32 unsigned-64)) - - (let () - (define anyint-set!-helper - (lambda (type mask e-bv e-offset e-value e-eness) - (and (or (constant unaligned-integers) (bv-offset-okay? e-offset mask)) - (constant? (lambda (x) (memq x '(big little))) e-eness) - (let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - (if (eq? (constant-value e-eness) (constant native-endianness)) - (build-object-set! type e-bv e-index imm-offset e-value) - (build-swap-object-set! type e-bv e-index imm-offset e-value)))))) - (define-syntax define-bv-anyint-set!-inline - (syntax-rules () - [(_ name type8 type16 type32 type64) - (define-inline 3 name - [(e-bv e-offset e-value e-eness e-size) - (and (fixnum-constant? e-size) - (case (constant-value e-size) - [(1) (let-values ([(e-index imm-offset) (bv-index-offset e-offset)]) - `(seq - ,e-eness - ,(build-object-set! 'type8 e-bv e-index imm-offset e-value)))] - [(2) (anyint-set!-helper 'type16 1 e-bv e-offset e-value e-eness)] - [(4) (anyint-set!-helper 'type32 3 e-bv e-offset e-value e-eness)] - [(8) (and (>= (constant ptr-bits) 64) - (anyint-set!-helper 'type64 7 e-bv e-offset e-value e-eness))] - [else #f]))])])) - - (define-bv-anyint-set!-inline bytevector-sint-set! - integer-8 integer-16 integer-32 integer-64) - (define-bv-anyint-set!-inline bytevector-uint-set! - unsigned-8 unsigned-16 unsigned-32 unsigned-64))) - - (let () - (define (byte-count e-n) - (or (nanopass-case (L7 Expr) e-n - [(quote ,d) - (and (and (integer? d) (exact? d)) - (let ([n (* d (constant string-char-bytes))]) - (and (target-fixnum? n) - `(immediate ,(fix n)))))] - [else #f]) - (%inline sll ,e-n ,(%constant string-char-offset)))) - (define byte-offset - (lambda (e-off) - (or (nanopass-case (L7 Expr) e-off - [(quote ,d) - (and (and (integer? d) (exact? d)) - (let ([n (+ (* d (constant string-char-bytes)) - (constant string-data-disp))]) - (and (target-fixnum? n) - `(immediate ,(fix n)))))] - [else #f]) - (%inline + - ,(%inline sll ,e-off ,(%constant string-char-offset)) - (immediate ,(fix (constant string-data-disp))))))) - (define-inline 3 string-copy! - [(e-bv1 e-off1 e-bv2 e-off2 e-n) - (%primcall src sexpr $byte-copy! ,e-bv1 ,(byte-offset e-off1) ,e-bv2 ,(byte-offset e-off2) ,(byte-count e-n))])) - - (define-inline 3 string-truncate! - [(e-str e-len) - (if (fixnum-constant? e-len) - (let ([len (constant-value e-len)]) - (if (fx= len 0) - `(quote ,(string)) - (bind #t (e-str) - `(seq - (set! ,(%mref ,e-str ,(constant string-type-disp)) - (immediate ,(fx+ (fx* len (constant string-length-factor)) - (constant type-string)))) - ,e-str)))) - (bind #t (e-str e-len) - `(if ,(%inline eq? ,e-len (immediate 0)) - (quote ,(string)) - (seq - (set! ,(%mref ,e-str ,(constant string-type-disp)) - ,(build-type/length e-len - (constant type-string) - (constant fixnum-offset) - (constant string-length-offset))) - ,e-str))))]) - - (let () - (define build-string-fill - (make-build-fill (constant string-char-bytes) (constant string-data-disp))) - (let () - (define do-make-string - (lambda (e-length e-fill) - ; NB: caller must bind e-fill - (safe-assert (no-need-to-bind? #f e-fill)) - (if (constant? (lambda (x) (and (fixnum? x) (fx<= 0 x 10000))) e-length) - (let ([n (constant-value e-length)]) - (if (fx= n 0) - `(quote ,(string)) - (let ([bytes (fx* n (constant string-char-bytes))]) - (bind #t ([t (%constant-alloc type-typed-object - (fx+ (constant header-size-string) bytes))]) - `(seq - (set! ,(%mref ,t ,(constant string-type-disp)) - (immediate ,(fx+ (fx* n (constant string-length-factor)) - (constant type-string)))) - ,(build-string-fill t `(immediate ,bytes) e-fill)))))) - (bind #t (e-length) - (let ([t-bytes (make-tmp 'tsize 'uptr)] [t-str (make-tmp 'tstr)]) - `(if ,(%inline eq? ,e-length (immediate 0)) - (quote ,(string)) - (let ([,t-bytes ,(translate e-length - (constant fixnum-offset) - (constant string-char-offset))]) - (let ([,t-str (alloc ,(make-info-alloc (constant type-typed-object) #f #f) - ,(%inline logand - ,(%inline + ,t-bytes - (immediate ,(fx+ (constant header-size-string) - (fx- (constant byte-alignment) 1)))) - (immediate ,(- (constant byte-alignment)))))]) - (seq - (set! ,(%mref ,t-str ,(constant string-type-disp)) - ,(build-type/length t-bytes - (constant type-string) - (constant string-char-offset) - (constant string-length-offset))) - ,(build-string-fill t-str t-bytes e-fill)))))))))) - (define default-fill `(immediate ,(ptr->imm #\nul))) - (define-inline 3 make-string - [(e-length) (do-make-string e-length default-fill)] - [(e-length e-fill) (bind #t (e-fill) (do-make-string e-length e-fill))]) - (let () - (define (valid-length? e-length) - (constant? - (lambda (x) - (and (or (fixnum? x) (bignum? x)) - (<= 0 x (constant maximum-string-length)))) - e-length)) - (define-inline 2 make-string - [(e-length) - (and (valid-length? e-length) - (do-make-string e-length default-fill))] - [(e-length e-fill) - (and (valid-length? e-length) - (constant? char? e-fill) - (do-make-string e-length e-fill))]))) - (define-inline 3 string-fill! - [(e-str e-fill) - `(seq - ,(bind #t (e-str e-fill) - (build-string-fill e-str - (translate - (%inline logxor - ,(%mref ,e-str ,(constant string-type-disp)) - ,(%constant type-string)) - (constant string-length-offset) - (constant string-char-offset)) - e-fill)) - ,(%constant svoid))])) - - (let () - (define build-fxvector-fill - (make-build-fill (constant ptr-bytes) (constant fxvector-data-disp))) - (meta-assert (= (constant log2-ptr-bytes) (constant fixnum-offset))) - (let () - (define do-make-fxvector - (lambda (e-length e-fill) - ; NB: caller must bind e-fill - (safe-assert (no-need-to-bind? #f e-fill)) - (if (constant? (lambda (x) (and (fixnum? x) (fx<= 0 x 10000))) e-length) - (let ([n (constant-value e-length)]) - (if (fx= n 0) - `(quote ,(fxvector)) - (let ([bytes (fx* n (constant ptr-bytes))]) - (bind #t ([t (%constant-alloc type-typed-object - (fx+ (constant header-size-fxvector) bytes))]) - `(seq - (set! ,(%mref ,t ,(constant fxvector-type-disp)) - (immediate ,(fx+ (fx* n (constant fxvector-length-factor)) - (constant type-fxvector)))) - ,(build-fxvector-fill t `(immediate ,bytes) e-fill)))))) - (bind #t (e-length) ; fixnum length doubles as byte count - (let ([t-fxv (make-tmp 'tfxv)]) - `(if ,(%inline eq? ,e-length (immediate 0)) - (quote ,(fxvector)) - (let ([,t-fxv (alloc ,(make-info-alloc (constant type-typed-object) #f #f) - ,(%inline logand - ,(%inline + ,e-length - (immediate ,(fx+ (constant header-size-fxvector) - (fx- (constant byte-alignment) 1)))) - (immediate ,(- (constant byte-alignment)))))]) - (seq - (set! ,(%mref ,t-fxv ,(constant fxvector-type-disp)) - ,(build-type/length e-length - (constant type-fxvector) - (constant fixnum-offset) - (constant fxvector-length-offset))) - ,(build-fxvector-fill t-fxv e-length e-fill))))))))) - (define default-fill `(immediate ,(fix 0))) - (define-inline 3 make-fxvector - [(e-length) (do-make-fxvector e-length default-fill)] - [(e-length e-fill) (bind #t (e-fill) (do-make-fxvector e-length e-fill))]) - (let () - (define (valid-length? e-length) - (constant? - (lambda (x) - (and (or (fixnum? x) (bignum? x)) - (<= 0 x (constant maximum-fxvector-length)))) - e-length)) - (define-inline 2 make-fxvector - [(e-length) - (and (valid-length? e-length) - (do-make-fxvector e-length default-fill))] - [(e-length e-fill) - (and (valid-length? e-length) - (constant? fixnum? e-fill) - (do-make-fxvector e-length e-fill))]))) - (define-inline 3 fxvector-fill! - [(e-fxv e-fill) - `(seq - ,(bind #t (e-fxv e-fill) - (build-fxvector-fill e-fxv - (translate - (%inline logxor - ,(%mref ,e-fxv ,(constant fxvector-type-disp)) - ,(%constant type-fxvector)) - (constant fxvector-length-offset) - (constant fixnum-offset)) - e-fill)) - ,(%constant svoid))])) - - (let () - (define build-vector-fill - (make-build-fill (constant ptr-bytes) (constant vector-data-disp))) - (meta-assert (= (constant log2-ptr-bytes) (constant fixnum-offset))) - (let () - (define do-make-vector - (lambda (e-length e-fill) - ; NB: caller must bind e-fill - (safe-assert (no-need-to-bind? #f e-fill)) - (if (constant? (lambda (x) (and (fixnum? x) (fx<= 0 x 10000))) e-length) - (let ([n (constant-value e-length)]) - (if (fx= n 0) - `(quote ,(vector)) - (let ([bytes (fx* n (constant ptr-bytes))]) - (bind #t ([t (%constant-alloc type-typed-object - (fx+ (constant header-size-vector) bytes))]) - `(seq - (set! ,(%mref ,t ,(constant vector-type-disp)) - (immediate ,(+ (fx* n (constant vector-length-factor)) - (constant type-vector)))) - ,(build-vector-fill t `(immediate ,bytes) e-fill)))))) - (bind #t (e-length) ; fixnum length doubles as byte count - (let ([t-vec (make-tmp 'tvec)]) - `(if ,(%inline eq? ,e-length (immediate 0)) - (quote ,(vector)) - (let ([,t-vec (alloc ,(make-info-alloc (constant type-typed-object) #f #f) - ,(%inline logand - ,(%inline + ,e-length - (immediate ,(fx+ (constant header-size-vector) - (fx- (constant byte-alignment) 1)))) - (immediate ,(- (constant byte-alignment)))))]) - (seq - (set! ,(%mref ,t-vec ,(constant vector-type-disp)) - ,(build-type/length e-length - (constant type-vector) - (constant fixnum-offset) - (constant vector-length-offset))) - ,(build-vector-fill t-vec e-length e-fill))))))))) - (define default-fill `(immediate ,(fix 0))) - (define-inline 3 make-vector - [(e-length) (do-make-vector e-length default-fill)] - [(e-length e-fill) (bind #t (e-fill) (do-make-vector e-length e-fill))]) - (let () - (define (valid-length? e-length) - (constant? - (lambda (x) (and (target-fixnum? x) (>= x 0))) - e-length)) - (define-inline 2 make-vector - [(e-length) - (and (valid-length? e-length) - (do-make-vector e-length default-fill))] - [(e-length e-fill) - (and (valid-length? e-length) - (constant? fixnum? e-fill) - (do-make-vector e-length e-fill))])))) - - (let () - (meta-assert (= (constant log2-ptr-bytes) (constant fixnum-offset))) - (define-inline 3 $make-eqhash-vector - [(e-length) - (let ([t-vec (make-tmp 'tvec)] - [t-idx (make-assigned-tmp 't-idx)] - [Ltop (make-local-label 'Ltop)]) - `(let ([,t-idx ,e-length]) - (if ,(%inline eq? ,t-idx (immediate 0)) - (quote ,(vector)) - (let ([,t-vec (alloc ,(make-info-alloc (constant type-typed-object) #f #f) - ,(%inline logand - ,(%inline + ,t-idx - (immediate ,(fx+ (constant header-size-vector) - (fx- (constant byte-alignment) 1)))) - (immediate ,(- (constant byte-alignment)))))]) - (seq - (set! ,(%mref ,t-vec ,(constant vector-type-disp)) - ,(build-type/length t-idx - (constant type-vector) - (constant fixnum-offset) - (constant vector-length-offset))) - (label ,Ltop - ,(%seq - (set! ,t-idx ,(%inline - ,t-idx (immediate ,(fix 1)))) - (set! ,(%mref ,t-vec ,t-idx ,(constant vector-data-disp)) ,t-idx) - (if ,(%inline eq? ,t-idx (immediate 0)) - ,t-vec - (goto ,Ltop)))))))))])) - - (define-inline 2 $continuation? - [(e) - (bind #t (e) - (build-and - (%type-check mask-closure type-closure ,e) - (%type-check mask-continuation-code type-continuation-code - ,(%mref - ,(%inline - - ,(%mref ,e ,(constant closure-code-disp)) - ,(%constant code-data-disp)) - ,(constant code-type-disp)))))]) - (define-inline 3 $continuation-stack-length - [(e) - (translate (%mref ,e ,(constant continuation-stack-length-disp)) - (constant fixnum-offset) - (constant log2-ptr-bytes))]) - (define-inline 3 $continuation-stack-clength - [(e) - (translate (%mref ,e ,(constant continuation-stack-clength-disp)) - (constant fixnum-offset) - (constant log2-ptr-bytes))]) - (define-inline 3 $continuation-return-code - [(e) - (bind #t ([t (%inline + - ,(%mref ,e ,(constant continuation-return-address-disp)) - ,(%constant return-address-toplink-disp))]) - (%inline - ,t ,(%mref ,t 0)))]) - (define-inline 3 $continuation-return-offset - [(e) - (build-fix - (%inline - - ,(%mref - ,(%mref ,e ,(constant continuation-return-address-disp)) - ,(constant return-address-toplink-disp)) - ,(%constant return-address-toplink-disp)))]) - (define-inline 3 $continuation-return-livemask - [(e) - (%mref - ,(%mref ,e ,(constant continuation-return-address-disp)) - ,(constant return-address-livemask-disp))]) - (define-inline 3 $continuation-stack-ref - [(e-k e-i) - (%mref - ,(%mref ,e-k ,(constant continuation-stack-disp)) - ,(translate e-i (constant fixnum-offset) (constant log2-ptr-bytes)) - 0)]) - (define-inline 2 $foreign-char? - [(e) - (bind #t (e) - (build-and - (%type-check mask-char type-char ,e) - (%inline < ,e (immediate ,(ptr->imm (integer->char #x100))))))]) - (define-inline 2 $foreign-wchar? - [(e) - (constant-case wchar-bits - [(16) - (bind #t (e) - (build-and - (%type-check mask-char type-char ,e) - (%inline < ,e (immediate ,(ptr->imm (integer->char #x10000))))))] - [(32) (%type-check mask-char type-char ,e)])]) - (define-inline 2 $integer-8? - [(e) - (unless (fx>= (constant fixnum-bits) 8) ($oops '$integer-8? "unexpected fixnum-bits")) - (bind #t (e) - (build-and - (%type-check mask-fixnum type-fixnum ,e) - (%inline u< - ,(%inline + ,e (immediate ,(fix #x80))) - (immediate ,(fix #x180)))))]) - (define-inline 2 $integer-16? - [(e) - (unless (fx>= (constant fixnum-bits) 16) ($oops '$integer-16? "unexpected fixnum-bits")) - (bind #t (e) - (build-and - (%type-check mask-fixnum type-fixnum ,e) - (%inline u< - ,(%inline + ,e (immediate ,(fix #x8000))) - (immediate ,(fix #x18000)))))]) - (define-inline 2 $integer-24? - [(e) - (unless (fx>= (constant fixnum-bits) 24) ($oops '$integer-24? "unexpected fixnum-bits")) - (bind #t (e) - (build-and - (%type-check mask-fixnum type-fixnum ,e) - (%inline u< - ,(%inline + ,e (immediate ,(fix #x800000))) - (immediate ,(fix #x1800000)))))]) - (define-inline 2 $integer-32? - [(e) - (bind #t (e) - (if (fx>= (constant fixnum-bits) 32) - (build-and - (%type-check mask-fixnum type-fixnum ,e) - (%inline u< - ,(%inline + ,e (immediate ,(fix #x80000000))) - (immediate ,(fix #x180000000)))) - (build-simple-or - (%type-check mask-fixnum type-fixnum ,e) - (build-and - (%type-check mask-typed-object type-typed-object ,e) - (bind #t ([t (%mref ,e ,(constant bignum-type-disp))]) - `(if ,(%type-check mask-signed-bignum type-positive-bignum ,t) - ,(build-libcall #f #f sexpr <= e `(quote #xffffffff)) - ,(build-and - (%type-check mask-signed-bignum type-negative-bignum ,t) - (build-libcall #f #f sexpr >= e `(quote #x-80000000)))))))))]) - (define-inline 2 $integer-40? - [(e) - (bind #t (e) - (if (fx>= (constant fixnum-bits) 32) - (build-and - (%type-check mask-fixnum type-fixnum ,e) - (%inline u< - ,(%inline + ,e (immediate ,(fix #x8000000000))) - (immediate ,(fix #x18000000000)))) - (build-simple-or - (%type-check mask-fixnum type-fixnum ,e) - (build-and - (%type-check mask-typed-object type-typed-object ,e) - (bind #t ([t (%mref ,e ,(constant bignum-type-disp))]) - `(if ,(%type-check mask-signed-bignum type-positive-bignum ,t) - ,(build-libcall #f #f sexpr <= e `(quote #xffffffffff)) - ,(build-and - (%type-check mask-signed-bignum type-negative-bignum ,t) - (build-libcall #f #f sexpr >= e `(quote #x-8000000000)))))))))]) - (define-inline 2 $integer-48? - [(e) - (bind #t (e) - (if (fx>= (constant fixnum-bits) 32) - (build-and - (%type-check mask-fixnum type-fixnum ,e) - (%inline u< - ,(%inline + ,e (immediate ,(fix #x800000000000))) - (immediate ,(fix #x1800000000000)))) - (build-simple-or - (%type-check mask-fixnum type-fixnum ,e) - (build-and - (%type-check mask-typed-object type-typed-object ,e) - (bind #t ([t (%mref ,e ,(constant bignum-type-disp))]) - `(if ,(%type-check mask-signed-bignum type-positive-bignum ,t) - ,(build-libcall #f #f sexpr <= e `(quote #xffffffffffff)) - ,(build-and - (%type-check mask-signed-bignum type-negative-bignum ,t) - (build-libcall #f #f sexpr >= e `(quote #x-800000000000)))))))))]) - (define-inline 2 $integer-56? - [(e) - (bind #t (e) - (if (fx>= (constant fixnum-bits) 32) - (build-and - (%type-check mask-fixnum type-fixnum ,e) - (%inline u< - ,(%inline + ,e (immediate ,(fix #x80000000000000))) - (immediate ,(fix #x180000000000000)))) - (build-simple-or - (%type-check mask-fixnum type-fixnum ,e) - (build-and - (%type-check mask-typed-object type-typed-object ,e) - (bind #t ([t (%mref ,e ,(constant bignum-type-disp))]) - `(if ,(%type-check mask-signed-bignum type-positive-bignum ,t) - ,(build-libcall #f #f sexpr <= e `(quote #xffffffffffffff)) - ,(build-and - (%type-check mask-signed-bignum type-negative-bignum ,t) - (build-libcall #f #f sexpr >= e `(quote #x-80000000000000)))))))))]) - (define-inline 2 $integer-64? - [(e) - (when (fx>= (constant fixnum-bits) 64) ($oops '$integer-64? "unexpected fixnum-bits")) - (bind #t (e) - (build-simple-or - (%type-check mask-fixnum type-fixnum ,e) - (build-and - (%type-check mask-typed-object type-typed-object ,e) - (bind #t ([t (%mref ,e ,(constant bignum-type-disp))]) - `(if ,(%type-check mask-signed-bignum type-positive-bignum ,t) - ,(build-libcall #f #f sexpr <= e `(quote #xffffffffffffffff)) - ,(build-and - (%type-check mask-signed-bignum type-negative-bignum ,t) - (build-libcall #f #f sexpr >= e `(quote #x-8000000000000000))))))))]) - (define-inline 3 char->integer - ; assumes types are set up so that fixnum tag will be right after the shift - [(e-char) (build-char->integer e-char)]) - (define-inline 2 char->integer - ; assumes types are set up so that fixnum tag will be right after the shift - [(e-char) - (bind #t (e-char) - `(if ,(%type-check mask-char type-char ,e-char) - ,(%inline srl ,e-char - (immediate ,(fx- (constant char-data-offset) (constant fixnum-offset)))) - ,(build-libcall #t src sexpr char->integer e-char)))]) - (define-inline 3 char- - ; assumes fixnum is zero - [(e1 e2) - (%inline sra - ,(%inline - ,e1 ,e2) - (immediate ,(fx- (constant char-data-offset) (constant fixnum-offset))))]) - (define-inline 3 integer->char - [(e-int) (build-integer->char e-int)]) - (define-inline 3 boolean=? - [(e1 e2) (%inline eq? ,e1 ,e2)] - [(e1 e2 . e*) (reduce-equality src sexpr moi e1 e2 e*)]) - (define-inline 3 symbol=? - [(e1 e2) (%inline eq? ,e1 ,e2)] - [(e1 e2 . e*) (reduce-equality src sexpr moi e1 e2 e*)]) - (let () - (define (go e flag) - (%inline logtest - ,(%mref ,e ,(constant record-type-flags-disp)) - (immediate ,(fix flag)))) - (define-inline 3 record-type-opaque? - [(e) (go e (constant rtd-opaque))]) - (define-inline 3 record-type-sealed? - [(e) (go e (constant rtd-sealed))]) - (define-inline 3 record-type-generative? - [(e) (go e (constant rtd-generative))])) - (let () - (define build-record? - (lambda (e) - (bind #t (e) - (build-and - (%type-check mask-typed-object type-typed-object ,e) - (bind #t ([t (%mref ,e ,(constant typed-object-type-disp))]) - (build-and - (%type-check mask-record type-record ,t) - (build-not - (%inline logtest - ,(%mref ,t ,(constant record-type-flags-disp)) - (immediate ,(fix (constant rtd-opaque))))))))))) - (define build-sealed-isa? - (lambda (e e-rtd) - (bind #t (e) - (bind #f (e-rtd) - (build-and - (%type-check mask-typed-object type-typed-object ,e) - (%inline eq? - ,(%mref ,e ,(constant typed-object-type-disp)) - ,e-rtd)))))) - (define build-unsealed-isa? - (lambda (e e-rtd) - (let ([t (make-assigned-tmp 't)] [Ltop (make-local-label 'Ltop)]) - (bind #t (e e-rtd) - (build-and - (%type-check mask-typed-object type-typed-object ,e) - `(let ([,t ,(%mref ,e ,(constant typed-object-type-disp))]) - ,(build-simple-or - (%inline eq? ,t ,e-rtd) - (build-and - (%type-check mask-record type-record ,t) - `(label ,Ltop - (seq - (set! ,t ,(%mref ,t ,(constant record-type-parent-disp))) - ,(build-simple-or - (%inline eq? ,t ,e-rtd) - `(if ,(%inline eq? ,t ,(%constant sfalse)) - ,(%constant sfalse) - (goto ,Ltop))))))))))))) - (define-inline 3 record? - [(e) (build-record? e)] - [(e e-rtd) - (if (constant? (lambda (x) - (and (record-type-descriptor? x) - (record-type-sealed? x))) - e-rtd) - (build-sealed-isa? e e-rtd) - (build-unsealed-isa? e e-rtd))]) - (define-inline 2 r6rs:record? - [(e) (build-record? e)]) - (define-inline 2 record? - [(e) (build-record? e)] - [(e e-rtd) - (nanopass-case (L7 Expr) e-rtd - [(quote ,d) - (and (record-type-descriptor? d) - (if (record-type-sealed? d) - (build-sealed-isa? e e-rtd) - (build-unsealed-isa? e e-rtd)))] - [else #f])]) - (define-inline 2 $sealed-record? - [(e e-rtd) (build-sealed-isa? e e-rtd)]) - (define-inline 2 eq-hashtable? - [(e) (let ([rtd (let () (include "hashtable-types.ss") (record-type-descriptor eq-ht))]) - (let ([e-rtd `(quote ,rtd)]) - (if (record-type-sealed? rtd) - (build-sealed-isa? e e-rtd) - (build-unsealed-isa? e e-rtd))))])) - (define-inline 2 gensym? - [(e) - (bind #t (e) - (build-and - (%type-check mask-symbol type-symbol ,e) - (bind #t ([t (%mref ,e ,(constant symbol-name-disp))]) - `(if ,t - ,(%type-check mask-pair type-pair ,t) - ,(%constant strue)))))]) - (let () - (define build-make-symbol - (lambda (e-name) - (bind #t ([t (%constant-alloc type-symbol (constant size-symbol))]) - (%seq - (set! ,(%mref ,t ,(constant symbol-name-disp)) ,e-name) - (set! ,(%mref ,t ,(constant symbol-value-disp)) ,(%constant sunbound)) - (set! ,(%mref ,t ,(constant symbol-pvalue-disp)) - (literal - ,(make-info-literal #f 'library - (lookup-libspec nonprocedure-code) - (constant code-data-disp)))) - (set! ,(%mref ,t ,(constant symbol-plist-disp)) ,(%constant snil)) - (set! ,(%mref ,t ,(constant symbol-splist-disp)) ,(%constant snil)) - (set! ,(%mref ,t ,(constant symbol-hash-disp)) ,(%constant sfalse)) - ,t)))) - (define (go e-pname) - (bind #t ([t (%constant-alloc type-pair (constant size-pair))]) - (%seq - (set! ,(%mref ,t ,(constant pair-cdr-disp)) ,e-pname) - (set! ,(%mref ,t ,(constant pair-car-disp)) ,(%constant sfalse)) - ,(build-make-symbol t)))) - (define-inline 3 gensym - [() (build-make-symbol (%constant sfalse))] - [(e-pname) (bind #f (e-pname) (go e-pname))] - [(e-pname e-uname) #f]) - (define-inline 2 gensym - [() (build-make-symbol (%constant sfalse))] - [(e-pname) (and (constant? string? e-pname) (go e-pname))] - [(e-pname e-uname) #f])) - (define-inline 3 symbol->string - [(e-sym) - (bind #t (e-sym) - (bind #t ([e-name (%mref ,e-sym ,(constant symbol-name-disp))]) - `(if ,e-name - (if ,(%type-check mask-pair type-pair ,e-name) - ,(%mref ,e-name ,(constant pair-cdr-disp)) - ,e-name) - ,(%primcall #f sexpr $gensym->pretty-name ,e-sym))))]) - (define-inline 3 $fxaddress - [(e) (%inline logand - ,(let ([n (- (log2 (constant typemod)) (constant fixnum-offset))]) - (if (> n 0) (%inline sra ,e (immediate ,n)) e)) - (immediate ,(- (constant fixnum-factor))))]) - (define-inline 3 $set-timer - [(e) (bind #f (e) - (bind #t ([t (build-fix (ref-reg %trap))]) - `(seq - (set! ,(ref-reg %trap) ,(build-unfix e)) - ,t)))]) - (define-inline 3 directory-separator? - [(e) (if-feature windows - (bind #t (e) - (build-simple-or - (%inline eq? ,e (immediate ,(ptr->imm #\/))) - (%inline eq? ,e (immediate ,(ptr->imm #\\))))) - (%inline eq? ,e (immediate ,(ptr->imm #\/))))]) - (let () - (define add-cdrs - (lambda (n e) - (if (fx= n 0) - e - (add-cdrs (fx- n 1) (%mref ,e ,(constant pair-cdr-disp)))))) - (define-inline 3 list-ref - [(e-ls e-n) - (nanopass-case (L7 Expr) e-n - [(quote ,d) - (and (and (fixnum? d) (fx< d 4)) - (%mref ,(add-cdrs d e-ls) ,(constant pair-car-disp)))] - [else #f])]) - (define-inline 3 list-tail - [(e-ls e-n) - (nanopass-case (L7 Expr) e-n - [(quote ,d) (and (and (fixnum? d) (fx<= d 4)) (add-cdrs d e-ls))] - [else #f])])) - (let () - (define (go0 src sexpr subtype) - (%primcall src sexpr $make-eq-hashtable - (immediate ,(fix (constant hashtable-default-size))) - (immediate ,(fix subtype)))) - (define (go1 src sexpr e-size subtype) - (nanopass-case (L7 Expr) e-size - [(quote ,d) - ; d must be a fixnum? for $hashtable-size-minlen and a - ; target-machine fixnum for cross compiling - (and (and (fixnum? d) (target-fixnum? d) (fx>= d 0)) - (%primcall src sexpr $make-eq-hashtable - (immediate ,(fix ($hashtable-size->minlen d))) - (immediate ,(fix subtype))))] - [else #f])) - (define-inline 3 make-eq-hashtable - [() (go0 src sexpr (constant eq-hashtable-subtype-normal))] - [(e-size) (go1 src sexpr e-size (constant eq-hashtable-subtype-normal))]) - (define-inline 3 make-weak-eq-hashtable - [() (go0 src sexpr (constant eq-hashtable-subtype-weak))] - [(e-size) (go1 src sexpr e-size (constant eq-hashtable-subtype-weak))]) - (define-inline 3 make-ephemeron-eq-hashtable - [() (go0 src sexpr (constant eq-hashtable-subtype-ephemeron))] - [(e-size) (go1 src sexpr e-size (constant eq-hashtable-subtype-ephemeron))])) - (let () - (define-syntax def-put-x - (syntax-rules () - [(_ name x-length) - (define-inline 3 name - [(e-bop e-x) - (bind #t (e-x) - (build-libcall #f src sexpr name e-bop e-x `(immediate 0) - (handle-prim #f #f 3 'x-length (list e-x))))] - [(e-bop e-x e-start) - (bind #t (e-x e-start) - (build-libcall #f src sexpr name e-bop e-x e-start - (%inline - - ,(handle-prim #f #f 3 'x-length (list e-x)) - ,e-start)))] - [(e-bop e-x e-start e-count) - (build-libcall #f src sexpr name e-bop e-x e-start e-count)])])) - (def-put-x put-bytevector bytevector-length) - (def-put-x put-bytevector-some bytevector-length) - (def-put-x put-string string-length) - (def-put-x put-string-some string-length)) - - (define-inline 3 $read-time-stamp-counter - [() - (constant-case architecture - [(x86) - (%seq - ; returns low-order 32 bits in eax, high-order in edx - (set! ,%eax (inline ,(make-info-kill* (reg-list %edx)) ,%read-time-stamp-counter)) - ,(u32xu32->ptr %edx %eax))] - [(x86_64) - (%seq - ; returns low-order 32 bits in rax, high-order in rdx - (set! ,%rax (inline ,(make-info-kill* (reg-list %rdx)) ,%read-time-stamp-counter)) - ,(unsigned->ptr - (%inline logor ,(%inline sll ,%rdx (immediate 32)) ,%rax) - 64))] - [(arm32) (unsigned->ptr (%inline read-time-stamp-counter) 32)] - [(ppc32) - (let ([t-hi (make-tmp 't-hi)]) - `(let ([,t-hi (inline ,(make-info-kill* (reg-list %real-zero)) - ,%read-time-stamp-counter)]) - ,(u32xu32->ptr t-hi %real-zero)))])]) - - (define-inline 3 $read-performance-monitoring-counter - [(e) - (constant-case architecture - [(x86) - (%seq - (set! ,%eax (inline ,(make-info-kill* (reg-list %edx)) ,%read-performance-monitoring-counter ,(build-unfix e))) - ,(u32xu32->ptr %edx %eax))] - [(x86_64) - (%seq - (set! ,%rax (inline ,(make-info-kill* (reg-list %rdx)) ,%read-performance-monitoring-counter ,(build-unfix e))) - ,(unsigned->ptr - (%inline logor ,(%inline sll ,%rdx (immediate 32)) ,%rax) - 64))] - [(arm32 ppc32) (unsigned->ptr (%inline read-performance-monitoring-counter ,(build-unfix e)) 32)])]) - - )) ; expand-primitives module - - (define-pass np-place-overflow-and-trap : L9 (ir) -> L9.5 () - (definitions - (define repeat? #f) - (define update-label! - (lambda (l oc tc) - (let ([orig-oc (local-label-overflow-check l)] - [orig-tc (local-label-trap-check l)]) - (unless (and (eq? oc orig-oc) (eq? tc orig-tc)) - (set! repeat? #t) - (local-label-overflow-check-set! l oc) - (local-label-trap-check-set! l tc))))) - (define combine-seq - (lambda (x y) - (case x - [(no) y] - [(yes) 'yes] - [else (if (eq? y 'no) 'maybe 'yes)]))) - (define-pass strip-redundant-overflow-and-trap : (L9.5 Expr) (ir) -> (L9.5 Expr) () - (definitions - (define-record-type goto (nongenerative) (fields label oc? tc?)) - (define goto* '()) - (define well-behaved-goto? - (lambda (goto) - (and (or (goto-oc? goto) (not (local-label-overflow-check (goto-label goto)))) - (or (goto-tc? goto) (not (local-label-trap-check (goto-label goto)))))))) - (Lvalue : Lvalue (ir oc? tc?) -> Lvalue () - [(mref ,[e0] ,[e1] ,imm) `(mref ,e0 ,e1 ,imm)]) - (Expr : Expr (ir oc? tc?) -> Expr () - [(overflow-check ,[e #t tc? -> e]) (if oc? e `(overflow-check ,e))] - [(trap-check ,ioc ,[e oc? #t -> e]) (if tc? e `(trap-check ,(if oc? #f ioc) ,e))] - [(call ,info ,mdcl (literal ,info0) ,[e*] ...) - (guard oc? (eq? (info-literal-type info0) 'library) - (libspec-does-not-expect-headroom? (info-literal-addr info0))) - `(call ,info ,mdcl - (literal ,(make-info-literal #f 'library - (libspec->headroom-libspec (info-literal-addr info0)) - 0)) - ,e* ...)] - [(loop ,x (,x* ...) ,[body oc? #f -> body]) `(loop ,x (,x* ...) ,body)] - [(label ,l ,[body]) - (local-label-overflow-check-set! l (and (not (eq? (local-label-overflow-check l) 'no)) oc?)) - (local-label-trap-check-set! l (and (not (eq? (local-label-trap-check l) 'no)) tc?)) - `(label ,l ,body)] - [(goto ,l) (set! goto* (cons (make-goto l oc? tc?) goto*)) ir]) - (let ([ir (Expr ir #f #f)]) - (and (andmap well-behaved-goto? goto*) ir))) - (define-pass insert-loop-traps : (L9 Expr) (ir) -> (L9.5 Expr) () - (Expr : Expr (ir) -> Expr () - [(loop ,x (,x* ...) ,[body]) `(loop ,x (,x* ...) (trap-check #f ,body))])) - (define has-no-headroom-libcall? - (lambda (e?) - (and e? - (nanopass-case (L9.5 Expr) e? - [(literal ,info) - (and (eq? (info-literal-type info) 'library) - (libspec-has-does-not-expect-headroom-version? (info-literal-addr info)) - info)] - [else #f])))) - (with-output-language (L9.5 Expr) - (define request-trap-check (if (generate-interrupt-trap) 'yes 'no)) - (define add-trap-check - (lambda (overflow? e) - (if (eq? request-trap-check 'yes) - `(trap-check ,overflow? ,e) - e))))) - (Lvalue : Lvalue (ir) -> Lvalue ('no 'no) - [(mref ,[e0 #f -> e0 oc0 tc0] ,[e1 #f -> e1 oc1 tc1] ,imm) - (values `(mref ,e0 ,e1 ,imm) (combine-seq oc0 oc1) (combine-seq tc0 tc1))]) - (Expr : Expr (ir tail?) -> Expr ('no 'no) - [(goto ,l) - (if (local-label? l) - (values `(goto ,l) (local-label-overflow-check l) (local-label-trap-check l)) - (values `(goto ,l) 'no 'no))] - [(values ,info ,[e* #f -> e* oc* tc*] ...) - (values `(values ,info ,e* ...) (fold-left combine-seq 'no oc*) (fold-left combine-seq 'no tc*))] - [(call ,info ,mdcl ,x ,[e* #f -> e* oc* tc*] ...) - (guard (uvar? x) (eq? (uvar-location x) 'loop)) - (values `(call ,info ,mdcl ,x ,e* ...) (fold-left combine-seq 'no oc*) request-trap-check)] - [(call ,info ,mdcl ,e? ,[e* #f -> e* oc* tc*] ...) - (let-values ([(e? oc tc) (if e? (Expr e? #f) (values e? 'no 'no))]) - ; to save code space, we skip trap check for error calls under assumption trap checks will - ; be made by the error handler. if not, could get a uninterruptible hard loop...c'est la vie - (define wrap-tc - (lambda (overflow? call) - (if (and (info-call-error? info) - (eq? (fold-left combine-seq tc tc*) 'no)) - call - (add-trap-check overflow? call)))) - (let ([noc? (eq? (fold-left combine-seq oc oc*) 'no)]) - (cond - [(and (or tail? (and (info-call-error? info) (fx< (debug-level) 2))) noc?) - (let ([call `(call ,info ,mdcl ,e? ,e* ...)]) - (if (info-call-pariah? info) - (values (wrap-tc #t call) 'no 'no) - (values call 'no request-trap-check)))] - [(and noc? (has-no-headroom-libcall? e?)) => - (lambda (info0) - (safe-assert (not (libspec-does-not-expect-headroom? (info-literal-addr info0)))) - (let ([call `(call ,info ,mdcl - (literal ,(make-info-literal #f 'library - (libspec->does-not-expect-headroom-libspec (info-literal-addr info0)) - 0)) - ,e* ...)]) - (if (info-call-pariah? info) - (values (wrap-tc #t call) 'no 'no) - (values call 'no request-trap-check))))] - [else (let ([call `(call ,info ,mdcl ,e? ,e* ...)]) - (if (info-call-pariah? info) - (values `(overflow-check ,(wrap-tc #f call)) 'no 'no) - (values call 'yes request-trap-check)))])))] - [(inline ,info ,prim ,[e* #f -> e* oc* tc*] ...) - (values `(inline ,info ,prim ,e* ...) (fold-left combine-seq 'no oc*) (fold-left combine-seq 'no tc*))] - [(alloc ,info ,[e #f -> e oc tc]) (values `(alloc ,info ,e) oc tc)] - [(loop ,x (,x* ...) ,body) - (uvar-location-set! x 'loop) - (let-values ([(body oc tc) (Expr body tail?)]) - (uvar-location-set! x #f) - (values - (if (eq? tc 'yes) - `(loop ,x (,x* ...) ,(add-trap-check #t body)) - `(loop ,x (,x* ...) ,body)) - (if (eq? oc 'no) 'no 'yes) - 'no))] - [(foreign-call ,info ,[e #f -> e oc tc] ,[e* #f -> e* oc* tc*] ...) - (values `(foreign-call ,info ,e ,e* ...) (fold-left combine-seq oc oc*) (fold-left combine-seq tc tc*))] - [(label ,l ,[body oc tc]) (update-label! l oc tc) (values `(label ,l ,body) oc tc)] - [(set! ,[lvalue -> lvalue oc0 tc0] ,[e #f -> e oc1 tc1]) - (values `(set! ,lvalue ,e) (combine-seq oc0 oc1) (combine-seq tc0 tc1))] - [(mvlet ,[e #f -> e oc tc] ((,x** ...) ,interface* ,[body* oc* tc*]) ...) - ; claiming mvlet always makes a nontail call - (values `(mvlet ,e ((,x** ...) ,interface* ,body*) ...) 'yes request-trap-check)] - [(mvcall ,info ,[e1 #f -> e1 oc1 tc1] ,[e2 #f -> e2 oc2 tc2]) - ; claiming mvcall always makes a nontail call - (values `(mvcall ,info ,e1 ,e2) 'yes request-trap-check)] - [(let ([,x* ,[e* #f -> e* oc* tc*]] ...) ,[body oc tc]) - (values `(let ([,x* ,e*] ...) ,body) (fold-left combine-seq oc oc*) (fold-left combine-seq tc tc*))] - [(if ,[e0 #f -> e0 oc0 tc0] ,[e1 oc1 tc1] ,[e2 oc2 tc2]) - (define combine-branch - (lambda (l r) - (case l - [(yes) (if (eq? r 'yes) 'yes 'maybe)] - [(no) (if (eq? r 'no) 'no 'maybe)] - [else l]))) - (let ([oc (combine-seq oc0 (combine-branch oc1 oc2))] - [tc (combine-seq tc0 (combine-branch tc1 tc2))]) - (define wrap-oc - (lambda (ocx e) - (if (and (eq? ocx 'yes) (not (eq? oc 'yes))) - `(overflow-check ,e) - e))) - (define wrap-tc - (lambda (tcx e) - (if (and (eq? tcx 'yes) (not (eq? tc 'yes))) - (add-trap-check #t e) - e))) - (values - `(if ,e0 ,(wrap-oc oc1 (wrap-tc tc1 e1)) ,(wrap-oc oc2 (wrap-tc tc2 e2))) - oc tc))] - [(seq ,[e0 #f -> e0 oc0 tc0] ,[e1 oc1 tc1]) - (values `(seq ,e0 ,e1) (combine-seq oc0 oc1) (combine-seq tc0 tc1))]) - (CaseLambdaClause : CaseLambdaClause (ir force-overflow?) -> CaseLambdaClause () - [(clause (,x* ...) ,mcp ,interface ,body) - (safe-assert (not repeat?)) ; should always be initialized and/or reset to #f - `(clause (,x* ...) ,mcp ,interface - ,(or (let f () - (let-values ([(body oc tc) (Expr body #t)]) - (if repeat? - (begin (set! repeat? #f) (f)) - (strip-redundant-overflow-and-trap - (let ([body (if (eq? tc 'yes) (add-trap-check #t body) body)]) - (if (or force-overflow? (eq? oc 'yes)) - `(overflow-check ,body) - body)))))) - ; punting badly here under assumption that we currently can't even generate - ; misbehaved gotos, i.e., paths ending in a goto that don't do an overflow - ; or trap check where the target label expects it to have been done. if we - ; ever violate this assumption on a regular basis, might want to revisit and - ; do something better. - ; ... test punt case by commenting out above for all but library.ss - `(overflow-check (trap-check #f ,(insert-loop-traps body)))))]) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(case-lambda ,info ,[cl* (let ([libspec (info-lambda-libspec info)]) - (and libspec (libspec-does-not-expect-headroom? libspec))) -> cl*] ...) - `(case-lambda ,info ,cl* ...)])) - - (define-pass np-rebind-on-ruined-path : L9.5 (ir) -> L9.5 () - (definitions - (define prefix*) - (define add-prefix! - (lambda (x) - (when (uvar? x) - (unless (uvar-in-prefix? x) - (uvar-in-prefix! x #t) - (set! prefix* (cons x prefix*)))))) - (define add-prefix*! (lambda (x*) (for-each add-prefix! x*))) - (define reset-prefix*! - (lambda (orig-prefix*) - (let loop ([ls prefix*] [diff* '()]) - (if (eq? ls orig-prefix*) - (begin (set! prefix* ls) diff*) - (let ([x (car ls)]) - (uvar-in-prefix! x #f) - (loop (cdr ls) (cons x diff*))))))) - (define-pass gather-refs : (L9.5 Expr) (e) -> (L9.5 Expr) (x*) - (definitions (define x*)) - (Expr : Expr (ir) -> Expr () - [,x (guard (uvar? x)) - (cond - [(uvar-in-prefix? x) - (let ([t (make-tmp 't)]) - (uvar-location-set! x t) - (uvar-in-prefix! x #f) - (set! x* (cons x x*)) - t)] - [(uvar-location x)] - [else x])]) - (fluid-let ([x* '()]) - (let ([e (Expr e)]) - (values e x*))))) - (Expr : Expr (ir) -> Expr () - [(overflow-check (call ,info ,mdcl ,e? ,e* ...)) - (guard (info-call-error? info)) - `(overflow-check (call ,info ,mdcl ,e? ,e* ...))] - [(overflow-check ,e) - (if (null? prefix*) - `(overflow-check ,e) - (let-values ([(e x*) (gather-refs e)]) - (let ([t* (map (lambda (x) - (let ([t (uvar-location x)]) - (uvar-location-set! x #f) - t)) - x*)]) - `(let ([,t* ,x*] ...) (overflow-check ,e)))))] - [(set! ,x ,[e]) - (guard (and (uvar? x) (not (uvar-assigned? x)))) - (add-prefix! x) - `(set! ,x ,e)] - [(let ([,x* ,[e*]] ...) ,body) - (add-prefix*! x*) - `(let ([,x* ,e*] ...) ,(Expr body))] - [(if ,[e0] ,e1 ,e2) - (let ([orig-prefix* prefix*]) - (let ([e1 (Expr e1)]) - (let ([e1-diff-prefix* (reset-prefix*! orig-prefix*)]) - (let ([e2 (Expr e2)]) - (add-prefix*! e1-diff-prefix*) - `(if ,e0 ,e1 ,e2)))))] - [(seq ,[e0] ,e1) `(seq ,e0 ,(Expr e1))]) - (CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause () - [(clause (,x* ...) ,mcp ,interface ,body) - (fluid-let ([prefix* x*]) - `(clause (,x* ...) ,mcp ,interface ,(Expr body)))])) - - - (define-pass np-finalize-loops : L9.5 (ir) -> L9.75 () - (Expr : Expr (ir) -> Expr () - [(loop ,x (,x* ...) ,body) - (let ([Ltop (make-local-label (uvar-name x))]) - (uvar-location-set! x (cons Ltop x*)) - (let ([body (Expr body)]) - (uvar-location-set! x #f) - `(label ,Ltop ,body)))] - [(call ,info ,mdcl ,x ,[e*] ...) - (guard (uvar-location x)) - (let ([Ltop.x* (uvar-location x)]) - (fold-left (lambda (body x e) `(seq (set! ,x ,e) ,body)) - `(goto ,(car Ltop.x*)) (cdr Ltop.x*) e*))])) - - (define-pass np-optimize-pred-in-value : L9.75 (ir) -> L9.75 () - (definitions - (define bar - (lambda (e bool?) - (if (eq? bool? 'wrapper) - (with-output-language (L9.75 Expr) - `(if ,e ,(%constant strue) ,(%constant sfalse))) - e))) - (define dont - (lambda (e) - (with-values (Expr e #f) (lambda (e bool?) e))))) - (Value : Expr (ir) -> Expr () - [else (with-values (Expr ir 'value) bar)]) - (Lvalue : Lvalue (ir) -> Expr (#f)) - (Expr : Expr (ir [value? #f]) -> Expr (#f) - [(immediate ,imm) (values ir (or (eq? imm (constant strue)) (eq? imm (constant sfalse))))] - [(set! ,lvalue ,[e]) (values `(set! ,lvalue ,e) #f)] - [(seq ,[dont : e0] ,[e1 bool?]) (values `(seq ,e0 ,e1) bool?)] - [(let ([,x* ,[e*]] ...) ,[e bool?]) (values `(let ([,x* ,e*] ...) ,e) bool?)] - [(inline ,info ,prim ,[e*] ...) - (guard (pred-primitive? prim)) - (values `(inline ,info ,prim ,e* ...) #t)] - [(if ,[dont : e0] ,[e1 bool1?] ,[e2 bool2?]) - (guard value?) - (if (and bool1? bool2?) - (values `(if ,e0 ,e1 ,e2) 'wrapper) - (values `(if ,e0 ,(bar e1 bool1?) ,(bar e2 bool2?)) #f))])) - - (define-pass np-remove-complex-opera* : L9.75 (ir) -> L10 () - ; remove-complex-opera* cannot assume that assigned uvars and - ; (mrefs at this point) are immutable. it must take this into - ; account and avoid possible interleaved subexpression evaluation - ; for calls and inline forms. it can do so by removing all lvalues - ; as call/inline subexpressions, or it can be more selective and - ; allow them to remain when doing so can't cause any problems. - ; for example, ( ) can be left alone, and both - ; - ; ((begin e ) ) => (begin e ( )) - ; - ; and - ; - ; ( (begin e )) => (begin e ( )) - ; - ; are safe transformations, but - ; - ; ((begin e1 ) (begin e2 )) - ; - ; cannot be turned into - ; - ; (begin e1 e2 ( )). - ; - ; NB: remove-complex-opera* produces set! forms rather than let bindings - ; since the former (but not the latter) can be pushed into both branches - ; of an if without causing potentially exponential code growth - (definitions - (define local*) - (define make-tmp - (lambda (x) - (import (only np-languages make-tmp)) - (let ([x (make-tmp x)]) - (set! local* (cons x local*)) - x))) - (define Ref - (lambda (ir setup*) - (if (var? ir) - (values ir setup*) - (let ([tmp (make-tmp 't)]) - (values tmp (cons (Rhs ir tmp) setup*)))))) - (define Lvalue? - (lambda (x) - (nanopass-case (L10 Triv) x - [,lvalue #t] - [else #f]))) - (define Triv* - (lambda (e* k) - (let f ([e* e*] [lvalue-setup* '()] [rt* '()] [setup* '()]) - (if (null? e*) - (build-seq* setup* - (build-seq* lvalue-setup* - (k (reverse rt*)))) - (let-values ([(t t-setup*) (Triv (car e*) (null? lvalue-setup*))]) - (if (and (null? lvalue-setup*) - (not (null? t-setup*)) - (Lvalue? t) - ; uvar's are singly assigned - (or (not (uvar? t)) (uvar-assigned? t))) - (f (cdr e*) t-setup* (cons t rt*) setup*) - (f (cdr e*) lvalue-setup* (cons t rt*) (append t-setup* setup*)))))))) - (define build-seq* (lambda (x* y) (fold-right build-seq y x*))) - (with-output-language (L10 Expr) - (define build-seq (lambda (x y) `(seq ,x ,y))) - (define Rhs - (lambda (ir lvalue) - (Expr ir - (lambda (e) - (nanopass-case (L10 Expr) e - [,rhs `(set! ,lvalue ,rhs)] - [(values ,info ,t) `(set! ,lvalue ,t)] - [(values ,info ,t* ...) - ; sets lvalue to void. otherwise, the lvalue we entered with (which - ; might be referenced downstream) is never set and hence fails in the live - ; analysis where it is live all the way out of the function. - `(seq - (call ,(make-info-call (info-call-src info) (info-call-sexpr info) #f #t #t) #f - (literal ,(make-info-literal #t 'object '$oops (constant symbol-value-disp))) - ,(%constant sfalse) - (literal ,(make-info-literal #f 'object - (format "returned ~r values to single value return context" - (length t*)) 0))) - (set! ,lvalue ,(%constant svoid)))] - [else (sorry! who "unexpected Rhs expression ~s" e)]))))))) - (CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause () - [(clause (,x* ...) ,mcp ,interface ,body) - (fluid-let ([local* '()]) - (let ([body (Expr body values)]) - (safe-assert (nodups x* local*)) - `(clause (,x* ...) (,local* ...) ,mcp ,interface - ,body)))]) - (Triv : Expr (ir lvalue-okay?) -> Triv (setup*) - [,x - (guard (or lvalue-okay? (and (uvar? x) (not (uvar-assigned? x))) (eq? x %zero))) - (values x '())] - [(mref ,e1 ,e2 ,imm) - (guard lvalue-okay?) - (let*-values ([(x1 setup*) (Ref e1 '())] [(x2 setup*) (Ref e2 setup*)]) - (values (%mref ,x1 ,x2 ,imm) setup*))] - [(literal ,info) (values `(literal ,info) '())] - [(immediate ,imm) (values `(immediate ,imm) '())] - [(label-ref ,l ,offset) (values `(label-ref ,l ,offset) '())] - [(let ([,x* ,e*] ...) ,[t setup*]) - (set! local* (append x* local*)) - (safe-assert (nodups local*)) - (values t - (fold-right - (lambda (ir lvalue setup*) (cons (Rhs ir lvalue) setup*)) - setup* e* x*))] - [(seq ,[Expr : e0 values -> e0] ,[t setup*]) - (values t (cons e0 setup*))] - [(pariah) (values (%constant svoid) (list (with-output-language (L10 Expr) `(pariah))))] - [else - (let ([tmp (make-tmp 't)]) - (values tmp (list (Rhs ir tmp))))]) - (Expr : Expr (ir k) -> Expr () - [(inline ,info ,prim ,e1* ...) - (Triv* e1* - (lambda (t1*) - (k `(inline ,info ,prim ,t1* ...))))] - [(alloc ,info ,e) - (let-values ([(t setup*) (Triv e #t)]) - (build-seq* setup* (k `(alloc ,info ,t))))] - [(call ,info ,mdcl ,e0? ,e1* ...) - (if e0? - (Triv* (cons e0? e1*) (lambda (t*) (k `(call ,info ,mdcl ,(car t*) ,(cdr t*) ...)))) - (Triv* e1* (lambda (t*) (k `(call ,info ,mdcl #f ,t* ...)))))] - [(foreign-call ,info ,e0 ,e1* ...) - (Triv* (cons e0 e1*) - (lambda (t*) - (k `(foreign-call ,info ,(car t*) ,(cdr t*) ...))))] - [(values ,info ,e* ...) - (Triv* e* - (lambda (t*) - (k `(values ,info ,t* ...))))] - [(if ,[Expr : e0 values -> e0] ,[e1] ,[e2]) `(if ,e0 ,e1 ,e2)] - [(seq ,[Expr : e0 values -> e0] ,[e1]) `(seq ,e0 ,e1)] - [(set! ,lvalue ,e) - (let-values ([(lvalue setup*) (Triv lvalue #t)]) - ; must put lvalue setup* first to avoid potentially interleaved argument - ; evaluation in, e.g.: - ; - ; (let ([p1 (cons 0 1)] [p2 (cons 0 2)]) - ; (let ([x (cons 0 3)]) - ; (set-car! - ; (begin (set-car! x p1) (car x)) - ; (begin (set-car! x p2) (car x))) - ; (eq? (car p1) p2))) - ; ; after expand-primitives (essentially): - ; => (let ([p1 (cons 0 1)] [p2 (cons 0 2)]) - ; (let ([x (cons 0 3)]) - ; (set! - ; ,(%mref (begin (set! ,(%mref x 0) p1) ,(%mref x 0)) 0) - ; (begin (set! ,(%mref x 0) p2) ,(%mref x 0))) - ; (eq? ,(%mref p1 0) p2))) - ; ; okay: - ; => (let ([p1 (cons 0 1)] [p2 (cons 0 2)]) - ; (let ([x (cons 0 3)]) - ; ; setup* for lvalue: - ; (set! ,(%mref x 0) p1) - ; (set! t ,(%mref x 0)) - ; ; setup* for e - ; (set! ,(%mref x 0) p2) - ; (set! ,(%mref t 0) ,(%mref x 0)) - ; (eq? ,(%mref p1 0) p2))) - ; ; not okay: - ; => (let ([p1 (cons 0 1)] [p2 (cons 0 2)]) - ; (let ([x (cons 0 3)]) - ; ; setup* for e - ; (set! ,(%mref x 0) p2) - ; ; setup* for lvalue: - ; (set! ,(%mref x 0) p1) - ; (set! t ,(%mref x 0)) - ; (set! - ; ,(%mref t 0) - ; ; wrong x[0] - ; ,(%mref x 0)) - ; (eq? ,(%mref p1 0) p2))) - (build-seq* setup* - `(seq - ,(Rhs e lvalue) - ,(k (%constant svoid)))))] - [(let ([,x* ,e*] ...) ,[body]) - (set! local* (append x* local*)) - (safe-assert (nodups local*)) - (fold-left (lambda (t x e) (build-seq (Rhs e x) t)) body x* e*)] - [(mvlet ,[Expr : e values -> e] ((,x** ...) ,interface* ,[body*]) ...) - (set! local* (append (apply append x**) local*)) - (safe-assert (nodups local*)) - `(mvlet ,e ((,x** ...) ,interface* ,body*) ...)] - [(mvcall ,info ,[Expr : e1 values -> e1] ,e2) - (let-values ([(t2 setup*) (Triv e2 #t)]) - (build-seq* setup* (k `(mvcall ,info ,e1 ,t2))))] - [(goto ,l) `(goto ,l)] - [(label ,l ,[body]) `(label ,l ,body)] - [(trap-check ,ioc ,[body]) `(trap-check ,ioc ,body)] - [(overflow-check ,[body]) `(overflow-check ,body)] - [(pariah) `(pariah)] - [(profile ,src) `(profile ,src)] - [else - (let-values ([(t setup*) (Triv ir #t)]) - (build-seq* setup* (k t)))])) - - (define-pass np-push-mrvs : L10 (ir) -> L10.5 () - (definitions - (define local*) - (define make-tmp - (lambda (x) - (import (only np-languages make-tmp)) - (let ([x (make-tmp x)]) - (set! local* (cons x local*)) - x))) - (define Mvcall - (lambda (info e consumer k) - (with-output-language (L10.5 Expr) - (nanopass-case (L10.5 Expr) e - [,t (k `(mvcall ,(make-info-call (info-call-src info) (info-call-sexpr info) #f #f #f) #f ,consumer ,t ()))] - [(values ,info2 ,t* ...) - (k `(mvcall ,(make-info-call (info-call-src info) (info-call-sexpr info) #f #f #f) #f ,consumer ,t* ... ()))] - [(mvcall ,info ,mdcl ,t0 ,t1* ... (,t* ...)) - (k `(mvcall ,info ,mdcl ,t0 ,t1* ... (,t* ... ,consumer)))] - [(if ,e0 ,[e1] ,[e2]) `(if ,e0 ,e1 ,e2)] - [(seq ,e0 ,[e1]) `(seq ,e0 ,e1)] - [(mlabel ,[e] (,l* ,[e*]) ...) `(mlabel ,e (,l* ,e*) ...)] - [(label ,l ,[body]) `(label ,l ,body)] - [(trap-check ,ioc ,[body]) `(trap-check ,ioc ,body)] - [(overflow-check ,[body]) `(overflow-check ,body)] - [(pariah) `(pariah)] - [(profile ,src) `(profile ,src)] - [(goto ,l) `(goto ,l)] - [,rhs ; alloc, inline, foreign-call - (let ([tmp (make-tmp 't)]) - `(seq - (set! ,tmp ,rhs) - ,(k `(mvcall ,(make-info-call (info-call-src info) (info-call-sexpr info) #f #f #f) #f ,consumer ,tmp ()))))] - [else ; set! & mvset - `(seq ,e ,(k `(mvcall ,(make-info-call (info-call-src info) (info-call-sexpr info) #f #f #f) #f ,consumer ,(%constant svoid) ())))]))))) - (CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause () - [(clause (,x* ...) (,local0* ...) ,mcp ,interface ,body) - (fluid-let ([local* local0*]) - (let ([body (Expr body)]) - (safe-assert (nodups x* local*)) - `(clause (,x* ...) (,local* ...) ,mcp ,interface - ,body)))]) - (Rhs : Rhs (ir) -> Rhs () - [(call ,info ,mdcl ,[t0?] ,[t1*] ...) `(mvcall ,info ,mdcl ,t0? ,t1* ... ())]) - (Expr : Expr (ir) -> Expr () - [(mvcall ,info ,[e] ,[t]) (Mvcall info e t values)] - [(set! ,[lvalue] (mvcall ,info ,[e] ,[t])) - (Mvcall info e t (lambda (rhs) `(set! ,lvalue ,rhs)))] - [(mvlet ,[e] ((,x** ...) ,interface* ,body*) ...) - (let ([label* (map (lambda (x) (make-local-label 'mv)) body*)]) - (define Pvalues - (lambda (info t*) - (define build-assignments - (lambda (x* t* body) - (fold-left - (lambda (body x t) - ; okay to drop t since it's a triv - (if (uvar-referenced? x) - `(seq (set! ,x ,t) ,body) - body)) - body x* t*))) - (find-matching-clause (length t*) x** interface* label* - (lambda (x* label) - ; mark label referenced so it won't be discarded - (local-label-iteration-set! label #t) - (build-assignments x* t* `(goto ,label))) - (lambda (nfixed x* label) - ; mark label referenced so it won't be discarded - (local-label-iteration-set! label #t) - (let ([xfixed* (list-head x* nfixed)] - [tfixed* (list-head t* nfixed)] - [xvar (list-ref x* nfixed)] - [tvar* (list-tail t* nfixed)]) - ; the args are all trivs, otherwise this code would not properly build the rest - ; list after all of the arguments have been evaluated (and it couldn't suppress - ; the list creation when xvar is unreferenced) - (build-assignments xfixed* tfixed* - (if (uvar-referenced? xvar) - `(seq - ,(if (null? tvar*) - `(set! ,xvar ,(%constant snil)) - (let ([t (make-tmp 't)]) - `(seq - (set! ,t ,(%constant-alloc type-pair - (fx* (constant size-pair) (length tvar*)))) - ,(let f ([tvar* tvar*] [offset 0]) - (let ([tvar (car tvar*)] [tvar* (cdr tvar*)]) - `(seq - (set! ,(%mref ,t - ,(fx+ (constant pair-car-disp) offset)) - ,tvar) - ,(if (null? tvar*) - `(seq - (set! ,(%mref ,t - ,(fx+ (constant pair-cdr-disp) offset)) - ,(%constant snil)) - (set! ,xvar ,t)) - (let ([next-offset (fx+ offset (constant size-pair))]) - `(seq - (set! ,(%mref ,t - ,(fx+ (constant pair-cdr-disp) offset)) - ,(%lea ,t next-offset)) - ,(f tvar* next-offset)))))))))) - (goto ,label)) - `(goto ,label))))) - (lambda () - (let ([src (and info (info-call-src info))] [sexpr (and info (info-call-sexpr info))]) - `(seq - (pariah) - (mvcall ,(make-info-call src sexpr #f #t #t) #f - (literal ,(make-info-literal #t 'object '$oops (constant symbol-value-disp))) - ,(%constant sfalse) - (literal ,(make-info-literal #f 'object "incorrect number of values received in multiple value context" 0)) - ()))))))) - (let ([e (nanopass-case (L10.5 Expr) e - [,t (Pvalues #f (list t))] - [(values ,info ,t* ...) (Pvalues info t*)] - [(mvcall ,info ,mdcl ,t0? ,t1* ... (,t* ...)) - (for-each (lambda (l) (local-label-iteration-set! l #t)) label*) - `(mvset ,info (,mdcl ,t0? ,t1* ...) (,t* ...) ((,x** ...) ,interface* ,label*) ...)] - [(if ,e0 ,[e1] ,[e2]) `(if ,e0 ,e1 ,e2)] - [(seq ,e0 ,[e1]) `(seq ,e0 ,e1)] - [(label ,l ,[body]) `(label ,l ,body)] - [(profile ,src) `(profile ,src)] - [(trap-check ,ioc ,[body]) `(trap-check ,ioc ,body)] - [(overflow-check ,[body]) `(overflow-check ,body)] - [(pariah) `(pariah)] - [(mlabel ,[e] (,l* ,[e*]) ...) `(mlabel ,e (,l* ,e*) ...)] - [(goto ,l) `(goto ,l)] - [,rhs ; alloc, inline, foreign-call - (let ([tmp (make-tmp 't)]) - `(seq - (set! ,tmp ,rhs) - ,(Pvalues #f (list tmp))))] - [else ; set! & mvset - `(seq ,e ,(Pvalues #f (list (%constant svoid))))])]) - (let-values ([(label* body*) - (let loop ([label* label*] [body* body*] [rlabel* '()] [rbody* '()]) - (if (null? label*) - (values rlabel* rbody*) - (let* ([label (car label*)]) - (if (local-label-iteration label) - (begin - (local-label-iteration-set! label #f) - (loop (cdr label*) (cdr body*) - (cons label rlabel*) - (cons (Expr (car body*)) rbody*))) - (loop (cdr label*) (cdr body*) rlabel* rbody*)))))]) - `(mlabel ,e (,label* ,body*) ...))))])) - - (define-pass np-normalize-context : L10.5 (ir) -> L11 () - (definitions - (define local*) - (define make-tmp - (lambda (x) - (import (only np-languages make-tmp)) - (let ([x (make-tmp x)]) - (set! local* (cons x local*)) - x))) - (define rhs-inline - (lambda (lvalue info prim t*) - (with-output-language (L11 Effect) - (cond - [(pred-primitive? prim) - `(if (inline ,info ,prim ,t* ...) - (set! ,lvalue ,(%constant strue)) - (set! ,lvalue ,(%constant sfalse)))] - [(effect-primitive? prim) - `(seq - (inline ,info ,prim ,t* ...) - (set! ,lvalue ,(%constant svoid)))] - [(not (value-primitive? prim)) ($oops who "unrecognized prim ~s" prim)] - [else `(set! ,lvalue (inline ,info ,prim ,t* ...))]))))) - (CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause () - [(clause (,x* ...) (,local0* ...) ,mcp ,interface ,body) - (fluid-let ([local* local0*]) - (let ([tlbody (Tail body)]) - (safe-assert (nodups x* local*)) - `(clause (,x* ...) (,local* ...) ,mcp ,interface ,tlbody)))]) - (Pred : Expr (ir) -> Pred () - (definitions - (define-syntax predicafy-triv - (syntax-rules () - [(_ ?t) - `(if ,(%inline eq? ?t (immediate ,(constant sfalse))) - (false) - (true))])) - (define-syntax predicafy-rhs - (syntax-rules () - [(_ ?rhs) - (let ([t (make-tmp 't)]) - `(seq - (set! ,t ?rhs) - ,(predicafy-triv ,t)))]))) - [,x (predicafy-triv ,x)] - [(mref ,x1 ,x2 ,imm) (predicafy-triv ,(%mref ,x1 ,x2 ,imm))] - [(literal ,info) - (if (info-literal-indirect? info) - (predicafy-triv (literal ,info)) - (if (and (eq? (info-literal-type info) 'object) - (eq? (info-literal-addr info) #f) - (eqv? (info-literal-offset info) 0)) - `(false) - `(true)))] - [(immediate ,imm) (if (eqv? imm (constant sfalse)) `(false) `(true))] - [(label-ref ,l ,offset) `(true)] - [(mvcall ,info ,mdcl ,[t0?] ,[t1] ... (,[t*] ...)) - (if (and (info-call-error? info) (fx< (debug-level) 2)) - `(seq (tail (mvcall ,info ,mdcl ,t0? ,t1 ... (,t* ...))) (true)) - (predicafy-rhs (mvcall ,info ,mdcl ,t0? ,t1 ... (,t* ...))))] - [(foreign-call ,info ,[t0] ,[t1] ...) (predicafy-rhs (foreign-call ,info ,t0 ,t1 ...))] - [(label ,l ,[pbody]) `(seq (label ,l) ,pbody)] - [(trap-check ,ioc ,[pbody]) `(seq (trap-check ,ioc) ,pbody)] - [(overflow-check ,[pbody]) `(seq (overflow-check) ,pbody)] - [(profile ,src) `(seq (profile ,src) (true))] - [(pariah) `(seq (pariah) (true))] - [(alloc ,info ,t) `(true)] - [(inline ,info ,prim ,[t*] ...) - (guard (value-primitive? prim)) - (predicafy-rhs (inline ,info ,prim ,t* ...))] - [(inline ,info ,prim ,[t*] ...) - (guard (effect-primitive? prim)) - `(seq (inline ,info ,prim ,t* ...) (true))] - [(inline ,info ,prim ,t* ...) - (guard (not (pred-primitive? prim))) - ($oops who "unrecognized prim ~s" prim)] - [(set! ,[lvalue] (inline ,info ,prim ,[t*] ...)) - `(seq ,(rhs-inline lvalue info prim t*) (true))] - [(set! ,[lvalue] (mvcall ,info ,mdcl ,[t0?] ,[t1] ... (,[t*] ...))) - (guard (info-call-error? info) (fx< (debug-level) 2)) - (%seq - (tail (mvcall ,info ,mdcl ,t0? ,t1 ... (,t* ...))) - (true))] - [(set! ,[lvalue] ,[rhs]) `(seq (set! ,lvalue ,rhs) (true))] - [(mvset ,info (,mdcl ,[t0?] ,[t1] ...) (,[t*] ...) ((,x** ...) ,interface* ,l*) ...) - `(seq - (mvset ,info (,mdcl ,t0? ,t1 ...) (,t* ...) ((,x** ...) ,interface* ,l*) ...) - (true))] - [(values ,info ,t) (Pred t)] - [(values ,info ,t* ...) - `(seq (mvcall ,(make-info-call (info-call-src info) (info-call-sexpr info) #f #t #t) #f - (literal ,(make-info-literal #t 'object '$oops (constant symbol-value-disp))) - ,(%constant sfalse) - (literal ,(make-info-literal #f 'object - (format "returned ~r values to single value return context" - (length t*)) 0)) - ()) - (true))]) - (Effect : Expr (ir) -> Effect () - [,x `(nop)] - [(mref ,x1 ,x2 ,imm) `(nop)] - [(literal ,info) `(nop)] - [(immediate ,imm) `(nop)] - [(label-ref ,l ,offset) `(nop)] - [(alloc ,info ,t) `(nop)] - [(inline ,info ,prim ,[t*] ...) - (cond - [(primitive-pure? prim) `(nop)] ; TODO: do we get any of these when cp0 is run? - [(value-primitive? prim) - `(set! ,(make-tmp 'waste) (inline ,info ,prim ,t* ...))] - [(pred-primitive? prim) - `(if (inline ,info ,prim ,t* ...) (nop) (nop))] - [else `(inline ,info ,prim ,t* ...)])] - [(set! ,[lvalue] (inline ,info ,prim ,[t*] ...)) - (rhs-inline lvalue info prim t*)] - [(set! ,[lvalue] (mvcall ,info ,mdcl ,[t0?] ,[t1] ... (,[t*] ...))) - (guard (info-call-error? info) (fx< (debug-level) 2)) - `(tail (mvcall ,info ,mdcl ,t0? ,t1 ... (,t* ...)))] - [(label ,l ,[ebody]) `(seq (label ,l) ,ebody)] - [(trap-check ,ioc ,[ebody]) `(seq (trap-check ,ioc) ,ebody)] - [(overflow-check ,[ebody]) `(seq (overflow-check) ,ebody)] - [(profile ,src) `(profile ,src)] - [(pariah) `(pariah)] - [(mvcall ,info ,mdcl ,[t0?] ,[t1] ... (,[t*] ...)) - (guard (info-call-error? info) (fx< (debug-level) 2)) - `(tail (mvcall ,info ,mdcl ,t0? ,t1 ... (,t* ...)))] - [(mlabel ,[e] (,l* ,[e*]) ...) - (let ([join (make-local-label 'mjoin)]) - `(seq - ,(let f ([e e] [l* l*] [e* e*]) - (if (null? l*) - e - (%seq ,e (goto ,join) - ,(f `(seq (label ,(car l*)) ,(car e*)) (cdr l*) (cdr e*))))) - (label ,join)))] - [(values ,info ,t* ...) `(nop)]) - (Tail : Expr (ir) -> Tail () - [(inline ,info ,prim ,[t*] ...) - (guard (pred-primitive? prim)) - `(if (inline ,info ,prim ,t* ...) - ,(%constant strue) - ,(%constant sfalse))] - [(inline ,info ,prim ,[t*] ...) - (guard (effect-primitive? prim)) - `(seq (inline ,info ,prim ,t* ...) ,(%constant svoid))] - [(inline ,info ,prim ,t* ...) - (guard (not (value-primitive? prim))) - ($oops who "unrecognized prim ~s" prim)] - [(set! ,[lvalue] (inline ,info ,prim ,[t*] ...)) - `(seq ,(rhs-inline lvalue info prim t*) ,(%constant svoid))] - [(set! ,[lvalue] (mvcall ,info ,mdcl ,[t0?] ,[t1] ... (,[t*] ...))) - (guard (info-call-error? info) (fx< (debug-level) 2)) - `(mvcall ,info ,mdcl ,t0? ,t1 ... (,t* ...))] - [(set! ,[lvalue] ,[rhs]) `(seq (set! ,lvalue ,rhs) ,(%constant svoid))] - [(mvset ,info (,mdcl ,[t0?] ,[t1] ...) (,[t*] ...) ((,x** ...) ,interface* ,l*) ...) - `(seq - (mvset ,info (,mdcl ,t0? ,t1 ...) (,t* ...) ((,x** ...) ,interface* ,l*) ...) - ,(%constant svoid))] - [(label ,l ,[tlbody]) `(seq (label ,l) ,tlbody)] - [(trap-check ,ioc ,[tlbody]) `(seq (trap-check ,ioc) ,tlbody)] - [(overflow-check ,[tlbody]) `(seq (overflow-check) ,tlbody)] - [(profile ,src) `(seq (profile ,src) ,(%constant svoid))] - [(pariah) `(seq (pariah) ,(%constant svoid))] - [(mlabel ,[tl] (,l* ,[tl*]) ...) - (let f ([tl tl] [l* l*] [tl* tl*]) - (if (null? l*) - tl - `(seq - (tail ,tl) - ,(f `(seq (label ,(car l*)) ,(car tl*)) (cdr l*) (cdr tl*)))))])) - - (define-pass np-insert-trap-check : L11 (ir) -> L11.5 () - (Effect : Effect (ir) -> Effect () - [(trap-check ,ioc) - `(seq - (set! ,(ref-reg %trap) ,(%inline -/eq ,(ref-reg %trap) (immediate 1))) - (if (inline ,(make-info-condition-code 'eq? #f #t) ,%condition-code) - ,(%seq - (pariah) - (mvcall ,(make-info-call #f #f #f #t #f) #f - (literal ,(make-info-literal #f 'library - (if ioc - (lookup-does-not-expect-headroom-libspec event) - (lookup-libspec event)) - 0)) - ())) - (nop)))])) - - (define-pass np-flatten-case-lambda : L11.5 (ir) -> L12 () - (definitions - (define Ldoargerr (make-Ldoargerr)) - (define Ldomvleterr (make-Ldomvleterr)) - (define flatten-clauses - (lambda (info cl* dcl*) - (let ([libspec (info-lambda-libspec info)]) - (with-output-language (L12 Tail) - (when libspec - (safe-assert (equal? (info-lambda-interface* info) (list (libspec-interface libspec)))) - (if (null? (info-lambda-fv* info)) - (when (libspec-closure? libspec) - ($oops who "libspec claims closure needed, but no free variables for ~s" (libspec-name libspec))) - (unless (libspec-closure? libspec) - ($oops who "libspec claims no closure needed, but has free variables ~s for ~s" (info-lambda-fv* info) (libspec-name libspec))))) - (if (or (info-lambda-well-known? info) libspec) - (let loop ([cl* cl*] [dcl* dcl*] [local* '()] [tlbody #f]) - (if (null? cl*) - (values local* (or tlbody (%constant svoid))) - (if (or libspec (direct-call-label-referenced (car dcl*))) - (nanopass-case (L11.5 CaseLambdaClause) (car cl*) - [(clause (,x* ...) (,local1* ...) ,mcp ,interface ,tlbody1) - (loop (cdr cl*) (cdr dcl*) (maybe-cons mcp (append x* local1* local*)) - (let ([tlbody1 `(entry-point (,x* ...) ,(car dcl*) ,mcp ,(Tail tlbody1))]) - (if tlbody - `(seq (tail ,tlbody) ,tlbody1) - tlbody1)))]) - (loop (cdr cl*) (cdr dcl*) local* tlbody)))) - (let f ([cl* cl*] [dcl* dcl*]) - (if (null? cl*) - (values '() `(seq (pariah) (goto ,Ldoargerr))) - (nanopass-case (L11.5 CaseLambdaClause) (car cl*) - [(clause (,x* ...) (,local* ...) ,mcp ,interface ,tlbody) - (let ([tlbody `(entry-point (,x* ...) ,(car dcl*) ,mcp ,(Tail tlbody))]) - (if (fx< interface 0) - (let ([fixed-args (lognot interface)]) - (let ([tlbody (if (uvar-referenced? (list-ref x* fixed-args)) - `(seq (do-rest ,fixed-args) ,tlbody) - tlbody)]) - (if (fx= fixed-args 0) - (values (maybe-cons mcp (append x* local*)) tlbody) - (let-values ([(next-local* next-tlbody) (f (cdr cl*) (cdr dcl*))]) - (values - (maybe-cons mcp (append x* local* next-local*)) - `(if ,(%inline u< ,%ac0 - (immediate ,fixed-args)) - ,next-tlbody - ,tlbody)))))) - (let-values ([(next-local* next-tlbody) (f (cdr cl*) (cdr dcl*))]) - (values - (maybe-cons mcp (append x* local* next-local*)) - `(if ,(%inline eq? ,%ac0 - (immediate ,interface)) - ,tlbody - ,next-tlbody)))))])))))))) - (define flatten-mvclauses - (lambda (x** interface* l*) - (with-output-language (L12 Effect) - (if (null? x**) - (%seq - (pariah) - ;; mverror point ensures that the call's return address - ;; is in sfp[0], so the caller's frame is still - ;; on the stack for error reporting and debugging - (mverror-point) - (goto ,Ldomvleterr)) - (let ([x* (car x**)] [interface (car interface*)] [l (car l*)]) - (let ([ebody `(mventry-point (,x* ...) ,l)]) - (if (fx< interface 0) - (let ([fixed-args (lognot interface)]) - (let ([ebody (if (uvar-referenced? (list-ref x* fixed-args)) - `(seq (do-rest ,fixed-args) ,ebody) - ebody)]) - (if (fx= fixed-args 0) - ebody - (let ([next-ebody (flatten-mvclauses (cdr x**) (cdr interface*) (cdr l*))]) - `(if ,(%inline u< ,%ac0 - (immediate ,fixed-args)) - ,next-ebody - ,ebody))))) - (let ([next-ebody (flatten-mvclauses (cdr x**) (cdr interface*) (cdr l*))]) - `(if ,(%inline eq? ,%ac0 - (immediate ,interface)) - ,ebody - ,next-ebody)))))))))) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(case-lambda ,info ,cl* ...) - (let-values ([(local* tlbody) (flatten-clauses info cl* (info-lambda-dcl* info))]) - (safe-assert (nodups local*)) - (info-lambda-dcl*-set! info (filter direct-call-label-referenced (info-lambda-dcl* info))) - `(lambda ,info (,local* ...) ,tlbody))]) - (Tail : Tail (ir) -> Tail ()) - (Effect : Effect (ir) -> Effect () - [(mvset ,info (,mdcl ,[t0?] ,[t1] ...) (,[t*] ...) ((,x** ...) ,interface* ,l*) ...) - `(mvset ,info (,mdcl ,t0? ,t1 ...) (,t* ...) ((,x** ...) ...) - ,(flatten-mvclauses x** interface* l*))])) - - (define-pass np-impose-calling-conventions : L12 (ir) -> L13 () - (definitions - (import (only asm-module asm-foreign-call asm-foreign-callable asm-enter)) - (define newframe-info-for-mventry-point) - (define label-for-mverror-point) - (define Lcall-error (make-Lcall-error)) - (define dcl*) - (define local*) - (define max-fv) - (define le-label) - (define-$type-check (L13 Pred)) - (define make-tmp - (lambda (x) - (import (only np-languages make-tmp)) - (let ([x (make-tmp x)]) - (set! local* (cons x local*)) - x))) - (define set-formal-registers! - (lambda (x*) - (let do-reg ([x* x*] [reg* arg-registers]) - (if (or (null? x*) (null? reg*)) - x* - (begin - (uvar-location-set! (car x*) (car reg*)) - (do-reg (cdr x*) (cdr reg*))))))) - (define get-arg-regs - (lambda (t*) - (let f ([t* t*] [reg* arg-registers]) - (if (or (null? t*) (null? reg*)) - (values '() '() t*) - (let ([reg (car reg*)]) - (let-values ([(reg* reg-t* frame-t*) (f (cdr t*) (cdr reg*))]) - (values (cons reg reg*) (cons (car t*) reg-t*) frame-t*))))))) - (module (build-tail-call build-nontail-call build-mv-return) - (define symref? - (lambda (info) - (and (info-literal-indirect? info) - (eq? (info-literal-type info) 'object) - (let ([x (info-literal-addr info)]) - (and (symbol? x) - (eqv? (info-literal-offset info) (constant symbol-value-disp)) - x))))) - (define libref? - (lambda (info) - (and (not (info-literal-indirect? info)) - (eq? (info-literal-type info) 'library) - (let ([x (info-literal-addr info)]) - (and (libspec? x) - (eqv? (info-literal-offset info) 0) - x))))) - (define build-call - (with-output-language (L13 Tail) - (case-lambda - [(t rpl reg* fv* maybe-info mdcl) - (build-call t #f rpl reg* fv* maybe-info mdcl #f)] - [(t cploc rpl reg* fv* maybe-info mdcl consumer?) - (let () - (define set-return-address - (lambda (tl) - (if rpl - (%seq (set! ,%ref-ret (label-ref ,rpl ,(constant size-rp-header))) ,tl) - (meta-cond - [(real-register? '%ret) (%seq (set! ,%ret ,(get-fv 0)) ,tl)] - [else tl])))) - (define finish-call - (lambda (argcnt? cp? t) - (safe-assert (not (eq? t (get-fv 0)))) - (let ([live-reg* (reg-cons* %ret (if cp? (reg-cons* %cp reg*) reg*))] - [live-fv* (meta-cond - [(real-register? '%ret) fv*] - [else (cons (get-fv 0) fv*)])]) - (if consumer? - `(jump ,t (,%ac0 ,live-reg* ... ,live-fv* ...)) - (if argcnt? - `(seq - (set! ,%ac0 (immediate ,(fx+ (length reg*) (length fv*)))) - (jump ,t (,%ac0 ,live-reg* ... ,live-fv* ...))) - `(jump ,t (,live-reg* ... ,live-fv* ...))))))) - (define direct-call - (lambda () - (if rpl - `(joto ,mdcl (,fv* ...)) - `(goto ,mdcl)))) - (define normal-call - (lambda () - (define cploc-is-cp? - (lambda () - ; cploc must be #f, an nfv, %cp or an mref tc[cp] - (meta-cond - [(real-register? '%cp) (eq? cploc %cp)] - [else (and cploc (not (var? cploc)))]))) - (define-syntax set-cp - (syntax-rules () - [(_ lhs rhs ?tl) - (let ([tl `?tl]) - (if (cploc-is-cp?) - tl - `(seq (set! lhs rhs) ,tl)))])) - (define insert-procedure-check - (lambda (reg tlbody) - (if (and maybe-info (info-call-check? maybe-info)) - `(if ,(%type-check mask-closure type-closure ,reg) - ,tlbody - (seq (pariah) (goto ,Lcall-error))) - tlbody))) - (if mdcl - (set-cp ,(ref-reg %cp) ,(or cploc (Triv t)) - ,(set-return-address - (if (memq mdcl dcl*) - (direct-call) - (finish-call #f ; don't set the argcount, since it doesn't need to be checked - #t (in-context Triv `(label-ref ,mdcl 0)))))) - (meta-cond - [(real-register? '%cp) - (set-cp ,%cp ,(or cploc (Triv t)) - ,(set-return-address ; must be set before potential jump to call-error - (insert-procedure-check %cp - (finish-call #t #t - (in-context Triv - (%mref ,%cp ,(constant closure-code-disp)))))))] - [else - `(seq - (set! ,%xp ,(or cploc (Triv t))) - ,(set-cp ,(ref-reg %cp) ,%xp - ,(set-return-address ; must be set before potential jump to call-error - (insert-procedure-check %xp - (finish-call #t #t - (in-context Triv - (%mref ,%xp ,(constant closure-code-disp))))))))])))) - (if (not t) - (set-return-address - (if (memq mdcl dcl*) - (direct-call) - (finish-call #f #f (in-context Triv `(label-ref ,mdcl 0))))) - (nanopass-case (L12 Triv) t - ; if the expression in the cp position #f, and we have an mdcl, this is - ; a hackish workaround for not having a good way to express maybe-Expr - [(literal ,info) - (cond - [(symref? info) => - ; okay to do pvalue call even if this is a consumer call since only primrefs - ; come through as consumer symrefs - (lambda (sym) - (%seq - (set! ,%xp (literal ,(make-info-literal #f 'object sym 0))) - (set! ,(ref-reg %cp) ,(%mref ,%xp ,(constant symbol-value-disp))) - ,(set-return-address - (finish-call #t #t - (in-context Triv - (%mref ,%xp ,(constant symbol-pvalue-disp)))))))] - [(libref? info) => - (lambda (libspec) - (define set-cp - (lambda (tlbody) - (if (libspec-closure? libspec) - `(seq - (set! ,(ref-reg %cp) (literal ,info)) - ,tlbody) - tlbody))) - (set-cp - (set-return-address - (finish-call #f (libspec-closure? libspec) - (in-context Triv `(literal ,(make-info-literal #f 'library-code libspec (constant code-data-disp))))))))] - [else (normal-call)])] - [else (normal-call)])))]))) - (define build-consumer-call - (lambda (tc cnfv rpl) - ; haven't a clue which argument registers are live, so list 'em all. - ; also haven't a clue which frame variables are live. really need a - ; way to list all of them as well, but we count on there being enough - ; other registers (e.g., ac0, xp) to get us from the producer return - ; point to the consumer jump point. - (build-call tc cnfv rpl arg-registers '() #f #f #t))) - (define prepare-for-consumer-call - (lambda (mrvl) - (with-output-language (L13 Effect) - (let ([loc0 (if (null? arg-registers) - (in-context Lvalue (%mref ,%sfp 0)) - (car arg-registers))]) - (%seq - (set! ,loc0 ,%ac0) - (set! ,%ac0 (immediate 1)) - (label ,mrvl)))))) - (define store-cp? - (lambda (t) - (nanopass-case (L12 Triv) t - [(literal ,info) #f] - [else #t]))) - (define build-nontail-call - (lambda (info mdcl t0 t1* tc* nfv** mrvl prepare-for-consumer? build-postlude) - (let-values ([(reg* reg-t* frame-t*) (get-arg-regs t1*)]) - (let ([nfv* (fold-left (lambda (ls x) (cons (make-tmp 'nfv) ls)) '() frame-t*)] - [cnfv* (fold-right (lambda (x ls) (cons (and (store-cp? x) (make-tmp 'cnfv)) ls)) '() tc*)] - [rpl* (map (lambda (tc) (make-local-label 'rpl)) tc*)] - [rpl (make-local-label 'rpl)]) - (let ([newframe-info (make-info-newframe (info-call-src info) (info-call-sexpr info) (reverse (remq #f cnfv*)) nfv* nfv**)]) - (with-output-language (L13 Effect) - (define build-return-point - (lambda (rpl mrvl cnfv* call) - (%seq (tail ,call) (label ,rpl) (return-point ,newframe-info ,rpl ,mrvl (,(remq #f cnfv*) ...))))) - (define set-locs - (lambda (loc* t* ebody) - (fold-right - (lambda (loc t ebody) - (if loc - `(seq (set! ,loc ,(Triv t)) ,ebody) - ebody)) - ebody loc* t*))) - ((lambda (e) (if (info-call-pariah? info) (%seq (pariah) ,e) e)) - (set-locs cnfv* tc* - (set-locs nfv* frame-t* - (set-locs reg* reg-t* - (%seq - (new-frame ,newframe-info ,rpl* ... ,rpl) - ,((lambda (e) - (if prepare-for-consumer? - `(seq ,e ,(prepare-for-consumer-call mrvl)) - e)) - (if (null? tc*) - (build-return-point rpl mrvl cnfv* - (build-call t0 rpl reg* nfv* info mdcl)) - (let ([this-mrvl (make-local-label 'mrvl)]) - `(seq - ,(let ([rpl (car rpl*)]) - (build-return-point rpl this-mrvl cnfv* - (build-call t0 rpl reg* nfv* info mdcl))) - ,(let f ([tc* tc*] [cnfv* cnfv*] [rpl* rpl*] [this-mrvl this-mrvl]) - `(seq - ,(prepare-for-consumer-call this-mrvl) - ,(let ([tc (car tc*)] [tc* (cdr tc*)] [rpl* (cdr rpl*)] [cnfv (car cnfv*)] [cnfv* (cdr cnfv*)]) - (if (null? tc*) - (build-return-point rpl mrvl cnfv* - (build-consumer-call tc cnfv rpl)) - (let ([this-mrvl (make-local-label 'mrvl)]) - `(seq - ,(let ([rpl (car rpl*)]) - (build-return-point rpl this-mrvl cnfv* - (build-consumer-call tc cnfv rpl))) - ,(f tc* cnfv* rpl* this-mrvl))))))))))) - ,(build-postlude newframe-info rpl)))))))))))) - ; NB: combine - (define build-nontail-call-for-tail-call-with-consumers - (lambda (info mdcl t0 t1* tc* nfv** mrvl prepare-for-consumer? build-postlude) - (let-values ([(reg* reg-t* frame-t*) (get-arg-regs t1*)]) - (let ([nfv* (fold-left (lambda (ls x) (cons (make-tmp 'nfv) ls)) '() frame-t*)] - [cnfv* (fold-right (lambda (x ls) (cons (and (store-cp? x) (make-tmp 'cnfv)) ls)) '() tc*)] - [rpl* (map (lambda (tc) (make-local-label 'rpl)) (cdr tc*))] - [rpl (make-local-label 'rpl)]) - (let ([newframe-info (make-info-newframe (info-call-src info) (info-call-sexpr info) (reverse (remq #f cnfv*)) nfv* nfv**)]) - (with-output-language (L13 Effect) - (define build-return-point - (lambda (rpl mrvl cnfv* call) - (%seq (tail ,call) (label ,rpl) (return-point ,newframe-info ,rpl ,mrvl (,(remq #f cnfv*) ...))))) - (define set-locs - (lambda (loc* t* ebody) - (fold-right - (lambda (loc t ebody) - (if loc - `(seq (set! ,loc ,(Triv t)) ,ebody) - ebody)) - ebody loc* t*))) - ((lambda (e) (if (info-call-pariah? info) (%seq (pariah) ,e) e)) - (set-locs cnfv* tc* - (set-locs nfv* frame-t* - (set-locs reg* reg-t* - (%seq - (new-frame ,newframe-info ,rpl* ... ,rpl) - ,((lambda (e) - (if prepare-for-consumer? - `(seq ,e ,(prepare-for-consumer-call mrvl)) - e)) - (if (null? (cdr tc*)) - (build-return-point rpl mrvl cnfv* - (build-call t0 rpl reg* nfv* info mdcl)) - (let ([this-mrvl (make-local-label 'mrvl)]) - `(seq - ,(let ([rpl (car rpl*)]) - (build-return-point rpl this-mrvl cnfv* - (build-call t0 rpl reg* nfv* info mdcl))) - ,(let f ([tc* tc*] [cnfv* cnfv*] [rpl* rpl*] [this-mrvl this-mrvl]) - `(seq - ,(prepare-for-consumer-call this-mrvl) - ,(let ([tc (car tc*)] [tc* (cdr tc*)] [rpl* (cdr rpl*)] [cnfv (car cnfv*)] [cnfv* (cdr cnfv*)]) - (if (null? (cdr tc*)) - (build-return-point rpl mrvl cnfv* - (build-consumer-call tc cnfv rpl)) - (let ([this-mrvl (make-local-label 'mrvl)]) - `(seq - ,(let ([rpl (car rpl*)]) - (build-return-point rpl this-mrvl cnfv* - (build-consumer-call tc cnfv rpl))) - ,(f tc* cnfv* rpl* this-mrvl))))))))))) - ,(build-postlude newframe-info (car (last-pair cnfv*)))))))))))))) - (module (build-tail-call build-mv-return) - (with-output-language (L13 Tail) - (define set-locs - (lambda (loc* t* tlbody) - (fold-right - (lambda (loc t tlbody) - ; omit set! for tail-frame optimization - (if (and (fv? loc) (uvar? t) (eq? (uvar-location t) loc)) - tlbody - `(seq (set! ,loc ,(Triv t)) ,tlbody))) - tlbody loc* t*))) - (define build-shift-args - (lambda (info) - (with-output-language (L13 Effect) - (let ([Ltop (make-local-label 'Ltop)]) - `(seq - (set! ,%ts ,(%inline - ,%ac0 (immediate ,(length arg-registers)))) - (if ,(%inline <= ,%ts (immediate 0)) - (nop) - ,(%seq - (set! ,%xp ,(%inline + ,%sfp ,(%constant ptr-bytes))) - (set! ,%ts ,(%inline sll ,%ts ,(%constant log2-ptr-bytes))) - (set! ,%ts ,(%inline + ,%ts ,%xp)) - (label ,Ltop) - (shift-arg ,%xp 0 ,info) - (set! ,%xp ,(%inline + ,%xp ,(%constant ptr-bytes))) - (if ,(%inline eq? ,%xp ,%ts) - (nop) - (goto ,Ltop))))))))) - (define build-tail-call - (lambda (info mdcl t0 t1* tc*) - (if (null? tc*) - (let-values ([(reg* reg-t* frame-t*) (get-arg-regs t1*)]) - (let ([fv* (let f ([frame-t* frame-t*] [i 0]) - (if (null? frame-t*) - (begin (set! max-fv (fxmax max-fv i)) '()) - (let ([i (fx+ i 1)]) - (cons (get-fv i) (f (cdr frame-t*) i)))))]) - (set-locs fv* frame-t* - (set-locs reg* reg-t* - (build-call t0 #f reg* fv* info mdcl))))) - (let ([tc (car (last-pair tc*))] - [mrvl (make-local-label 'mrvl)]) - (if (store-cp? tc) - (%seq - ,(build-nontail-call-for-tail-call-with-consumers info mdcl t0 t1* tc* '() mrvl #t - (lambda (newframe-info cnfv) - (safe-assert cnfv) - (%seq - (remove-frame ,newframe-info) - (restore-local-saves ,newframe-info) - (set! ,(ref-reg %cp) ,cnfv) - ,(build-shift-args newframe-info)))) - ,(build-consumer-call tc (in-context Triv (ref-reg %cp)) #f)) - (let ([tc* (list-head tc* (fx- (length tc*) 1))]) - `(seq - ,(build-nontail-call info mdcl t0 t1* tc* '() mrvl #t - (lambda (newframe-info rpl) - (%seq - (remove-frame ,newframe-info) - (restore-local-saves ,newframe-info) - ,(build-shift-args newframe-info)))) - ,(build-consumer-call tc #f #f)))))))) - (define build-mv-return - (lambda (t*) - (let-values ([(reg* reg-t* frame-t*) (get-arg-regs t*)]) - (let ([fv* (let f ([frame-t* frame-t*] [i 0]) - (if (null? frame-t*) - (begin (set! max-fv (fxmax max-fv i)) '()) - (let ([i (fx+ i 1)]) - (cons (get-fv i) (f (cdr frame-t*) i)))))]) - (set-locs fv* frame-t* - (set-locs reg* reg-t* - `(seq - (set! ,%ac0 (immediate ,(length t*))) - ,(meta-cond - [(real-register? '%ret) - (%seq - ; must leave RA in %ret for values-error - (set! ,%ret ,(get-fv 0)) - (jump ,(%mref ,%ret ,(constant return-address-mv-return-address-disp)) - (,%ac0 ,%ret ,reg* ... ,fv* ...)))] - [else - (%seq - (set! ,%xp ,(get-fv 0)) - (jump ,(%mref ,%xp ,(constant return-address-mv-return-address-disp)) - (,%ac0 ,reg* ... ,(get-fv 0) ,fv* ...)))]))))))))))) - (define-syntax do-return - (lambda (x) - (syntax-case x () - [(k retval) - (with-implicit (k quasiquote) - #'`(seq - (set! ,%ac0 retval) - (jump ,(get-fv 0) (,%ac0))))]))) - (define Ref - (lambda (x) - (when (uvar? x) (uvar-referenced! x #t)) - x)) - (module (build-foreign-call build-fcallable) - (with-output-language (L13 Effect) - (define build-unfix - (lambda (t) - (in-context Rhs - (%inline sra ,t ,(%constant fixnum-offset))))) - (define build-fix - (lambda (t) - (in-context Rhs - (%inline sll ,t ,(%constant fixnum-offset))))) - (define Scheme->C - ; ASSUMPTIONS: ac0, ac1, and xp are not C argument registers - (lambda (type toC t) - (define ptr->integer - (lambda (width t k) - (if (fx>= (constant fixnum-bits) width) - (k (build-unfix t)) - `(seq - (set! ,%ac0 ,t) - (if ,(%type-check mask-fixnum type-fixnum ,%ac0) - ,(if (fx> width (constant ptr-bits)) - (%seq - (set! ,%ac0 ,(build-unfix %ac0)) - (if ,(%inline < ,%ac0 (immediate 0)) - ,(k %ac0 (in-context Rhs `(immediate -1))) - ,(k %ac0 (in-context Rhs `(immediate 0))))) - (k (build-unfix %ac0))) - (seq - (set! ,%ac0 - (inline - ,(case width - [(32) (intrinsic-info-asmlib dofargint32 #f)] - [(64) (intrinsic-info-asmlib dofargint64 #f)] - [else ($oops who "can't handle width ~s" width)]) - ,%asmlibcall)) - ,(if (fx> width (constant ptr-bits)) - (k %ac0 (in-context Rhs (ref-reg %ac1))) - (k %ac0)))))))) - (define build-u* - (lambda () - (let ([x (make-tmp 't)]) - `(seq - (set! ,x ,t) - (if ,(%inline eq? ,x ,(%constant sfalse)) - ,(toC (in-context Rhs `(immediate 0))) - ,(toC (in-context Rhs (%lea ,x (constant bytevector-data-disp))))))))) - (define build-float - (lambda () - (let ([x (make-tmp 't)]) - `(seq - (set! ,x ,t) - ,(toC x))))) - (nanopass-case (Ltype Type) type - [(fp-scheme-object) (toC t)] - [(fp-fixnum) (toC (build-unfix t))] - [(fp-u8*) (build-u*)] - [(fp-u16*) (build-u*)] - [(fp-u32*) (build-u*)] - [(fp-integer ,bits) (ptr->integer bits t toC)] - [(fp-unsigned ,bits) (ptr->integer bits t toC)] - [(fp-double-float) (build-float)] - [(fp-single-float) (build-float)] - [(fp-ftd ,ftd) - (let ([x (make-tmp 't)]) - `(seq - (set! ,x ,t) - ,(toC (in-context Rhs - (%mref ,x ,(constant record-data-disp))))))] - [(fp-ftd& ,ftd) - (let ([x (make-tmp 't)]) - (%seq - (set! ,x ,t) - (set! ,x ,(%mref ,x ,(constant record-data-disp))) - ,(toC x)))] - [else ($oops who "invalid parameter type specifier ~s" type)]))) - (define Scheme->C-for-result - (lambda (type toC t) - (nanopass-case (Ltype Type) type - [(fp-void) (toC)] - [(fp-ftd& ,ftd) - ;; pointer isn't received as a result, but instead passed - ;; to the function as its first argument (or simulated as such) - (toC)] - [else - (Scheme->C type toC t)]))) - (define C->Scheme - ; ASSUMPTIONS: ac0, ac1, and xp are not C argument registers - (lambda (type fromC lvalue for-return?) - (define integer->ptr - ; ac0 holds low 32-bits, ac1 holds high 32 bits, if needed - (lambda (width lvalue) - (if (fx>= (constant fixnum-bits) width) - `(set! ,lvalue ,(build-fix %ac0)) - (let ([e1 (lambda (big) - (let ([x (make-tmp 't)]) - (%seq - (set! ,x ,(build-fix %ac0)) - (set! ,x ,(build-unfix x)) - (if ,(%inline eq? ,x ,%ac0) - (set! ,lvalue ,(build-fix %ac0)) - ,big))))] - [e2 `(seq - (set! ,%ac0 - (inline - ,(case width - [(32) (intrinsic-info-asmlib dofretint32 #f)] - [(64) (intrinsic-info-asmlib dofretint64 #f)] - [else ($oops who "can't handle width ~s" width)]) - ,%asmlibcall)) - (set! ,lvalue ,%ac0))]) - (if (fx> width (constant ptr-bits)) - (let ([Lbig (make-local-label 'Lbig)] [t-ac1 (make-tmp 't-ac1)]) - (let ([t-ac1 (make-tmp 't-ac1)]) - `(seq - ; TODO: unnecessary if ac1 is not a pseudo register - (set! ,t-ac1 ,(ref-reg %ac1)) - (if (if ,(%inline < ,%ac0 (immediate 0)) - ,(%inline eq? ,t-ac1 (immediate -1)) - ,(%inline eq? ,t-ac1 (immediate 0))) - ,(e1 `(goto ,Lbig)) - (seq (label ,Lbig) ,e2))))) - (e1 e2)))))) - (define unsigned->ptr - ; ac0 holds low 32-bits, ac1 holds high 32 bits, if needed - (lambda (width lvalue) - (if (fx>= (constant fixnum-bits) width) - `(set! ,lvalue ,(build-fix %ac0)) - (let ([e1 (lambda (big) - `(if ,(%inline u< - ,(%constant most-positive-fixnum) - ,%ac0) - ,big - (set! ,lvalue ,(build-fix %ac0))))] - [e2 `(seq - (set! ,%ac0 - (inline - ,(case width - [(32) (intrinsic-info-asmlib dofretuns32 #f)] - [(64) (intrinsic-info-asmlib dofretuns64 #f)] - [else ($oops who "can't handle width ~s" width)]) - ,%asmlibcall)) - (set! ,lvalue ,%ac0))]) - (if (fx> width (constant ptr-bits)) - (let ([Lbig (make-local-label 'Lbig)] [t-ac1 (make-tmp 't-ac1)]) - (let ([t-ac1 (make-tmp 't-ac1)]) - `(seq - ; TODO: unnecessary if ac1 is not a pseudo register - (set! ,t-ac1 ,(ref-reg %ac1)) - (if ,(%inline eq? ,t-ac1 (immediate 0)) - ,(e1 `(goto ,Lbig)) - (seq (label ,Lbig) ,e2))))) - (e1 e2)))))) - (define (alloc-fptr ftd) - (%seq - (set! ,%xp - ,(%constant-alloc type-typed-object (fx* (constant ptr-bytes) 2) #f)) - (set! - ,(%mref ,%xp ,(constant record-type-disp)) - (literal ,(make-info-literal #f 'object ftd 0))) - (set! ,(%mref ,%xp ,(constant record-data-disp)) ,%ac0) - (set! ,lvalue ,%xp))) - (nanopass-case (Ltype Type) type - [(fp-void) `(set! ,lvalue ,(%constant svoid))] - [(fp-scheme-object) (fromC lvalue)] - [(fp-fixnum) - (%seq - ,(fromC %ac0) - (set! ,%ac0 ,(build-fix %ac0)) - (set! ,lvalue ,%ac0))] - [(fp-u8*) - (%seq - ,(fromC %ac0) - (set! ,%xp (inline ,(intrinsic-info-asmlib dofretu8* #f) ,%asmlibcall)) - (set! ,lvalue ,%xp))] - [(fp-u16*) - (%seq - ,(fromC %ac0) - (set! ,%xp (inline ,(intrinsic-info-asmlib dofretu16* #f) ,%asmlibcall)) - (set! ,lvalue ,%xp))] - [(fp-u32*) - (%seq - ,(fromC %ac0) - (set! ,%xp (inline ,(intrinsic-info-asmlib dofretu32* #f) ,%asmlibcall)) - (set! ,lvalue ,%xp))] - [(fp-integer ,bits) - `(seq - ,(if (fx> bits (constant ptr-bits)) - (fromC %ac0 (in-context Lvalue (ref-reg %ac1))) - (fromC %ac0)) - ,(integer->ptr bits lvalue))] - [(fp-unsigned ,bits) - `(seq - ,(if (fx> bits (constant ptr-bits)) - (fromC %ac0 (in-context Lvalue (ref-reg %ac1))) - (fromC %ac0)) - ,(unsigned->ptr bits lvalue))] - [(fp-double-float) - (%seq - (set! ,%xp ,(%constant-alloc type-flonum (constant size-flonum) for-return?)) - ,(fromC %xp) - (set! ,lvalue ,%xp))] - [(fp-single-float) - (%seq - (set! ,%xp ,(%constant-alloc type-flonum (constant size-flonum) for-return?)) - ,(fromC %xp) - (set! ,lvalue ,%xp))] - [(fp-ftd ,ftd) - (%seq - ,(fromC %ac0) ; C integer return might be wiped out by alloc - ,(alloc-fptr ftd))] - [(fp-ftd& ,ftd) - (%seq - ,(fromC %ac0) - ,(alloc-fptr ftd))] - [else ($oops who "invalid result type specifier ~s" type)])))) - (define (pick-Scall result-type) - (nanopass-case (Ltype Type) result-type - [(fp-void) (lookup-c-entry Scall-any-results)] - [else (lookup-c-entry Scall-one-result)])) - (define build-foreign-call - (with-output-language (L13 Effect) - (lambda (info t0 t1* maybe-lvalue new-frame?) - (let ([arg-type* (info-foreign-arg-type* info)] - [result-type (info-foreign-result-type info)]) - (let ([e (let-values ([(allocate c-args ccall c-res deallocate) (asm-foreign-call info)]) - ; NB. allocate must save tc if not callee-save, and ccall - ; (not deallocate) must restore tc if not callee-save - (%seq - ,(allocate) - ; cp must hold our closure or our code object. we choose code object - (set! ,(%tc-ref cp) (label-ref ,le-label 0)) - ,(with-saved-scheme-state - (in) ; save just the required registers, e.g., %sfp - (out %ac0 %ac1 %cp %xp %yp %ts %td scheme-args extra-regs) - (fold-left (lambda (e t1 arg-type c-arg) `(seq ,(Scheme->C arg-type c-arg t1) ,e)) - (ccall t0) t1* arg-type* c-args)) - ,(let ([e (deallocate)]) - (if maybe-lvalue - (nanopass-case (Ltype Type) result-type - [(fp-ftd& ,ftd) - ;; Don't actually return a value, because the result - ;; was instead installed in the first argument. - `(seq (set! ,maybe-lvalue ,(%constant svoid)) ,e)] - [else - `(seq ,(C->Scheme result-type c-res maybe-lvalue #t) ,e)]) - e))))]) - (if new-frame? - (sorry! who "can't handle nontail foreign calls") - e)))))) - (define build-fcallable - (with-output-language (L13 Tail) - (lambda (info self-label) - (define set-locs - (lambda (loc* t* ebody) - (fold-right - (lambda (loc t ebody) - (if loc (in-context Effect `(seq (set! ,loc ,t) ,ebody)) ebody)) - ebody loc* t*))) - (let ([arg-type* (info-foreign-arg-type* info)] - [result-type (info-foreign-result-type info)]) - (let ([x* (map (lambda (x) (make-tmp 't)) arg-type*)]) - (let-values ([(reg* reg-x* frame-x*) (get-arg-regs x*)]) - (let ([fv* (let f ([frame-x* frame-x*] [i 0]) - (if (null? frame-x*) - (begin (set! max-fv (fxmax max-fv i)) '()) - (let ([i (fx+ i 1)]) - (cons (get-fv i) (f (cdr frame-x*) i)))))] - [cp-save (meta-cond - [(real-register? '%cp) (make-tmp 'cp)] - [else #f])]) - ; add 2 for the old RA and cchain - (set! max-fv (fx+ max-fv 2)) - (let-values ([(c-init c-args c-result c-return) (asm-foreign-callable info)]) - ; c-init saves C callee-save registers and restores tc - ; each of c-args sets a variable to one of the C arguments - ; c-result converts C results to Scheme values - ; c-return restores callee-save registers and returns to C - (%seq - ,(c-init) - ,(restore-scheme-state - (in %cp) ; to save and then restore just before S_call_help - (out %ac0 %ac1 %xp %yp %ts %td scheme-args extra-regs)) - ; need overflow check since we're effectively retroactively turning - ; what was a foreign call into a Scheme non-tail call - (fcallable-overflow-check) - ; leave room for the RA & c-chain - (set! ,%sfp ,(%inline + ,%sfp (immediate ,(fx* (constant ptr-bytes) 2)))) - ; stash %cp and restore later to make sure it's intact by the time - ; that we get to S_call_help - ,(meta-cond - [(real-register? '%cp) `(set! ,cp-save ,%cp)] - [else `(nop)]) - ; convert arguments - ,(fold-left (lambda (e x arg-type c-arg) `(seq ,(C->Scheme arg-type c-arg x #f) ,e)) - (set-locs fv* frame-x* - (set-locs (map (lambda (reg) (in-context Lvalue (%mref ,%tc ,(reg-tc-disp reg)))) reg*) reg-x* - `(set! ,%ac0 (immediate ,(length arg-type*))))) - x* arg-type* c-args) - ; cookie (0) will be replaced by the procedure, so this - ; needs to be a quote, not an immediate - (set! ,(ref-reg %ac1) (literal ,(make-info-literal #f 'object 0 0))) - (set! ,(ref-reg %ts) (label-ref ,self-label 0)) ; for locking - ,(meta-cond - [(real-register? '%cp) `(set! ,%cp ,cp-save)] - [else `(nop)]) - ,(save-scheme-state - (in %ac0 %ac1 %ts %cp) - (out %xp %yp %td scheme-args extra-regs)) - ; Scall-{any,one}-results calls the Scheme implementation of the - ; callable, locking this callable wrapper (as communicated in %ts) - ; until just before returning - (inline ,(make-info-c-simple-call fv* #f (pick-Scall result-type)) ,%c-simple-call) - ,(restore-scheme-state - (in %ac0) - (out %ac1 %cp %xp %yp %ts %td scheme-args extra-regs)) - ; assuming no use of %cp from here on that could get saved into `(%tc-ref cp)`: - ,(Scheme->C-for-result result-type c-result %ac0) - ,(c-return))))))))))) - (define handle-do-rest - (lambda (fixed-args offset save-asm-ra?) - (with-output-language (L13 Effect) - (let-values ([(arg reg* fv-start) - ; not using interface - (let f ([arg-number fixed-args] [rl arg-registers]) - (cond - [(null? rl) - (let ([fv-offset (fx+ (fx* arg-number (constant ptr-bytes)) offset)]) - (values - (in-context Lvalue (%mref ,%sfp ,fv-offset)) - '() - (fx+ fv-offset (constant ptr-bytes))))] - [(= arg-number 0) (values (car rl) (cdr rl) offset)] - [else (f (fx- arg-number 1) (cdr rl))]))]) - ; TODO: try to avoid using ts by starting at the end and coming back until ac0 - ; reaches k(sfp), so we can use ts and/or td as an argument register. (need one - ; available for the memory-memory moves) - (let* ([Lstart (make-local-label 'Lstart)] - [Ldone (make-local-label 'Ldone)] - [bump-xp-and-store-cdr - `(seq - (set! ,%xp ,(%inline + ,%xp ,(%constant size-pair))) - (if ,(%inline eq? ,%xp ,%ac0) - (goto ,Ldone) - (set! ,(%mref ,%xp - ,(fx- (constant pair-cdr-disp) (constant size-pair))) - ,%xp)))]) - (%seq - ; set ac0 to number of rest elements - (set! ,%ac0 ,(%inline - ,%ac0 (immediate ,fixed-args))) - (if ,(%inline eq? ,%ac0 (immediate 0)) - (set! ,arg ,(%constant snil)) - ,(%seq - ; adjust & scale ac0 to size of rest list in bytes - (set! ,%ac0 ,(%inline sll ,%ac0 ,(%constant pair-shift))) - ; allocate the space - (set! ,%xp (alloc ,(make-info-alloc (constant type-pair) #f save-asm-ra?) ,%ac0)) - ; point ac0 past end of list - (set! ,%ac0 ,(%inline + ,%ac0 ,%xp)) - ; store the first element - (set! ,(%mref ,%xp ,(constant pair-car-disp)) ,arg) - ; store the list in the first-element's old home - (set! ,arg ,%xp) - ; store remaining reg elements, then loop through frame elements - ,(let f ([reg* reg*]) - (%seq - ,bump-xp-and-store-cdr - ,(if (null? reg*) - (%seq - ; set ts to start of the fram arguments - (set! ,%ts ,(%inline + ,%sfp (immediate ,fv-start))) - (label ,Lstart) - ; copy next element from stack to list - (set! ,(%mref ,%xp ,(constant pair-car-disp)) - ,(%mref ,%ts 0)) - ,bump-xp-and-store-cdr - (set! ,%ts ,(%inline + ,%ts ,(%constant ptr-bytes))) - (goto ,Lstart)) - (%seq - (set! ,(%mref ,%xp ,(constant pair-car-disp)) - ,(car reg*)) - ,(f (cdr reg*)))))) - (label ,Ldone) - ; store nil in the last cdr - (set! ,(%mref ,%xp - ,(fx- (constant pair-cdr-disp) (constant size-pair))) - ,(%constant snil)))))))))) - (define make-named-info-lambda - (lambda (name interface) - (make-info-lambda #f #f #f interface name))) - (define make-do-rest - (lambda (fixed-args offset) - (with-output-language (L13 CaseLambdaExpr) - `(lambda ,(make-named-info-lambda 'dorest '()) 0 () - ,(asm-enter - (%seq - (check-live ,(intrinsic-entry-live* (vector-ref dorest-intrinsics fixed-args)) ...) - ,(handle-do-rest fixed-args offset #t) - (asm-return ,(intrinsic-return-live* (vector-ref dorest-intrinsics fixed-args)) ...))))))) - (define frame-args-offset (constant ptr-bytes)) - ; TODO: commonize these procedures (as macros) outside of - ; np-expand-hand-coded/np-impose-calling-conventions? - (define make-arg-opnd - (lambda (n) - (let ([regnum (length arg-registers)]) - (if (fx<= n regnum) - (list-ref arg-registers (fx- n 1)) - (with-output-language (L13 Lvalue) - (%mref ,%sfp - ,(fx* (constant ptr-bytes) (fx- n regnum)))))))) - (define do-call - (lambda (interface) - (with-output-language (L13 Tail) - (%seq - (set! ,%ac0 (immediate ,interface)) - ,(meta-cond - [(real-register? '%cp) - `(jump ,(%mref ,%cp ,(constant closure-code-disp)) - (,%ac0 ,%cp ,(reg-cons* %ret arg-registers) ...))] - [else - (%seq - (set! ,%td ,(ref-reg %cp)) - (jump ,(%mref ,%td ,(constant closure-code-disp)) - (,%ac0 ,(reg-cons* %ret arg-registers) ...)))]))))) - (with-output-language (L13 Effect) - (meta-cond - [(real-register? '%cp) - (define xp/cp %cp) - (define load-xp/cp `(nop))] - [else - (define xp/cp %xp) - (define load-xp/cp `(set! ,%xp ,(ref-reg %cp)))])) - (define-syntax %set-esp - (lambda (x) - (syntax-case x () - [(k e) - (with-implicit (k quasiquote %mref ref-reg) - (if (real-register? '%esp) - ; write-through to tc so %esp need not be saved when going to C - #'`(seq - (set! ,(ref-reg %esp) e) - (set! ,(%mref ,%tc ,(tc-disp %esp)) ,(ref-reg %esp))) - #'`(set! ,(ref-reg %esp) e)))]))) - (define nuate-help - (lambda () - ; Since cp is not always a real register, and the mref form requires us to put a var of some sort - ; in for its base, we need to move cp to to a real register. Unfortunately, there do not seem to be - ; enough real registers available, since ac0 is in use through out, xp and td serve as temopraries, and - ; we'd like to keep ts free to serve for memory to memory moves. - ; Since this is the case, we need a temporary to put cp into when we are working with it and - ; xp is the natural choice (or td or ts if we switched amongst their roles) - (with-output-language (L13 Tail) - ; cont. in cp and xp/cp, arg count in ac0, stack base in sfp, old frame base in yp - (let ([Lmultishot (make-local-label 'Lmultishot)] - [Lcopy-values (make-local-label 'Lcopy-values)] - [Lcopyup-values (make-local-label 'Lcopyup-values)] - [Lcopydown-values (make-local-label 'Lcopydown-values)] - [Lcopy-stack (make-local-label 'Lcopy-stack)] - [Lreturn (make-local-label 'Lreturn)]) - (%seq - (set! ,%td ,(%mref ,xp/cp ,(constant continuation-stack-clength-disp))) - (if ,(%inline eq? - ,(%mref ,xp/cp ,(constant continuation-stack-length-disp)) - ,%td) - ; length and clength match, so it is either mutlishot or shot1shot - (if ,(%inline eq? ,%td ,(%constant scaled-shot-1-shot-flag)) - ; shot 1-shot - ,(%seq - (set! ,(ref-reg %cp) (literal ,(make-info-literal #t 'object '$oops - (constant symbol-value-disp)))) - (set! ,(make-arg-opnd 1) ,(%constant sfalse)) - (set! ,(make-arg-opnd 2) - (literal ,(make-info-literal #f 'object - "attempt to invoke shot one-shot continuation" 0))) - ,(do-call 2)) - ; multishot - ,(%seq - (label ,Lmultishot) - ; split if clength > underflow-limit - (if (if ,(%inline > ,%td ,(%constant underflow-limit)) - (true) - ; resize unless stack-base + clength + size(values) <= esp - ; this is conservative to save a few instructions: really need - ; stack-base + clength <= esp and clength + size(values) < stack-size; - ; also, size may include argument register values - ; Carefully using ts again - ,(%seq - (set! ,%ts ,(%inline sll ,%ac0 ,(%constant log2-ptr-bytes))) - (set! ,%ts ,(%inline + ,%ts ,%sfp)) - (set! ,%ts ,(%inline + ,%ts ,%td)) - ,(%inline < ,(ref-reg %esp) ,%ts))) - ,(%seq - ,(with-saved-scheme-state - (in %ac0 %cp %xp %yp scheme-args) - (out %ac1 %ts %td extra-regs) - `(inline ,(make-info-c-simple-call #f (lookup-c-entry split-and-resize)) ,%c-simple-call)) - (set! ,%td ,(%mref ,xp/cp ,(constant continuation-stack-clength-disp)))) - (nop)) - ; (new) stack base in sfp, clength in ac1, old frame base in yp - ; set up return address and stack link - (set! ,(%tc-ref stack-link) ,(%mref ,xp/cp ,(constant continuation-link-disp))) - ; set %td to end of the destination area / base of stack values dest - (set! ,%td ,(%inline + ,%td ,%sfp)) - ; don't shift if no stack values - (if ,(%inline <= ,%ac0 (immediate ,(length arg-registers))) - (nop) - ,(%seq - ; set xp to old frame base - (set! ,%xp ,(ref-reg %yp)) - ; set sfp to stack values bytes - (set! ,%sfp ,(%inline - ,%ac0 (immediate ,(length arg-registers)))) - (set! ,%sfp ,(%inline sll ,%sfp ,(%constant log2-ptr-bytes))) - ; shift stack return values up or down - (if ,(%inline < ,%xp ,%td) - ,(%seq - (label ,Lcopyup-values) - (set! ,%sfp ,(%inline - ,%sfp ,(%constant ptr-bytes))) - (set! ,(%mref ,%td ,%sfp ,frame-args-offset) ,(%mref ,%xp ,%sfp ,frame-args-offset)) - (if ,(%inline eq? ,%sfp (immediate 0)) - ,(%seq - ; restore for invariants below; td is already okay - ,load-xp/cp - (set! ,%sfp ,(%tc-ref scheme-stack))) - (goto ,Lcopyup-values))) - ,(%seq - (set! ,%sfp ,(%inline + ,%sfp ,%td)) - (label ,Lcopydown-values) - (set! ,(%mref ,%td ,frame-args-offset) ,(%mref ,%xp ,frame-args-offset)) - (set! ,%td ,(%inline + ,%td ,(%constant ptr-bytes))) - (set! ,%xp ,(%inline + ,%xp ,(%constant ptr-bytes))) - (if ,(%inline eq? ,%td ,%sfp) - ,(%seq - ; restore for invariants below - ,load-xp/cp - (set! ,%sfp ,(%tc-ref scheme-stack)) - (set! ,%td ,(%inline + ,%sfp ,(%mref ,xp/cp ,(constant continuation-stack-clength-disp))))) - (goto ,Lcopydown-values)))))) - ; invariants: xp/cp = continuation, sfp = stack base, td = end of destination area - ; set %xp to saved stack base - (set! ,%xp ,(%mref ,xp/cp ,(constant continuation-stack-disp))) - (label ,Lcopy-stack) - (if ,(%inline eq? ,%sfp ,%td) - (nop) - ,(%seq - (set! ,(%mref ,%sfp 0) ,(%mref ,%xp 0)) - (set! ,%sfp ,(%inline + ,%sfp ,(%constant ptr-bytes))) - (set! ,%xp ,(%inline + ,%xp ,(%constant ptr-bytes))) - (goto ,Lcopy-stack))) - ,load-xp/cp - (goto ,Lreturn))) - ; 1 shot - ,(%seq - ; treat as multishot if clength + size(values) > length - ; conservative: some values may be in argument registers - ; AWK - very carefully using ts here as we are out of other registers - (set! ,%ts ,(%inline sll ,%ac0 ,(%constant log2-ptr-bytes))) - (set! ,%ts ,(%inline + ,%ts ,%td)) - (if ,(%inline < ,(%mref ,xp/cp ,(constant continuation-stack-length-disp)) ,%ts) - (goto ,Lmultishot) - ,(%seq - ; set up stack link - (set! ,(%tc-ref stack-link) ,(%mref ,xp/cp ,(constant continuation-link-disp))) - ; place old stack in ac1 for now to cache him later (after we've removed - ; the values, so that we have a place to store the length and link) - (set! ,(ref-reg %ac1) ,%sfp) - ; grab saved stack - (set! ,%sfp ,(%mref ,xp/cp ,(constant continuation-stack-disp))) - ; set up tc's scheme-stack variable - (set! ,(%tc-ref scheme-stack) ,%sfp) - ; set up esp as stack-base + length - slop - (set! ,%ts ,(%inline - ,%sfp ,(%constant stack-slop))) - ,(%set-esp ,(%inline + ,%ts ,(%mref ,xp/cp ,(constant continuation-stack-length-disp)))) - ; set up frame pointer to stack-base + current length - (set! ,%sfp ,(%inline + ,%sfp ,%td)) - ; bypass copy loop if no stack values - (if ,(%inline <= ,%ac0 (immediate ,(length arg-registers))) - (nop) - ,(%seq - ; set td to stack values bytes - (set! ,%td ,(%inline - ,%ac0 (immediate ,(length arg-registers)))) - (set! ,%td ,(%inline sll ,%td ,(%constant log2-ptr-bytes))) - ; set xp, td to top of stack values src, dest - (set! ,%xp ,(ref-reg %yp)) - ; move stack return values to top of saved stack segment - (label ,Lcopy-values) - (set! ,%td ,(%inline - ,%td ,(%constant ptr-bytes))) - (set! ,(%mref ,%sfp ,%td ,frame-args-offset) ,(%mref ,%xp ,%td ,frame-args-offset)) - (if ,(%inline eq? ,%td (immediate 0)) - ,load-xp/cp ; need to load cp-reg, since xp is wiped out - (goto ,Lcopy-values)))) - ; place old stack in stack cache - (set! ,%td ,(ref-reg %ac1)) - (set! ,(%mref ,%td 0) ,(%tc-ref scheme-stack-size)) - (set! ,(%mref ,%td ,(constant ptr-bytes)) ,(%tc-ref stack-cache)) - (set! ,(%tc-ref stack-cache) ,%td) - ; set up tc's stack-size variable - (set! ,(%tc-ref scheme-stack-size) ,(%mref ,xp/cp ,(constant continuation-stack-length-disp))) - ; mark continuation shot - (set! ,(%mref ,xp/cp ,(constant continuation-stack-length-disp)) ,(%constant scaled-shot-1-shot-flag)) - (set! ,(%mref ,xp/cp ,(constant continuation-stack-clength-disp)) ,(%constant scaled-shot-1-shot-flag)) - ; return with 1 or multiple values - (label ,Lreturn) - (if ,(%inline eq? ,%ac0 (immediate 1)) - ,(%seq - (set! ,%ac0 ,(make-arg-opnd 1)) - (jump ,(%mref ,xp/cp ,(constant continuation-return-address-disp)) (,%ac0))) - ,(meta-cond - [(real-register? '%ret) - (%seq - (set! ,%ret ,(%mref ,xp/cp ,(constant continuation-return-address-disp))) - (jump ,(%mref ,%ret ,(constant return-address-mv-return-address-disp)) - (,%ac0 ,%ret ,arg-registers ...)))] - [else - (let ([fv0 (get-fv 0)]) - (%seq - (set! ,%xp ,(%mref ,xp/cp ,(constant continuation-return-address-disp))) - (set! ,fv0 ,%xp) - (jump ,(%mref ,%xp ,(constant return-address-mv-return-address-disp)) - (,%ac0 ,arg-registers ... ,fv0))))])))))))))))) - (Program : Program (ir) -> Program () - [(labels ([,l* ,le*] ...) ,l) - `(labels ([,l* ,(map CaseLambdaExpr le* l*)] ...) ,l)]) - (CaseLambdaExpr : CaseLambdaExpr (ir l) -> CaseLambdaExpr () - [(lambda ,info (,local0* ...) ,tlbody) - (fluid-let ([dcl* (info-lambda-dcl* info)] [max-fv 0] [local* local0*] [le-label l]) - (let ([tlbody (Tail tlbody)]) - (let ([local* (filter uvar-referenced? local*)]) - (safe-assert (nodups local*)) - (for-each (lambda (local) (uvar-location-set! local #f)) local*) - `(lambda ,info ,max-fv (,local* ...) ,tlbody))))] - [(fcallable ,info ,l) - (let ([lambda-info (make-info-lambda #f #f #f (list (length (info-foreign-arg-type* info))) - (info-foreign-name info) (constant code-flag-template))]) - (fluid-let ([max-fv 0] [local* '()]) - (let ([tlbody (build-fcallable info l)]) - `(lambda ,lambda-info ,max-fv (,local* ...) ,tlbody))))] - [(hand-coded ,sym) - (case sym - [(dorest0) (make-do-rest 0 frame-args-offset)] - [(dorest1) (make-do-rest 1 frame-args-offset)] - [(dorest2) (make-do-rest 2 frame-args-offset)] - [(dorest3) (make-do-rest 3 frame-args-offset)] - [(dorest4) (make-do-rest 4 frame-args-offset)] - [(dorest5) (make-do-rest 5 frame-args-offset)] - [(callcc) - (let ([Ltop (make-local-label 'Ltop)]) - `(lambda ,(make-named-info-lambda 'callcc '(1)) 0 () - ,(%seq - (set! ,(ref-reg %cp) ,(make-arg-opnd 1)) - (set! ,%td ,(%tc-ref stack-link)) - (set! ,%xp ,%td) - (label ,Ltop) - (set! ,%ac0 ,(%mref ,%xp ,(constant continuation-stack-clength-disp))) - (if ,(%inline eq? - ,(%mref ,%xp ,(constant continuation-stack-length-disp)) - ,%ac0) - ,(%seq - (set! ,%ac0 - (literal ,(make-info-literal #f 'library-code - (lookup-libspec dounderflow) - (fx+ (constant code-data-disp) (constant size-rp-header))))) - (if (if ,(%inline eq? ,%ref-ret ,%ac0) - ,(%inline eq? - ,(%mref ,%td ,(constant continuation-winders-disp)) - ,(%tc-ref winders)) - (false)) - ,(%seq - (set! ,(make-arg-opnd 1) ,%td) - ,(do-call 1)) - ,(%seq - (set! ,%xp ,(%constant-alloc type-closure (constant size-continuation))) - ; TODO: remove next line once get-room preserves %td - (set! ,%td ,(%tc-ref stack-link)) - (set! ,(%mref ,%xp ,(constant continuation-code-disp)) - (literal ,(make-info-literal #f 'library (lookup-libspec nuate) (constant code-data-disp)))) - (set! ,(%mref ,%xp ,(constant continuation-return-address-disp)) ,%ref-ret) - (set! ,(%mref ,%xp ,(constant continuation-winders-disp)) ,(%tc-ref winders)) - (set! ,%ref-ret ,%ac0) - (set! ,(%mref ,%xp ,(constant continuation-link-disp)) ,%td) - (set! ,(%tc-ref stack-link) ,%xp) - (set! ,%ac0 ,(%tc-ref scheme-stack)) - (set! ,(%tc-ref scheme-stack) ,%sfp) - (set! ,(%mref ,%xp ,(constant continuation-stack-disp)) ,%ac0) - (set! ,%ac0 ,(%inline - ,%sfp ,%ac0)) - (set! ,(%mref ,%xp ,(constant continuation-stack-length-disp)) ,%ac0) - (set! ,(%mref ,%xp ,(constant continuation-stack-clength-disp)) ,%ac0) - (set! ,(%tc-ref scheme-stack-size) ,(%inline - ,(%tc-ref scheme-stack-size) ,%ac0)) - (set! ,(make-arg-opnd 1) ,%xp) - ,(do-call 1)))) - ,(%seq - (set! ,(%mref ,%xp ,(constant continuation-stack-length-disp)) ,%ac0) - (set! ,%xp ,(%mref ,%xp ,(constant continuation-link-disp))) - (goto ,Ltop))))))] - [(call1cc) - `(lambda ,(make-named-info-lambda 'call1cc '(1)) 0 () - ,(%seq - (set! ,(ref-reg %cp) ,(make-arg-opnd 1)) - (set! ,%td ,(%tc-ref stack-link)) - (set! ,%ac0 - (literal ,(make-info-literal #f 'library-code - (lookup-libspec dounderflow) - (fx+ (constant code-data-disp) (constant size-rp-header))))) - (if (if ,(%inline eq? ,%ref-ret ,%ac0) - ,(%inline eq? - ,(%mref ,%td ,(constant continuation-winders-disp)) - ,(%tc-ref winders)) - (false)) - ,(%seq - (set! ,(make-arg-opnd 1) ,%td) - ,(do-call 1)) - ,(%seq - (set! ,%xp ,(%constant-alloc type-closure (constant size-continuation))) - ; TODO: remove next line once get-room preserves %td - (set! ,%td ,(%tc-ref stack-link)) - (set! ,(%mref ,%xp ,(constant continuation-code-disp)) - (literal ,(make-info-literal #f 'library (lookup-libspec nuate) (constant code-data-disp)))) - (set! ,(%mref ,%xp ,(constant continuation-return-address-disp)) ,%ref-ret) - (set! ,(%mref ,%xp ,(constant continuation-winders-disp)) - ,(%tc-ref winders)) - ,(meta-cond - [(real-register? '%ret) `(set! ,%ret ,%ac0)] - [else `(nop)]) - (set! ,(%mref ,%xp ,(constant continuation-link-disp)) ,%td) - (set! ,(%tc-ref stack-link) ,%xp) - (set! ,%ac0 ,(%tc-ref scheme-stack)) - (set! ,(%mref ,%xp ,(constant continuation-stack-disp)) ,%ac0) - (set! ,(%mref ,%xp ,(constant continuation-stack-clength-disp)) - ,(%inline - ,%sfp ,%ac0)) - ; we need to get ourselves a new stack. we carve it out of the old - ; one if the old one is large enough. if not, we look for one in - ; the cache. if the cache is empty, we allocate a new stack. - (set! ,%sfp ,(%inline + ,%sfp (immediate ,(fx* (constant one-shot-headroom) 2)))) - (if ,(%inline <= ,%sfp ,(ref-reg %esp)) - ,(%seq - (set! ,%sfp ,(%inline - ,%sfp ,(%constant one-shot-headroom))) - (set! ,%ac0 ,(%inline - ,%sfp ,%ac0)) - (set! ,(%mref ,%xp ,(constant continuation-stack-length-disp)) ,%ac0) - (set! ,(%tc-ref scheme-stack) ,%sfp) - (set! ,(%tc-ref scheme-stack-size) ,(%inline - ,(%tc-ref scheme-stack-size) ,%ac0)) - (set! ,(make-arg-opnd 1) ,%xp) - ,(meta-cond - [(real-register? '%ret) `(nop)] - [else `(set! ,%ref-ret - (literal ,(make-info-literal #f 'library-code - (lookup-libspec dounderflow) - (fx+ (constant code-data-disp) (constant size-rp-header)))))]) - ,(do-call 1)) - ,(%seq - ; set continuation length to entire stack size - (set! ,(%mref ,%xp ,(constant continuation-stack-length-disp)) - ,(%tc-ref scheme-stack-size)) - (set! ,%sfp ,(%tc-ref stack-cache)) - (if ,(%inline eq? ,%sfp ,(%constant snil)) - ,(%seq - (set! ,%ac0 ,%xp) - (set! ,%xp ,(%constant-alloc typemod (constant default-stack-size))) - (set! ,%sfp ,%xp) - (set! ,(%tc-ref scheme-stack) ,%sfp) - (set! ,(%tc-ref scheme-stack-size) ,(%constant default-stack-size)) - ,(%set-esp ,(%inline + ,%sfp - (immediate ,(fx- (constant default-stack-size) (constant stack-slop))))) - (set! ,(make-arg-opnd 1) ,%ac0) - ,(meta-cond - [(real-register? '%ret) `(nop)] - [else `(set! ,%ref-ret - (literal ,(make-info-literal #f 'library-code - (lookup-libspec dounderflow) - (fx+ (constant code-data-disp) (constant size-rp-header)))))]) - ,(do-call 1)) - ,(%seq - (set! ,(%tc-ref stack-cache) ,(%mref ,%sfp ,(constant ptr-bytes))) ; next stack-segment - (set! ,%ac0 ,(%mref ,%sfp 0)) ; stack-segment size - (set! ,(%tc-ref scheme-stack) ,%sfp) - (set! ,(%tc-ref scheme-stack-size) ,%ac0) - ,(%set-esp ,(%lea ,%ac0 ,%sfp (fx- (constant stack-slop)))) - (set! ,(make-arg-opnd 1) ,%xp) - ,(meta-cond - [(real-register? '%ret) `(nop)] - [else `(set! ,%ref-ret - (literal ,(make-info-literal #f 'library-code - (lookup-libspec dounderflow) - (fx+ (constant code-data-disp) (constant size-rp-header)))))]) - ,(do-call 1)))))))))] - [(dounderflow) - (let ([Lret (make-local-label 'Lret)] [Lmvreturn (make-local-label 'Lmvreturn)]) - `(lambda ,(make-named-info-lambda 'winder-dummy '()) 0 () - ,(%seq - ; (asm align) - (label ,Lret) - (rp-header ,Lmvreturn 0 0) - (set! ,(make-arg-opnd 1) ,%ac0) - (set! ,%ac0 (immediate 1)) - (label ,Lmvreturn) - (set! ,xp/cp ,(%tc-ref stack-link)) - ,(meta-cond - [(real-register? '%cp) `(nop)] - [else `(set! ,(ref-reg %cp) ,xp/cp)]) - (set! ,(ref-reg %yp) ,%sfp) - ,(nuate-help))))] - [(nuate) - (let ([info (make-named-info-lambda 'continuation '(-1))]) - (info-lambda-flags-set! info (fxlogor (constant code-flag-continuation) (constant code-flag-system))) - `(lambda ,info 0 () - ,(%seq - ,load-xp/cp - (if ,(%inline eq? ,(%tc-ref winders) - ,(%mref ,xp/cp ,(constant continuation-winders-disp))) - ,(%seq - (set! ,(ref-reg %yp) ,%sfp) - (set! ,%sfp ,(%tc-ref scheme-stack)) - ,(nuate-help)) - ,(%seq - (if ,(%inline eq? ,%ac0 (immediate 0)) - (set! ,%xp ,(%constant snil)) - ,(%seq - ,(handle-do-rest 0 frame-args-offset #f) - (set! ,%xp ,(make-arg-opnd 1)))) - (set! ,%sfp ,(%tc-ref scheme-stack)) - (set! ,(make-arg-opnd 2) ,%xp) - (set! ,(make-arg-opnd 1) ,(ref-reg %cp)) - (jump (literal ,(make-info-literal #f 'library-code - (lookup-libspec dounderflow*) - (constant code-data-disp))) - (,(reg-cons* %cp arg-registers) ...)))))))] - [else `(hand-coded ,sym)])]) - (Lvalue : Lvalue (ir) -> Lvalue () - [,x (Ref x)] - [(mref ,x1 ,x2 ,imm) (%mref ,(Ref x1) ,(Ref x2) ,imm)]) - (Triv : Triv (ir) -> Triv () - [,x (Ref x)] ; TODO: cannot call ref in cata, as we don't allow top-level cata - [(mref ,x1 ,x2 ,imm) (%mref ,(Ref x1) ,(Ref x2) ,imm)]) - (Rhs : Rhs (ir) -> Rhs () - [(mvcall ,info ,mdcl ,t0? ,t1* ... (,t* ...)) - ($oops who "Effect is responsible for handling mvcalls")]) - (Effect : Effect (ir) -> Effect () - [(do-rest ,fixed-args) - (if (fx<= fixed-args dorest-intrinsic-max) - `(inline ,(intrinsic-info-asmlib (vector-ref dorest-intrinsics fixed-args) #f) ,%asmlibcall!) - (handle-do-rest fixed-args frame-args-offset #f))] - ; TODO: get internal error when , is missing from ,l - [(mventry-point (,x* ...) ,l) - (%seq - (remove-frame ,newframe-info-for-mventry-point) - ,(let f ([x* x*]) - (if (null? x*) - (%seq - (restore-local-saves ,newframe-info-for-mventry-point) - (goto ,l)) - (let ([x (car x*)]) - (if (uvar-referenced? x) - `(seq (set! ,x ,(uvar-location x)) ,(f (cdr x*))) - (f (cdr x*)))))))] - [(mverror-point) - `(set! ,%ref-ret (label-ref ,label-for-mverror-point ,(constant size-rp-header)))] - [(mvcall ,info ,mdcl ,t0? ,t1* ... (,t* ...)) - (let ([mrvl (make-local-label 'mrvl)]) - (build-nontail-call info mdcl t0? t1* t* '() mrvl #f - (lambda (newframe-info rpl) - (%seq (label ,mrvl) (remove-frame ,newframe-info) (restore-local-saves ,newframe-info)))))] - [(mvset ,info (,mdcl ,t0? ,t1* ...) (,t* ...) ((,x** ...) ...) ,ebody) - (let* ([frame-x** (map (lambda (x*) (set-formal-registers! x*)) x**)] - [nfv** (map (lambda (x*) (map (lambda (x) - (let ([nfv (make-tmp 'mvset-nfv)]) - (uvar-location-set! x nfv) - nfv)) - x*)) - frame-x**)]) - (let ([mrvl (make-local-label 'mrvl)]) - (build-nontail-call info mdcl t0? t1* t* nfv** mrvl #t - (lambda (newframe-info rpl) - (fluid-let ([newframe-info-for-mventry-point newframe-info] - [label-for-mverror-point rpl]) - (Effect ebody))))))] - [(set! ,[lvalue] (mvcall ,info ,mdcl ,t0? ,t1* ... (,t* ...))) - (build-nontail-call info mdcl t0? t1* t* '() #f #f - (lambda (newframe-info rpl) - (let ([retval (make-tmp 'retval)]) - (%seq - (remove-frame ,newframe-info) - (set! ,retval ,%ac0) - (restore-local-saves ,newframe-info) - (set! ,lvalue ,retval)))))] - [(foreign-call ,info ,[t0] ,[t1*] ...) - (build-foreign-call info t0 t1* #f #t)] - [(set! ,[lvalue] (foreign-call ,info ,[t0] ,[t1*] ...)) - (build-foreign-call info t0 t1* lvalue #t)]) - (Tail : Tail (ir) -> Tail () - [(entry-point (,x* ...) ,dcl ,mcp ,tlbody) - (unless (andmap (lambda (x) (eq? (uvar-type x) 'ptr)) x*) - ($oops who "can't handle anything but plain vanilla types yet")) - ; clear and recompute referenced flags on entry-point formals in case tail-frame - ; optimization eliminates all of the references - (when mcp (uvar-referenced! mcp #f)) - (for-each (lambda (x) (uvar-referenced! x #f)) x*) - (let do-frame ([x* (set-formal-registers! x*)] [fv-idx 1]) - (unless (null? x*) - (let ([x (car x*)] [fv (get-fv fv-idx)]) - (uvar-location-set! x fv) - (do-frame (cdr x*) (fx+ fv-idx 1))))) - (let () - (define bind-formals - (lambda (mcp x* tlbody) - (define add-cpset - (lambda (mcp tlbody) - (if (and mcp (uvar-referenced? mcp)) `(seq (set! ,mcp ,(ref-reg %cp)) ,tlbody) tlbody))) - ; we set cp after registers and before frame vars, since it might - ; or might not be a register - (let f ([x* x*] [mcp mcp]) - (if (null? x*) - (add-cpset mcp tlbody) - (let ([x (car x*)]) - (if (uvar-referenced? x) - (let ([loc (uvar-location x)]) - (if (fv? loc) - (begin - (set! max-fv (fxmax max-fv (fv-offset loc))) - (add-cpset mcp `(seq (set! ,x ,loc) ,(f (cdr x*) #f)))) - `(seq (set! ,x ,loc) ,(f (cdr x*) mcp)))) - (f (cdr x*) mcp))))))) - (let ([tlbody (Tail tlbody)]) - (%seq - (label ,dcl) - ; TODO: don't want to save ret for leaf routines - ; TODO: don't necessarily want to position ret save here - ,(meta-cond - [(real-register? '%ret) `(set! ,(get-fv 0) ,%ret)] - [else `(nop)]) - (overflood-check) - ,(bind-formals mcp x* tlbody))))] - [(mvcall ,info ,mdcl ,t0? ,t1* ... (,t* ...)) - (build-tail-call info mdcl t0? t1* t*)] - [(foreign-call ,info ,[t0] ,[t1*] ...) - `(seq - ; CAUTION: fv0 must hold return address when we call into C - ,(build-foreign-call info t0 t1* %ac0 #f) - (jump ,(get-fv 0) (,%ac0)))] - [,rhs (do-return ,(Rhs ir))] - [(values ,info ,[t]) (do-return ,t)] - [(values ,info ,t* ...) (build-mv-return t*)])) - - (define-pass np-expand-hand-coded : L13 (ir) -> L13.5 () - (definitions - (import (only asm-module asm-enter)) - (define Ldoargerr (make-Ldoargerr)) - (define-$type-check (L13.5 Pred)) - (define make-info - (lambda (name interface*) - (make-info-lambda #f #f #f interface* name))) - (define make-arg-opnd - (lambda (n) - (let ([regnum (length arg-registers)]) - (if (fx<= n regnum) - (list-ref arg-registers (fx- n 1)) - (with-output-language (L13.5 Lvalue) - (%mref ,%sfp - ,(fx* (constant ptr-bytes) (fx- n regnum)))))))) - (define do-call - (lambda () - (with-output-language (L13.5 Tail) - (meta-cond - [(real-register? '%cp) - `(jump ,(%mref ,%cp ,(constant closure-code-disp)) - (,%ac0 ,%cp ,(reg-cons* %ret arg-registers) ...))] - [else - (%seq - (set! ,%td ,(ref-reg %cp)) - (jump ,(%mref ,%td ,(constant closure-code-disp)) - (,%ac0 ,(reg-cons* %ret arg-registers) ...)))])))) - (define (make-list*-procedure name) - (with-output-language (L13.5 CaseLambdaExpr) - (let ([Ltop (make-local-label 'ltop)]) - `(lambda ,(make-info name '(-2)) 0 () - (seq - (set! ,%ac0 ,(%inline - ,%ac0 (immediate 1))) - ; TODO: would be nice to avoid cmpl here - (if ,(%inline eq? ,%ac0 (immediate 0)) - (seq - (set! ,%ac0 ,(make-arg-opnd 1)) - (jump ,%ref-ret (,%ac0))) - ; TODO: would be nice to avoid second cmpl here - (if ,(%inline < ,%ac0 (immediate 0)) - (seq (pariah) (goto ,Ldoargerr)) - ,(%seq - (set! ,%ac0 ,(%inline sll ,%ac0 ,(%constant pair-shift))) - (set! ,%xp (alloc ,(make-info-alloc (constant type-pair) #f #f) ,%ac0)) - ,(let f ([reg* arg-registers] [i 0]) - (if (null? reg*) - ; filled in first i pairs - ; have at least two stack arguments - ; ac0 is at least (i+1) * pair-size; also amount allocated - (%seq - ; point xp to last pair of list - (set! ,%xp - ,(%lea ,%xp ,%ac0 - (fx- (constant size-pair)))) - ; adjust from two ptrs per pair to one ptr per stack element - (set! ,%ac0 - ,(%inline srl ,%ac0 (immediate 1))) - ; point ac0 to second-to-last stack argument - (set! ,%ac0 - ,(%lea ,%sfp ,%ac0 - (fx* i (fx- (constant ptr-bytes))))) - (set! ,(%mref ,%xp ,(constant pair-cdr-disp)) - ,(%mref ,%ac0 ,(constant ptr-bytes))) - (label ,Ltop) - (set! ,(%mref ,%xp ,(constant pair-car-disp)) - ,(%mref ,%ac0 0)) - (set! ,%ac0 ,(%inline - ,%ac0 ,(%constant ptr-bytes))) - (if ,(%inline eq? ,%ac0 ,%sfp) - ,(%seq - (set! ,%ac0 ,(%inline - ,%xp (immediate ,(fx* i (constant size-pair))))) - (jump ,%ref-ret (,%ac0))) - ,(%seq - (set! ,(%mref ,%xp ,(fx- (constant pair-cdr-disp) (constant size-pair))) - ,%xp) - (set! ,%xp ,(%inline - ,%xp ,(%constant size-pair))) - (goto ,Ltop)))) - (%seq - (set! ,(%mref ,%xp - ,(fx+ (fx* i (constant size-pair)) (constant pair-car-disp))) - ,(car reg*)) - (if ,(%inline eq? ,%ac0 (immediate ,(fx* (fx+ i 1) (constant size-pair)))) - ,(%seq - (set! ,(%mref ,%xp - ,(fx+ (fx* i (constant size-pair)) (constant pair-cdr-disp))) - ,(make-arg-opnd (fx+ i 2))) - (set! ,%ac0 ,%xp) - (jump ,%ref-ret (,%ac0))) - ,(%seq - (set! ,(%mref ,%xp - ,(fx+ (fx* i (constant size-pair)) (constant pair-cdr-disp))) - ,(%inline + ,%xp - (immediate ,(fx* (fx+ i 1) (constant size-pair))))) - ,(f (cdr reg*) (fx+ i 1))))))))))))))) - (module (make-do/call make-do/ret) - (define make-do - (lambda (enter e) - ; ret-loc is relevant only on machines with %ret reg: - ; #f => ret is known to be at sfp[0]---no need to save or restore - ; non-#f => save and restore to/from ret-loc - ; if C needs to know about or might change the return address, ret-loc - ; must be either #f or sfp[0]. otherwise, it can be (%tc-ref ret), which - ; is useful if we don't know if %ret holds the return address. in that case, - ; saving %ret to (%tc-ref ret) does no harm, nor does restoring it - ; from there, but it might be harmful to save %ret to sfp[0], since %ret's - ; contents are unknown. - (lambda (ret-loc name entry) - (with-output-language (L13.5 CaseLambdaExpr) - `(lambda ,(make-info name '()) 0 () - ,(enter - (%seq - ,(meta-cond - [(real-register? '%ret) (if ret-loc `(set! ,ret-loc ,%ret) `(nop))] - [else `(nop)]) - ,(with-saved-scheme-state - (in %ac0 %ac1 %cp %xp %yp %ts %td scheme-args extra-regs) - (out) - `(inline ,(make-info-c-simple-call #t entry) ,%c-simple-call)) - ,(meta-cond - [(real-register? '%ret) (if ret-loc `(set! ,%ret ,ret-loc) `(nop))] - [else `(nop)]) - ,e))))))) - (define make-do/call (make-do (lambda (e) e) (do-call))) - (define (make-do/ret entry-live* return-live*) - (with-output-language (L13.5 Tail) - (make-do (lambda (e) (asm-enter (%seq (check-live ,entry-live* ...) ,e))) - `(asm-return ,return-live* ...))))) - (define make-dofargint - (lambda (name size entry-live* return-live*) - (with-output-language (L13.5 CaseLambdaExpr) - `(lambda ,(make-info name '()) 0 () - ,(asm-enter - (%seq - (check-live ,entry-live* ...) - ,(cond - [(= (constant bigit-bits) size) - (%seq - (set! ,%td ,(%mref ,%ac0 ,(constant bignum-type-disp))) - (set! ,%ac0 - (inline ,(make-info-load (bigit-type) #f) ,%load - ,%ac0 ,%zero - ,(%constant bignum-data-disp))) - (if ,(%inline eq? ,%td - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (nop) - (set! ,%ac0 ,(%inline - (immediate 0) ,%ac0))))] - [(= (* (constant bigit-bits) 2) (* (constant ptr-bits) 2) size) - (let ([ac1 (in-context Lvalue (ref-reg %ac1))]) - (let ([Lnegative (make-local-label 'Lnegative)] [Lreturn (make-local-label 'Lreturn)]) - (%seq - (set! ,%xp ,%ac0) - (set! ,%td ,(%mref ,%xp ,(constant bignum-type-disp))) - (if ,(%inline eq? ,%td - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - ,(%seq - (set! ,%ac0 - (inline ,(make-info-load (bigit-type) #f) ,%load - ,%xp ,%zero - ,(%constant bignum-data-disp))) - (set! ,ac1 (immediate 0)) - (goto ,Lreturn)) - (if ,(%inline eq? ,%td - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-negative-bignum)))) - ,(%seq - (set! ,%ac0 - (inline ,(make-info-load (bigit-type) #f) ,%load - ,%xp ,%zero - ,(%constant bignum-data-disp))) - (set! ,ac1 (immediate 0)) - (goto ,Lnegative)) - ,(%seq - (set! ,ac1 - (inline ,(make-info-load (bigit-type) #f) ,%load - ,%xp ,%zero - ,(%constant bignum-data-disp))) - (set! ,%ac0 - (inline ,(make-info-load (bigit-type) #f) ,%load - ,%xp ,%zero - (immediate ,(fx+ (constant bignum-data-disp) (constant bigit-bytes))))) - (if ,(%inline eq? ,%td - (immediate ,(fx+ (fxsll 2 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (goto ,Lreturn) - (goto ,Lnegative))))) - (label ,Lnegative) - (set! ,%ac0 ,(%inline -/eq (immediate 0) ,%ac0)) - (if (inline ,(make-info-condition-code 'eq? #f #t) ,%condition-code) - (set! ,ac1 ,(%inline - (immediate 0) ,ac1)) - (set! ,ac1 ,(%inline lognot ,ac1))) - (label ,Lreturn))))] - [(= (* (constant bigit-bits) 2) (constant ptr-bits) size) - (let ([Lnegative (make-local-label 'Lnegative)] [Lreturn (make-local-label 'Lreturn)]) - (%seq - (set! ,%xp ,%ac0) - (set! ,%td ,(%mref ,%xp ,(constant bignum-type-disp))) - (set! ,%ac0 - (inline ,(make-info-load (bigit-type) #f) ,%load - ,%xp ,%zero - ,(%constant bignum-data-disp))) - (if ,(%inline eq? ,%td - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (goto ,Lreturn) - (if ,(%inline eq? ,%td - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-negative-bignum)))) - (goto ,Lnegative) - ,(%seq - (set! ,%xp - (inline ,(make-info-load (bigit-type) #f) ,%load - ,%xp ,%zero - (immediate ,(fx+ (constant bignum-data-disp) (constant bigit-bytes))))) - (set! ,%ac0 - ,(%inline sll ,%ac0 ,(%constant bigit-bits))) - (set! ,%ac0 ,(%inline logor ,%ac0 ,%xp)) - (if ,(%inline eq? ,%td - (immediate ,(fx+ (fxsll 2 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (goto ,Lreturn) - (goto ,Lnegative))))) - (label ,Lnegative) - (set! ,%ac0 ,(%inline - (immediate 0) ,%ac0)) - (label ,Lreturn)))] - [else (sorry! name "cannot handle size ~s" size)]) - (asm-return ,return-live* ...))))))) - (define make-dofretint - (lambda (name size entry-live* return-live*) - (with-output-language (L13.5 CaseLambdaExpr) - `(lambda ,(make-info name '()) 0 () - ,(asm-enter - (%seq - (check-live ,entry-live* ...) - ,(cond - [(= (constant bigit-bits) size) - (%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (constant bigit-bytes)) - #f #t)) - (if ,(%inline < ,%ac0 (immediate 0)) - ,(%seq - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-negative-bignum)))) - (set! ,%ac0 ,(%inline - (immediate 0) ,%ac0))) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-positive-bignum))))) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - ,(%constant bignum-data-disp) ,%ac0) - (set! ,%ac0 ,%xp))] - [(= (* (constant bigit-bits) 2) (* (constant ptr-bits) 2) size) - (let ([ac1 (in-context Lvalue (ref-reg %ac1))] - [Lstore1 (make-local-label 'Lstore1)] - [Lstore2 (make-local-label 'Lstore2)]) - (%seq - (if ,(%inline < ,ac1 (immediate 0)) - ,(%seq - (set! ,ac1 ,(%inline lognot ,ac1)) - (set! ,%ac0 ,(%inline - (immediate 0) ,%ac0)) - ; TODO: use condition code here - (if (if ,(%inline eq? ,%ac0 (immediate 0)) - ,(%seq - (set! ,ac1 ,(%inline + ,ac1 (immediate 1))) - (false)) - ,(%inline eq? ,ac1 (immediate 0))) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (constant bigit-bytes)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-negative-bignum)))) - (goto ,Lstore1)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (fx* (constant bigit-bytes) 2)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 2 (constant bignum-length-offset)) - (constant type-negative-bignum)))) - (goto ,Lstore2)))) - ; TODO: use condition code here - (if ,(%inline eq? ,ac1 (immediate 0)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (constant bigit-bytes)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (label ,Lstore1) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - ,(%constant bignum-data-disp) ,%ac0)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (fx* (constant bigit-bytes) 2)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 2 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (label ,Lstore2) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - ,(%constant bignum-data-disp) - ,ac1) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - (immediate ,(fx+ (constant bignum-data-disp) (constant bigit-bytes))) - ,%ac0)))) - (set! ,%ac0 ,%xp)))] - [(= (* (constant bigit-bits) 2) (constant ptr-bits) size) - (let ([Lstore1 (make-local-label 'Lstore1)] [Lstore2 (make-local-label 'Lstore2)]) - (%seq - (if ,(%inline < ,%ac0 (immediate 0)) - ,(%seq - (set! ,%ac0 ,(%inline - (immediate 0) ,%ac0)) - (set! ,%td ,(%inline srl ,%ac0 - ,(%constant bigit-bits))) - (if ,(%inline eq? ,%td (immediate 0)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (constant bigit-bytes)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-negative-bignum)))) - (goto ,Lstore1)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (fx* (constant bigit-bytes) 2)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 2 (constant bignum-length-offset)) - (constant type-negative-bignum)))) - (goto ,Lstore2)))) - ,(%seq - (set! ,%td ,(%inline srl ,%ac0 - ,(%constant bigit-bits))) - (if ,(%inline eq? ,%td (immediate 0)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (constant bigit-bytes)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (label ,Lstore1) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - ,(%constant bignum-data-disp) ,%ac0)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (fx* (constant bigit-bytes) 2)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 2 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (label ,Lstore2) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - ,(%constant bignum-data-disp) - ,%td) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - (immediate ,(fx+ (constant bignum-data-disp) (constant bigit-bytes))) - ,%ac0))))) - (set! ,%ac0 ,%xp)))] - [else (sorry! name "cannot handle size ~s" size)]) - (asm-return ,return-live* ...))))))) - (define make-dofretuns - (lambda (name size entry-live* return-live*) - (with-output-language (L13.5 CaseLambdaExpr) - `(lambda ,(make-info name '()) 0 () - ,(asm-enter - (%seq - (check-live ,entry-live* ...) - ,(cond - [(= (constant bigit-bits) size) - (%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (constant bigit-bytes)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - ,(%constant bignum-data-disp) ,%ac0) - (set! ,%ac0 ,%xp))] - [(= (* (constant bigit-bits) 2) (* (constant ptr-bits) 2) size) - (let ([ac1 (in-context Lvalue (ref-reg %ac1))]) - (%seq - (if ,(%inline eq? ,ac1 (immediate 0)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (constant bigit-bytes)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - ,(%constant bignum-data-disp) ,%ac0)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (fx* (constant bigit-bytes) 2)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 2 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - ,(%constant bignum-data-disp) - ,ac1) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - (immediate ,(fx+ (constant bignum-data-disp) (constant bigit-bytes))) - ,%ac0))) - (set! ,%ac0 ,%xp)))] - [(= (* (constant bigit-bits) 2) (constant ptr-bits) size) - (%seq - (set! ,%td ,(%inline srl ,%ac0 - ,(%constant bigit-bits))) - (if ,(%inline eq? ,%td (immediate 0)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (constant bigit-bytes)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 1 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - ,(%constant bignum-data-disp) ,%ac0)) - ,(%seq - (set! ,%xp - ,(%constant-alloc type-typed-object - (fx+ (constant header-size-bignum) (fx* (constant bigit-bytes) 2)) - #f #t)) - (set! ,(%mref ,%xp ,(constant bignum-type-disp)) - (immediate ,(fx+ (fxsll 2 (constant bignum-length-offset)) - (constant type-positive-bignum)))) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - ,(%constant bignum-data-disp) - ,%td) - (inline ,(make-info-load (bigit-type) #f) ,%store ,%xp ,%zero - (immediate ,(fx+ (constant bignum-data-disp) (constant bigit-bytes))) - ,%ac0))) - (set! ,%ac0 ,%xp))] - [else (sorry! name "cannot handle size ~s" size)]) - (asm-return ,return-live* ...))))))) - (define make-dofretu* - (lambda (name type size entry-live* return-live*) - (with-output-language (L13.5 CaseLambdaExpr) - (let ([Ltop1 (make-local-label 'Ltop1)] [Ltop2 (make-local-label 'Ltop2)]) - `(lambda ,(make-info name '()) 0 () - ,(asm-enter - (%seq - (check-live ,entry-live* ...) - ; argument in ac0, return value in xp - (if ,(%inline eq? ,%ac0 (immediate 0)) - ,(%seq - (set! ,%xp ,(%constant sfalse)) - (asm-return ,return-live* ...)) - ,(%seq - (set! ,%td (immediate 0)) - (label ,Ltop1) - (set! ,%ts - (inline ,(make-info-load type #f) ,%load ,%ac0 ,%td - (immediate 0))) - (if ,(%inline eq? ,%ts (immediate 0)) - (if ,(%inline eq? ,%td (immediate 0)) - ,(%seq - (set! ,%xp (literal ,(make-info-literal #f 'object #vu8() 0))) - (asm-return ,return-live* ...)) - ,(%seq - (set! ,(ref-reg %ac1) ,%td) - (set! ,%td ,(%inline + ,%td - (immediate - ,(fx+ (constant header-size-bytevector) - (fx- (constant byte-alignment) 1))))) - (set! ,%td ,(%inline logand ,%td - (immediate ,(fx- (constant byte-alignment))))) - (set! ,%xp (alloc ,(make-info-alloc (constant type-typed-object) #f #t) ,%td)) - (set! ,%td ,(ref-reg %ac1)) - (set! ,%td ,(%inline sll ,%td - ,(%constant bytevector-length-offset))) - (set! ,%td ,(%inline logor ,%td - ,(%constant type-bytevector))) - (set! ,(%mref ,%xp ,(constant bytevector-type-disp)) - ,%td) - (set! ,%td ,(ref-reg %ac1)) - (label ,Ltop2) - (if ,(%inline eq? ,%td (immediate 0)) - (asm-return ,return-live* ...) - ,(%seq - (set! ,%td ,(%inline - ,%td (immediate ,size))) - (set! ,%ts - (inline ,(make-info-load type #f) ,%load ,%ac0 ,%td - (immediate 0))) - (inline ,(make-info-load type #f) ,%store ,%xp ,%td - ,(%constant bytevector-data-disp) - ,%ts) - (goto ,Ltop2))))) - ,(%seq - (set! ,%td ,(%inline + ,%td (immediate ,size))) - (goto ,Ltop1))))))))))))) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(hand-coded ,sym) - (case sym - [(values-procedure) - (let ([regnum (length arg-registers)] - [Ltop (make-local-label 'top)]) - `(lambda ,(make-info "values" '(-1)) 0 () - (if ,(%inline eq? ,%ac0 (immediate 1)) - (seq - (set! ,%ac0 ,(make-arg-opnd 1)) - (jump ,%ref-ret (,%ac0))) - ,(meta-cond - [(real-register? '%ret) - `(jump ,(%mref ,%ret ,(constant return-address-mv-return-address-disp)) - (,%ac0 ,%ret ,arg-registers ...))] - [else - (%seq - (set! ,%xp ,%ref-ret) - (jump ,(%mref ,%xp - ,(constant return-address-mv-return-address-disp)) - (,%ac0 ,arg-registers ... ,(get-fv 0))))]))))] - [($apply-procedure) - (let ([Lloop (make-local-label 'loop)] - [Ldone (make-local-label 'done)]) - `(lambda ,(make-info "$apply" '(3)) 0 () - ,(%seq - (set! ,(ref-reg %cp) ,(make-arg-opnd 1)) - (set! ,%ac0 ,(make-arg-opnd 2)) - (set! ,%xp ,(make-arg-opnd 3)) - ;; TODO: when fixnum-offset = log2-ptr-bytes, we can avoid an sll by saving - ;; %ac0 before we shift it right. - (set! ,%ac0 ,(%inline sra ,%ac0 ,(%constant fixnum-offset))) - (if ,(%inline eq? ,%ac0 (immediate 0)) - (goto ,Ldone) - ,(%seq - (set! ,%td ,(%inline sll ,%ac0 ,(%constant log2-ptr-bytes))) - (set! ,%td ,(%inline + ,%td ,%sfp)) - (if ,(%inline > ,%td ,(ref-reg %esp)) - (seq (pariah) - ,(with-saved-ret-reg - (with-saved-scheme-state - (in %cp %xp %ac0) - (out %ac1 %yp %ts %td scheme-args extra-regs) - `(inline ,(make-info-c-simple-call #f (lookup-c-entry handle-apply-overflood)) ,%c-simple-call)))) - (nop)) - ,(let load-regs ([regs arg-registers]) - (if (null? regs) - (%seq - (set! ,%td ,%sfp) - (label ,Lloop) - (set! ,(%mref ,%td ,(constant ptr-bytes)) - ,(%mref ,%xp ,(constant pair-car-disp))) - (set! ,%xp - ,(%mref ,%xp ,(constant pair-cdr-disp))) - (if ,(%type-check mask-nil snil ,%xp) - ,(%seq (label ,Ldone) ,(do-call)) - ,(%seq - (set! ,%td ,(%inline + ,%td ,(%constant ptr-bytes))) - (goto ,Lloop)))) - (%seq - (set! ,(car regs) ,(%mref ,%xp ,(constant pair-car-disp))) - (set! ,%xp ,(%mref ,%xp ,(constant pair-cdr-disp))) - (if ,(%type-check mask-nil snil ,%xp) - (goto ,Ldone) - ,(load-regs (cdr regs)))))))))))] - [(list*-procedure) (make-list*-procedure "list*")] - [(cons*-procedure) (make-list*-procedure "cons*")] - [($record-procedure) - (let ([Ltop (make-local-label 'ltop)]) - `(lambda ,(make-info "$record" '(-2)) 0 () - (if ,(%inline eq? ,%ac0 (immediate 0)) - (seq (pariah) (goto ,Ldoargerr)) - ,(%seq - (set! ,%ac0 ,(%inline sll ,%ac0 ,(%constant log2-ptr-bytes))) - (set! ,%td ,(%inline + ,%ac0 (immediate ,(fx- (constant byte-alignment) 1)))) - (set! ,%td ,(%inline logand ,%td (immediate ,(- (constant byte-alignment))))) - (set! ,%xp (alloc ,(make-info-alloc (constant type-typed-object) #f #f) ,%td)) - ,(let f ([reg* arg-registers] [i 0]) - (if (null? reg*) - (%seq - ; point xp to last element of record - (set! ,%xp - ,(%lea ,%xp ,%ac0 (fx- (constant ptr-bytes)))) - ; point ac0 to last stack argument - (set! ,%ac0 - ,(%lea ,%sfp ,%ac0 - (fx* i (fx- (constant ptr-bytes))))) - (label ,Ltop) - (set! ,(%mref ,%xp ,(constant record-type-disp)) - ,(%mref ,%ac0 0)) - (set! ,%ac0 ,(%inline - ,%ac0 ,(%constant ptr-bytes))) - (if ,(%inline eq? ,%ac0 ,%sfp) - ,(%seq - (set! ,%ac0 ,(%inline - ,%xp (immediate ,(fx* i (constant ptr-bytes))))) - (jump ,%ref-ret (,%ac0))) - ,(%seq - (set! ,%xp ,(%inline - ,%xp ,(%constant ptr-bytes))) - (goto ,Ltop)))) - (%seq - (set! ,(%mref ,%xp - ,(fx+ (fx* i (constant ptr-bytes)) (constant record-type-disp))) - ,(car reg*)) - (if ,(%inline eq? ,%ac0 (immediate ,(fx* (fx+ i 1) (constant ptr-bytes)))) - ,(%seq - (set! ,%ac0 ,%xp) - (jump ,%ref-ret (,%ac0))) - ,(f (cdr reg*) (fx+ i 1))))))))))] - [(vector-procedure) - (let ([Ltop (make-local-label 'ltop)]) - `(lambda ,(make-info "vector" '(-1)) 0 () - (if ,(%inline eq? ,%ac0 (immediate 0)) - ,(%seq - (set! ,%ac0 (literal ,(make-info-literal #f 'object '#() 0))) - (jump ,%ref-ret (,%ac0))) - ,(%seq - (set! ,%ac0 ,(%inline sll ,%ac0 ,(%constant log2-ptr-bytes))) - (set! ,%td ,(%inline + ,%ac0 (immediate ,(fx+ (constant ptr-bytes) (fx- (constant byte-alignment) 1))))) - (set! ,%td ,(%inline logand ,%td (immediate ,(- (constant byte-alignment))))) - (set! ,%xp (alloc ,(make-info-alloc (constant type-typed-object) #f #f) ,%td)) - ,(let ([delta (fx- (constant vector-length-offset) (constant log2-ptr-bytes))]) - (safe-assert (fx>= delta 0)) - (if (fx= delta 0) - (if (fx= (constant type-vector) 0) - `(set! ,(%mref ,%xp ,(constant vector-type-disp)) ,%ac0) - (%seq - (set! ,%td ,(%inline logor ,%ac0 (immediate ,(constant type-vector)))) - (set! ,(%mref ,%xp ,(constant vector-type-disp)) ,%td))) - (%seq - (set! ,%td ,(%inline sll ,%ac0 (immediate ,delta))) - ,(if (fx= (constant type-vector) 0) - `(set! ,(%mref ,%xp ,(constant vector-type-disp)) ,%td) - (%seq - (set! ,%td ,(%inline logor ,%td (immediate ,(constant type-vector)))) - (set! ,(%mref ,%xp ,(constant vector-type-disp)) ,%td)))))) - ,(let f ([reg* arg-registers] [i 0]) - (if (null? reg*) - (%seq - ; point xp to last element of vector - (set! ,%xp ,(%inline + ,%xp ,%ac0)) - ; point ac0 to last stack argument - (set! ,%ac0 - ,(%lea ,%sfp ,%ac0 - (fx* i (fx- (constant ptr-bytes))))) - (label ,Ltop) - (set! ,(%mref ,%xp ,(fx- (constant vector-data-disp) (constant ptr-bytes))) - ,(%mref ,%ac0 0)) - (set! ,%ac0 ,(%inline - ,%ac0 ,(%constant ptr-bytes))) - (if ,(%inline eq? ,%ac0 ,%sfp) - ,(%seq - (set! ,%ac0 ,(%inline - ,%xp (immediate ,(fx* (fx+ i 1) (constant ptr-bytes))))) - (jump ,%ref-ret (,%ac0))) - ,(%seq - (set! ,%xp ,(%inline - ,%xp ,(%constant ptr-bytes))) - (goto ,Ltop)))) - (%seq - (set! ,(%mref ,%xp - ,(fx+ (fx* i (constant ptr-bytes)) (constant vector-data-disp))) - ,(car reg*)) - (if ,(%inline eq? ,%ac0 (immediate ,(fx* (fx+ i 1) (constant ptr-bytes)))) - ,(%seq - (set! ,%ac0 ,%xp) - (jump ,%ref-ret (,%ac0))) - ,(f (cdr reg*) (fx+ i 1))))))))))] - [(list-procedure) - (let ([Ltop (make-local-label 'ltop)]) - `(lambda ,(make-info "list" '(-1)) 0 () - (if ,(%inline eq? ,%ac0 (immediate 0)) - (seq - (set! ,%ac0 ,(%constant snil)) - (jump ,%ref-ret (,%ac0))) - ,(%seq - (set! ,%ac0 ,(%inline sll ,%ac0 ,(%constant pair-shift))) - (set! ,%xp (alloc ,(make-info-alloc (constant type-pair) #f #f) ,%ac0)) - ,(let f ([reg* arg-registers] [i 0]) - (if (null? reg*) - ; filled in first i pairs - ; have at least one stack argument - ; ac0 is amount allocated, or size-pair * # elements - (%seq - ; point xp to last pair of list - (set! ,%xp - ,(%lea ,%xp ,%ac0 (fx- (constant size-pair)))) - ; adjust from two ptrs per pair to one ptr per stack element - (set! ,%ac0 - ,(%inline srl ,%ac0 (immediate 1))) - ; point ac0 to last stack argument - (set! ,%ac0 - ,(%lea ,%sfp ,%ac0 - (fx* i (fx- (constant ptr-bytes))))) - (set! ,(%mref ,%xp ,(constant pair-cdr-disp)) - ,(%constant snil)) - (label ,Ltop) - (set! ,(%mref ,%xp ,(constant pair-car-disp)) - ,(%mref ,%ac0 0)) - (set! ,%ac0 ,(%inline - ,%ac0 ,(%constant ptr-bytes))) - (if ,(%inline eq? ,%ac0 ,%sfp) - ,(%seq - (set! ,%ac0 ,(%inline - ,%xp (immediate ,(fx* i (constant size-pair))))) - (jump ,%ref-ret (,%ac0))) - ,(%seq - (set! ,(%mref ,%xp ,(fx- (constant pair-cdr-disp) (constant size-pair))) - ,%xp) - (set! ,%xp ,(%inline - ,%xp ,(%constant size-pair))) - (goto ,Ltop)))) - (%seq - (set! ,(%mref ,%xp - ,(fx+ (fx* i (constant size-pair)) (constant pair-car-disp))) - ,(car reg*)) - (if ,(%inline eq? ,%ac0 (immediate ,(fx* (fx+ i 1) (constant size-pair)))) - ,(%seq - (set! ,(%mref ,%xp - ,(fx+ (fx* i (constant size-pair)) (constant pair-cdr-disp))) - ,(%constant snil)) - (set! ,%ac0 ,%xp) - (jump ,%ref-ret (,%ac0))) - ,(%seq - (set! ,(%mref ,%xp - ,(fx+ (fx* i (constant size-pair)) (constant pair-cdr-disp))) - ,(%inline + ,%xp - (immediate ,(fx* (fx+ i 1) (constant size-pair))))) - ,(f (cdr reg*) (fx+ i 1)))))))))))] - [($instantiate-code-object) - `(lambda ,(make-info "$instantiate-code-object" '(3)) 0 () - ,(%seq - ,(with-saved-ret-reg - (%seq - ,(save-scheme-state - (in scheme-args) - (out %ac0 %ac1 %cp %xp %yp %ts %td extra-regs)) - (inline ,(make-info-c-simple-call #f (lookup-c-entry instantiate-code-object)) - ,%c-simple-call) - ,(restore-scheme-state - (in %ac0) - (out %ac1 %cp %xp %yp %ts %td scheme-args extra-regs)))) - (jump ,%ref-ret (,%ac0))))] - [(values-error) (make-do/call (in-context Lvalue (%tc-ref ret)) "values-error" (lookup-c-entry handle-values-error))] - [(domvleterr) (make-do/call (in-context Lvalue (%tc-ref ret)) "domvleterr" (lookup-c-entry handle-mvlet-error))] - [(doargerr) (make-do/call (in-context Lvalue (%tc-ref ret)) "doargerr" (lookup-c-entry handle-arg-error))] - [(call-error) (make-do/call (in-context Lvalue (%tc-ref ret)) "call-error" (lookup-c-entry handle-docall-error))] - [(dooverflow) ((make-do/ret (intrinsic-entry-live* dooverflow) (intrinsic-return-live* dooverflow)) #f "dooverflow" (lookup-c-entry handle-overflow))] - [(dooverflood) ((make-do/ret (intrinsic-entry-live* dooverflood) (intrinsic-return-live* dooverflood)) #f "dooverflood" (lookup-c-entry handle-overflood))] - [(scan-remembered-set) ((make-do/ret (intrinsic-entry-live* scan-remembered-set) (intrinsic-return-live* scan-remembered-set)) (in-context Lvalue (%tc-ref ret)) "scan-remembered-set" (lookup-c-entry scan-remembered-set))] - [(get-room) ((make-do/ret (intrinsic-entry-live* get-room) (intrinsic-return-live* get-room)) (in-context Lvalue (%tc-ref ret)) "get-room" (lookup-c-entry get-more-room))] - [(nonprocedure-code) - `(lambda ,(make-info "nonprocedure-code" '()) 0 () - ,(%seq - (set! ,%td ,(%mref ,%xp ,(constant symbol-value-disp))) - (if ,(%type-check mask-closure type-closure ,%td) - (seq - (set! ,(ref-reg %cp) ,%td) - (set! ,(%mref ,%xp ,(constant symbol-pvalue-disp)) - ,(%mref ,%td ,(constant closure-code-disp)))) - ,(with-saved-ret-reg - (with-saved-scheme-state - (in %ac0 %ac1 %cp %xp %yp scheme-args) - (out %ts %td extra-regs) - `(inline ,(make-info-c-simple-call #f (lookup-c-entry handle-nonprocedure-symbol)) - ,%c-simple-call)))) - ,(do-call)))] - [($foreign-entry-procedure) - `(lambda ,(make-info "$foreign-entry" '(1)) 0 () - ,(%seq - (set! ,%ac0 ,(make-arg-opnd 1)) - ,(with-saved-ret-reg - (with-saved-scheme-state - (in %ac0) - (out %cp %xp %yp %ac1 %ts %td scheme-args extra-regs) - `(inline ,(make-info-c-simple-call #f (lookup-c-entry foreign-entry)) - ,%c-simple-call))) - (jump ,%ref-ret (,%ac0))))] - [($install-library-entry-procedure) - `(lambda ,(make-info "$install-library-entry" '(2)) 0 () - ,(%seq - ,(with-saved-ret-reg - (%seq - ,(save-scheme-state - (in scheme-args) - (out %ac0 %ac1 %cp %xp %yp %ts %td extra-regs)) - (inline ,(make-info-c-simple-call #f (lookup-c-entry install-library-entry)) - ,%c-simple-call) - ,(restore-scheme-state - (in) - (out %ac0 %ac1 %cp %xp %yp %ts %td scheme-args extra-regs)))) - (set! ,%ac0 ,(%constant svoid)) - (jump ,%ref-ret (,%ac0))))] - [(bytevector=?) - (let ([bv1 (make-tmp 'bv1)] [bv2 (make-tmp 'bv2)] [idx (make-tmp 'idx)] [len2 (make-tmp 'len2)]) - (define (argcnt->max-fv n) (max (- n (length arg-registers)) 0)) - (let ([Ltop (make-local-label 'Ltop)] [Ltrue (make-local-label 'Ltrue)] [Lfail (make-local-label 'Lfail)]) - (define iptr-bytes (in-context Triv (%constant ptr-bytes))) - `(lambda ,(make-info "bytevector=?" '(2)) ,(argcnt->max-fv 2) (,bv1 ,bv2 ,idx ,len2) - ,(%seq - (set! ,bv1 ,(make-arg-opnd 1)) - (set! ,bv2 ,(make-arg-opnd 2)) - (if ,(%inline eq? ,bv1 ,bv2) - (goto ,Ltrue) - ,(%seq - (set! ,idx ,(%inline srl - ,(%mref ,bv1 ,(constant bytevector-type-disp)) - ,(%constant bytevector-length-offset))) - (set! ,len2 ,(%inline srl - ,(%mref ,bv2 ,(constant bytevector-type-disp)) - ,(%constant bytevector-length-offset))) - (if ,(%inline eq? ,len2 ,idx) - ,(%seq - (label ,Ltop) - (if ,(%inline >= ,idx ,iptr-bytes) - (if ,(%inline eq? - ,(%mref ,bv1 ,(constant bytevector-data-disp)) - ,(%mref ,bv2 ,(constant bytevector-data-disp))) - ,(%seq - (set! ,idx ,(%inline - ,idx ,iptr-bytes)) - (set! ,bv1 ,(%inline + ,bv1 ,iptr-bytes)) - (set! ,bv2 ,(%inline + ,bv2 ,iptr-bytes)) - (goto ,Ltop)) - (goto ,Lfail)) - (if (if ,(%inline eq? ,idx (immediate 0)) - (true) - ,(%seq - (set! ,bv1 ,(%mref ,bv1 ,(constant bytevector-data-disp))) - (set! ,bv2 ,(%mref ,bv2 ,(constant bytevector-data-disp))) - (set! ,idx ,(%inline - ,iptr-bytes ,idx)) - (set! ,idx ,(%inline sll ,idx (immediate 3))) - ,(constant-case native-endianness - [(little) - (%seq - (set! ,bv1 ,(%inline sll ,bv1 ,idx)) - (set! ,bv2 ,(%inline sll ,bv2 ,idx)))] - [(big) - (%seq - (set! ,bv1 ,(%inline srl ,bv1 ,idx)) - (set! ,bv2 ,(%inline srl ,bv2 ,idx)))]) - ,(%inline eq? ,bv1 ,bv2))) - ,(%seq - (label ,Ltrue) - (set! ,%ac0 ,(%constant strue)) - (jump ,%ref-ret (,%ac0))) - (goto ,Lfail)))) - ,(%seq - (label ,Lfail) - (set! ,%ac0 ,(%constant sfalse)) - (jump ,%ref-ret (,%ac0))))))))))] - [(dofargint32) (make-dofargint "dofargint32" 32 (intrinsic-entry-live* dofargint32) (intrinsic-return-live* dofargint32))] - [(dofargint64) (make-dofargint "dofargint64" 64 (intrinsic-entry-live* dofargint64) (intrinsic-return-live* dofargint64))] - [(dofretint32) (make-dofretint "doretint32" 32 (intrinsic-entry-live* dofretint32) (intrinsic-return-live* dofretint32))] - [(dofretint64) (make-dofretint "doretint64" 64 (intrinsic-entry-live* dofretint64) (intrinsic-return-live* dofretint64))] - [(dofretuns32) (make-dofretuns "doretuns32" 32 (intrinsic-entry-live* dofretuns32) (intrinsic-return-live* dofretuns32))] - [(dofretuns64) (make-dofretuns "doretuns64" 64 (intrinsic-entry-live* dofretuns64) (intrinsic-return-live* dofretuns64))] - [(dofretu8*) (make-dofretu* "dofretu8*" 'unsigned-8 1 (intrinsic-entry-live* dofretu8*) (intrinsic-return-live* dofretu8*))] - [(dofretu16*) (make-dofretu* "dofretu16*" 'unsigned-16 2 (intrinsic-entry-live* dofretu16*) (intrinsic-return-live* dofretu16*))] - [(dofretu32*) (make-dofretu* "dofretu32*" 'unsigned-32 4 (intrinsic-entry-live* dofretu32*) (intrinsic-return-live* dofretu32*))] - [(error-invoke) ; more generally "tail-reentry" - `(lambda ,(make-info "error-invoke" '()) 0 () - ,(%seq - ,(%inline invoke-prelude) - ,(restore-scheme-state - (in %ac0 %ac1 %cp %xp %yp scheme-args) - (out %ts %td extra-regs)) - ,(meta-cond - [(real-register? '%ret) `(set! ,%ret ,(%mref ,%sfp 0))] - [else `(nop)]) - ,(do-call)))] - [(invoke) - (let ([Lret (make-local-label 'Lret)] - [Lexit (make-local-label 'Lexit)] - [Lmvreturn (make-local-label 'Lmvreturn)]) - `(lambda ,(make-info "invoke" '()) 0 () - ,(%seq - ; TODO: add alignment - #;(asm align) ; must start aligned or align below may fail - ,(%inline invoke-prelude) - ,(restore-scheme-state - (in %ac0 %cp scheme-args) - (out %ac1 %xp %yp %ts %td extra-regs)) - (new-frame ,(make-info-newframe #f #f '() '() '()) ,'() ... ,Lret) - ; NB: hack!!! - (set! ,%sfp ,(%inline - ,%sfp (immediate ,(constant ptr-bytes)))) - (set! ,%ref-ret (label-ref ,Lret ,(constant size-rp-header))) - (tail ,(do-call)) ; argcnt already in ac0 - #;(asm align) - (label ,Lret) - (rp-header ,Lmvreturn ,(* 2 (constant ptr-bytes)) 1) ; cchain is live at sfp[ptr-bytes] - (set! ,(ref-reg %ac1) (immediate 1)) ; single-value as expected - ,(save-scheme-state - (in %ac0 %ac1) - (out %cp %xp %yp %ts %td scheme-args extra-regs)) - (label ,Lexit) - (inline ,(make-info-c-simple-call #f (lookup-c-entry Sreturn)) ,%c-simple-call) - (label ,Lmvreturn) - (set! ,(ref-reg %ac1) ,%ac0) - ,(save-scheme-state - (in %ac0 %ac1 scheme-args) - (out %cp %xp %yp %ts %td extra-regs)) - (goto ,Lexit))))] - [else ($oops who "unrecognized hand-coded name ~s" sym)])])) - - (define-pass np-expose-allocation-pointer : L13.5 (ir) -> L14 () - ; NB: uses %ts when %ap is not a real register - ; NB: should use an unspillable, but we don't have unspillables yet - (definitions - (define local*) - (define make-tmp - (lambda (x) - (import (only np-languages make-tmp)) - (let ([x (make-tmp x)]) - (set! local* (cons x local*)) - x))) - (define refap (with-output-language (L14 Triv) (ref-reg %ap))) - (define refeap (with-output-language (L14 Triv) (ref-reg %eap))) - (with-output-language (L14 Effect) - (define build-alloc - (lambda (info lvalue t) - (let ([Lget-room (make-local-label 'Lget-room)]) - ((lambda (p) - (meta-cond - [(real-register? '%ap) (p %ap values)] - [else `(seq (set! ,%ts ,refap) ,(p %ts (lambda (e) `(seq ,e (set! ,refap ,%ts)))))])) - (lambda (ap store-ap) - (%seq - (set! ,%xp ,(%inline + ,ap (immediate ,(- (info-alloc-tag info) (constant typemod))))) - ,(nanopass-case (L14 Triv) t - [(immediate ,imm) - (guard (fixnum? imm) (fx< imm (constant bytes-per-segment))) - ; reset_allocation_pointer never uses the last segment of the address - ; space, so we can allocate less than bytes-per-segment w/o carry check - (store-ap `(set! ,ap ,(%inline + ,ap ,t)))] - [else - (%seq - ,(store-ap `(set! ,ap ,(%inline +/carry ,ap ,t))) - (if (inline ,(make-info-condition-code 'carry #f #t) ,%condition-code) - (goto ,Lget-room) - (nop)))]) - (if ,(%inline u< ,refeap ,ap) - ,(%seq - (label ,Lget-room) - (pariah) - ,((lambda (e) - (if (info-alloc-save-flrv? info) - (%seq ,(%inline save-flrv) ,e ,(%inline restore-flrv)) - e)) - `(set! ,%xp (inline ,(intrinsic-info-asmlib get-room (info-alloc-save-ra? info)) ,%asmlibcall)))) - (nop)) - (set! ,lvalue ,%xp))))))) - (define (build-inc-cc-counter arg) - (%inline inc-cc-counter ,%tc ,(%constant tc-alloc-counter-disp) ,arg)) - (define (build-shift-and-inc-cc-counter t) - (let ([tcnt (make-tmp 'tcnt)]) - (%seq - (set! ,tcnt ,(%inline sra ,t ,(%constant log2-ptr-bytes))) - ,(build-inc-cc-counter tcnt)))) - (define alloc-helper - (lambda (info lvalue t) - (if (generate-allocation-counts) - (nanopass-case (L14 Triv) t - [(immediate ,imm) - (%seq - ,(build-inc-cc-counter - (in-context Triv - `(immediate ,(fxsra imm (constant log2-ptr-bytes))))) - ,(build-alloc info lvalue t))] - [else - (if (var? t) - (%seq ,(build-shift-and-inc-cc-counter t) ,(build-alloc info lvalue t)) - (let ([talloc (make-tmp 'talloc)]) - (%seq - (set! ,talloc ,t) - ,(build-shift-and-inc-cc-counter talloc) - ,(build-alloc info lvalue talloc))))]) - (build-alloc info lvalue t)))))) - (Effect : Effect (ir) -> Effect () - [(inline ,info ,effect-prim ,t) - (guard (eq? effect-prim %remember)) - (if (real-register? '%eap) - (%seq - (if ,(%inline u< ,refap ,refeap) - (nop) - (seq - (pariah) - (inline ,(intrinsic-info-asmlib scan-remembered-set #f) ,%asmlibcall!))) - (set! ,refeap ,(%inline - ,refeap ,(%constant ptr-bytes))) - ; write through to tc so dirty-list bounds are always known in case of an - ; invalid memory reference or illegal instruction - (set! (mref ,%tc ,%zero ,(tc-disp %eap)) ,refeap) - (set! ,(%mref ,refeap 0) ,t)) - (%seq - (set! ,%td ,refeap) - (if ,(%inline u< ,refap ,%td) - (nop) - ,(%seq - (pariah) - (inline ,(intrinsic-info-asmlib scan-remembered-set #f) ,%asmlibcall!) - (set! ,%td ,refeap))) - (set! ,%td ,(%inline - ,%td ,(%constant ptr-bytes))) - (set! ,refeap ,%td) - (set! ,(%mref ,%td 0) ,t)))] - [(set! ,lvalue (alloc ,info ,[t])) (alloc-helper info lvalue t)]) - (Tail : Tail (ir) -> Tail ()) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info ,max-fv (,local0* ...) ,tlbody) - (fluid-let ([local* local0*]) - (let ([tlbody (Tail tlbody)]) - `(lambda ,info ,max-fv (,local* ...) ,tlbody)))])) - - (define-record-type goto-block - (parent block) - (fields (mutable next)) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (rec make-goto-block - (case-lambda - [() (make-goto-block #f)] - [(next) ((pargs->new) next)]))))) - - (define-record-type if-block - (parent block) - (fields - (mutable pred) - (mutable true) - (mutable false) - (mutable live-out)) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (true false) - ((pargs->new) #f true false 'uninitialized))))) - - (define-record-type newframe-block - (parent block) - (fields - info - (mutable next) - (mutable rp*) - (mutable rp) - (mutable live-rp) - (mutable live-call) - (mutable live-out)) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (info next) - ((pargs->new) info next #f #f 'uninitialized 'uninitialized 'uninitialized))))) - - (define-record-type joto-block - (parent block) - (fields nfv* (mutable next)) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (nfv*) - ((pargs->new) nfv* #f))))) - - (define-record-type tail-block - (parent block) - (fields (mutable tail) (mutable exit)) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda () - ((pargs->new) #f #f))))) - - (define-record-type bcache - (fields effect*) - (nongenerative) - (protocol - (lambda (new) - (lambda (block) - (new (block-effect* block)))))) - - (define-record-type if-bcache - (parent bcache) - (fields pred) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (block) - ((pargs->new block) (if-block-pred block)))))) - - (define-record-type tail-bcache - (parent bcache) - (fields tail) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (block) - ((pargs->new block) (tail-block-tail block)))))) - - (define-who cache-block-info - (lambda (block) - (cond - [(or (goto-block? block) (joto-block? block) (newframe-block? block)) (make-bcache block)] - [(if-block? block) (make-if-bcache block)] - [(tail-block? block) (make-tail-bcache block)] - [else (sorry! who "unrecognized block ~s" block)]))) - - (define-who restore-block-info! - (lambda (block bcache) - (block-effect*-set! block (bcache-effect* bcache)) - (cond - [(or (goto-block? block) (joto-block? block) (newframe-block? block)) (void)] - [(if-block? block) (if-block-pred-set! block (if-bcache-pred bcache))] - [(tail-block? block) (tail-block-tail-set! block (tail-bcache-tail bcache))] - [else (sorry! who "unrecognized block ~s" block)]))) - - (define-pass np-expose-basic-blocks : L14 (ir) -> L15a () - (definitions - (define add-instr! - (lambda (block ir) - (block-effect*-set! block (cons ir (block-effect* block))))) - - (define add-label-link! - (lambda (from l setter) - (let ([x (local-label-block l)]) - (if (block? x) - (setter from x) - (local-label-block-set! l (cons (lambda (to) (setter from to)) (or x '()))))))) - - (define resolve-waiting-links! - (lambda (l to) - (let ([x (local-label-block l)]) - (safe-assert (not (block? x))) - (when x (for-each (lambda (add-link!) (add-link! to)) x)) - (local-label-block-set! l to)))) - - (define-pass build-graph : (L14 Tail) (ir) -> * (block block*) - (definitions - (define add-goto-block - (lambda (l block*) - (if (local-label? l) - (let ([block (make-goto-block)]) - (add-label-link! block l goto-block-next-set!) - (values block (cons block block*))) - (let ([block (make-tail-block)]) - (tail-block-tail-set! block (with-output-language (L15a Tail) `(goto ,l))) - (values block (cons block block*)))))) - (define add-true/false-block - (lambda (target block* label-name) - (let ([block (make-goto-block target)]) - (unless (block-label target) - (block-label-set! target (make-local-label label-name))) - (values block (cons block block*)))))) - (Lvalue : Lvalue (ir target) -> * (ir) - [,x x] - [(mref ,x1 ,x2 ,imm) (with-output-language (L15a Lvalue) `(mref ,x1 ,x2 ,imm))]) - (Triv : Triv (ir target) -> * (ir) - [(literal ,info) (with-output-language (L15a Triv) `(literal ,info))] - [(immediate ,imm) (with-output-language (L15a Triv) `(immediate ,imm))] - [,lvalue (Lvalue lvalue target)] - [(label-ref ,l ,offset) (with-output-language (L15a Triv) `(label-ref ,l ,offset))]) - ;; TODO: framework should come up with some way of handling or complaining about a - ;; (maybe foo) when returning from a multiple value case. - (Rhs : Rhs (ir target) -> * (ir) - [(inline ,info ,value-prim ,[Triv : t target -> t] ...) - (with-output-language (L15a Rhs) `(inline ,info ,value-prim ,t ...))] - [,t (Triv t target)]) - (Tail : Tail (ir block*) -> * (block block*) - [(goto ,l) (add-goto-block l block*)] - [(seq ,e0 ,[block block*]) (Effect e0 block block*)] - [(if ,p0 ,tl1 ,[f-block block*]) - (let-values ([(t-block block*) (Tail tl1 block*)]) - (Pred p0 t-block f-block block*))] - [(jump ,t (,var* ...)) - (let ([block (make-tail-block)]) - (tail-block-tail-set! block - (with-output-language (L15a Tail) - `(jump ,(make-live-info) ,(Triv t block) (,var* ...)))) - (values block (cons block block*)))] - [(joto ,l (,nfv* ...)) - (let ([block (make-joto-block nfv*)]) - (add-label-link! block l joto-block-next-set!) - (values block (cons block block*)))] - [(asm-return ,reg* ...) - (let ([block (make-tail-block)]) - (tail-block-tail-set! block (with-output-language (L15a Tail) `(asm-return ,reg* ...))) - (values block (cons block block*)))] - [(asm-c-return ,info ,reg* ...) - (let ([block (make-tail-block)]) - (tail-block-tail-set! block (with-output-language (L15a Tail) `(asm-c-return ,info ,reg* ...))) - (values block (cons block block*)))] - [else ($oops who "unexpected Tail ~s" ir)]) - (Effect : Effect (ir target block*) -> * (target block*) - [(nop) (values target block*)] - [(inline ,info ,effect-prim ,[Triv : t target -> t] ...) - (add-instr! target (with-output-language (L15a Effect) `(inline ,(make-live-info) ,info ,effect-prim ,t ...))) - (values target block*)] - [(overflow-check) - (add-instr! target (with-output-language (L15a Effect) `(overflow-check ,(make-live-info)))) - (values target block*)] - [(overflood-check) - (add-instr! target (with-output-language (L15a Effect) `(overflood-check ,(make-live-info)))) - (values target block*)] - [(fcallable-overflow-check) - (add-instr! target (with-output-language (L15a Effect) `(fcallable-overflow-check ,(make-live-info)))) - (values target block*)] - [(new-frame ,info ,rpl* ... ,rpl) - (let ([block (make-newframe-block info target)] [l (make-local-label 'docall)]) - (block-label-set! target l) - (let ([rp* (fold-left (lambda (ls rp) (cons #f ls)) '() rpl*)]) - (newframe-block-rp*-set! block rp*) - (let loop ([rpl* rpl*] [rp* rp*]) - (unless (null? rpl*) - (add-label-link! rp* (car rpl*) set-car!) - (loop (cdr rpl*) (cdr rp*))))) - (add-label-link! block rpl newframe-block-rp-set!) - (values block (cons block block*)))] - [(remove-frame ,info) - (add-instr! target (with-output-language (L15a Effect) `(remove-frame ,(make-live-info) ,info))) - (values target block*)] - [(restore-local-saves ,info) - (add-instr! target (with-output-language (L15a Effect) `(restore-local-saves ,(make-live-info) ,info))) - (values target block*)] - [(return-point ,info ,rpl ,mrvl (,cnfv* ...)) - (add-instr! target (with-output-language (L15a Effect) `(return-point ,info ,rpl ,mrvl (,cnfv* ...)))) - (block-return-point! target #t) - (values target block*)] - [(rp-header ,mrvl ,fs ,lpm) - (add-instr! target (with-output-language (L15a Effect) `(rp-header ,mrvl ,fs ,lpm))) - (block-return-point! target #t) - (values target block*)] - [(shift-arg ,reg ,imm ,info) - (add-instr! target (with-output-language (L15a Effect) `(shift-arg ,(make-live-info) ,reg ,imm ,info))) - (values target block*)] - [(pariah) - (block-pariah! target #t) - (values target block*)] - [(profile ,src) - (block-src*-set! target (cons src (block-src* target))) - (values target block*)] - [(tail ,tl) (Tail tl block*)] - [(label ,l) - (block-label-set! target l) - (resolve-waiting-links! l target) - (let ([block (make-goto-block target)]) - (values block (cons block block*)))] - [(goto ,l) (add-goto-block l block*)] - [(seq ,e0 ,[block block*]) (Effect e0 block block*)] - [(set! ,[Lvalue : lvalue target -> lvalue] ,[Rhs : rhs target -> rhs]) - (add-instr! target (with-output-language (L15a Effect) `(set! ,(make-live-info) ,lvalue ,rhs))) - (values target block*)] - [(if ,p0 ,e1 ,e2) - (let ([t-block (make-goto-block target)] [f-block (make-goto-block target)] [l (make-local-label 'ej)]) - (let ([block* (cons* t-block f-block block*)]) - (block-label-set! target l) - (let-values ([(f-block block*) (Effect e2 f-block block*)]) - (let-values ([(t-block block*) (Effect e1 t-block block*)]) - (Pred p0 t-block f-block block*)))))] - [(check-live ,reg* ...) - (add-instr! target (with-output-language (L15a Effect) `(check-live ,(make-live-info) ,reg* ...))) - (values target block*)] - [else ($oops who "unexpected Effect ~s" ir)]) - (Pred : Pred (ir t-target f-target block*) -> * (block block*) - [(true) (add-true/false-block t-target block* 'lt)] - [(false) (add-true/false-block f-target block* 'lf)] - [(inline ,info ,pred-prim ,t* ...) - (let ([block (make-if-block t-target f-target)]) - (unless (block-label t-target) (block-label-set! t-target (make-local-label 'lt))) - (unless (block-label f-target) (block-label-set! f-target (make-local-label 'lf))) - (if-block-pred-set! block - (with-output-language (L15a Pred) - `(inline ,(make-live-info) ,info ,pred-prim ,(map (lambda (t) (Triv t block)) t*) ...))) - (values block (cons block block*)))] - [(seq ,e0 ,[block block*]) (Effect e0 block block*)] - [(goto ,l) (add-goto-block l block*)] - [(if ,p0 ,p1 ,[f-block block*]) - (let-values ([(t-block block*) (Pred p1 t-target f-target block*)]) - (Pred p0 t-block f-block block*))] - [(mlabel ,p (,l* ,p*) ...) - (let loop ([l* l*] [p* p*] [block* block*]) - (if (null? l*) - (Pred p t-target f-target block*) - (let-values ([(block block*) (Pred (car p*) t-target f-target block*)]) - (let ([l (car l*)]) - (resolve-waiting-links! l block) - (block-label-set! block l) - (loop (cdr l*) (cdr p*) block*)))))] - [else ($oops who "unexpected Pred ~s" ir)]) - (Tail ir '()))) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info ,max-fv (,local* ...) ,tlbody) - (let-values ([(entry-block block*) (build-graph tlbody)]) - (unless (block-label entry-block) - (let ([label (make-local-label 'entry)]) - (local-label-block-set! label entry-block) - (block-label-set! entry-block label))) - ; NB: if entry-block is not a dcl block, it must appear first in entry-block*, - ; NB: as it is the generic entry point for the procedure - (let ([entry-block* (let ([block* (fold-left - (lambda (block* dcl) - (let ([block (local-label-block dcl)]) - (if (block? block) (cons block block*) block*))) - '() (info-lambda-dcl* info))]) - (if (memq entry-block block*) block* (cons entry-block block*)))]) - ; mark reachable blocks - (for-each - (rec mark! - (lambda (from) - (unless (block-seen? from) - (block-seen! from #t) - (cond - [(goto-block? from) (mark! (goto-block-next from))] - [(joto-block? from) (mark! (joto-block-next from))] - [(if-block? from) (mark! (if-block-true from)) (mark! (if-block-false from))] - [(newframe-block? from) - (mark! (newframe-block-next from)) - (for-each mark! (newframe-block-rp* from)) - (mark! (newframe-block-rp from))] - [(tail-block? from) (void)] - [else (sorry! who "unrecognized from ~s" from)])))) - entry-block*) - ; discard unreachable blocks, some of of which build-graph stupidly produces - (let ([block* (filter block-seen? block*)]) - (for-each (lambda (block) (block-seen! block #f)) block*) - (safe-assert (andmap block-label (append entry-block* block*))) - (safe-assert (lambda (b) (eq? (local-label-block (block-label b)) b)) (append entry-block* block*)) - `(lambda ,info ,max-fv (,local* ...) (,entry-block* ...) (,block* ...)))))])) - - - (define-pass np-add-block-source! : L15a (ir) -> L15a () - (definitions - (define block-checksum - (lambda (block) - (fxlogor - (fxsll (fxlogand (length (block-effect* block)) (fxsrl (most-positive-fixnum) 3)) 3) - (cond - [(goto-block? block) #x001] - [(joto-block? block) #x010] - [(if-block? block) #x011] - [(newframe-block? block) #x100] - [(tail-block? block) #x101] - [else (sorry! who "unrecognized block ~s" block)]))))) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info ,max-fv (,local* ...) (,entry-block* ...) (,block* ...)) - (for-each - (lambda (block) - (include "types.ss") - (let ([n (fx- ($block-counter) 1)]) - ($block-counter n) - (block-pseudo-src-set! block - (make-source ($sfd) n (block-checksum block))))) - block*) - ir])) - - (define-pass np-remove-repeater-blocks! : L15a (ir) -> L15a () - (definitions - (define path-compress! - (lambda (b) - (cond - [(block-repeater? b) (goto-block-next b)] - [(and (goto-block? b) (null? (block-effect* b)) (null? (block-src* b))) - (block-repeater! b #t) - (let ([end (path-compress! (goto-block-next b))]) - (goto-block-next-set! b end) - end)] - [else b]))) - (define resolve - (lambda (b) - (if (block-repeater? b) - (goto-block-next b) - b)))) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info ,max-fv (,local* ...) (,entry-block* ...) (,block* ...)) - (for-each path-compress! block*) - (for-each - (lambda (from) - (define resolve! - (lambda (get put!) - (let ([to (get from)]) - (when (block-repeater? to) - (put! from (goto-block-next to)))))) - (cond - [(goto-block? from) - (unless (block-repeater? from) - (resolve! goto-block-next goto-block-next-set!))] - [(joto-block? from) - (resolve! joto-block-next joto-block-next-set!)] - [(if-block? from) - (resolve! if-block-true if-block-true-set!) - (resolve! if-block-false if-block-false-set!)] - [(newframe-block? from) - (resolve! newframe-block-next newframe-block-next-set!) - (newframe-block-rp*-set! from (map resolve (newframe-block-rp* from))) - (resolve! newframe-block-rp newframe-block-rp-set!)] - [(tail-block? from) (void)] - [else (sorry! who "unrecognized block ~s" from)])) - block*) - (for-each (lambda (dcl) - (let* ([b0 (local-label-block dcl)] [b (and b0 (resolve b0))]) - (unless (eq? b b0) - (local-label-block-set! dcl b) - (block-label-set! b dcl)))) - (info-lambda-dcl* info)) - `(lambda ,info ,max-fv (,local* ...) - (,(map resolve entry-block*) ...) - (,(filter (lambda (b) (or (not (block-repeater? b)) (eq? (goto-block-next b) b))) block*) ...))])) - - (define-pass np-propagate-pariahty! : L15a (ir) -> L15a () - (definitions - (define propagate! - (lambda (b) - (unless (block-seen? b) - (block-seen! b #t) - (block-pariah! b #f) - (cond - [(goto-block? b) (propagate! (goto-block-next b))] - [(joto-block? b) (propagate! (joto-block-next b))] - [(if-block? b) - ; could set likely branch direction before marking targets as pariahs, - ; but these are all pariah blocks anyway - (propagate! (if-block-true b)) - (propagate! (if-block-false b))] - [(newframe-block? b) - (propagate! (newframe-block-next b)) - (for-each propagate! (newframe-block-rp* b)) - (propagate! (newframe-block-rp b))] - [(tail-block? b) (void)] - [else (sorry! who "unrecognized block ~s" b)]))))) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info ,max-fv (,local* ...) (,entry-block* ...) (,block* ...)) - (safe-assert (not (ormap block-seen? block*))) - ; optimistically assume all blocks are pariahs, then un-pariah anything reachable from - ; the entry block without going through a known pariah block - (for-each (lambda (b) (if (block-pariah? b) (block-seen! b #t) (block-pariah! b #t))) block*) - (for-each propagate! entry-block*) - (for-each (lambda (b) (block-seen! b #f)) block*) - ir])) - - (module (np-insert-profiling) - (include "types.ss") - - (define-record-type start-block - (parent block) - (fields - (mutable link*)) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda () - ((pargs->new) '()))))) - - (define-record-type link - (fields - from - (mutable to) - (mutable weight) - (mutable mst) - (mutable counter) - (mutable op)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (from to) - (new from to 0 #f #f #f))))) - - (define-who add-link-records! - ; also adds exit-block links - (lambda (start-block exit-block entry-block* block*) - (define do-link - (lambda (from to) - (let ([link (make-link from to)]) - (block-in-link*-set! to (cons link (block-in-link* to))) - (unless (block-seen? to) - (block-seen! to #t) - (cond - [(goto-block? to) (goto-block-next-set! to (do-link to (goto-block-next to)))] - [(joto-block? to) (joto-block-next-set! to (do-link to (joto-block-next to)))] - [(if-block? to) - (if-block-true-set! to (do-link to (if-block-true to))) - (if-block-false-set! to (do-link to (if-block-false to)))] - [(tail-block? to) (tail-block-exit-set! to (do-link to exit-block))] - [(newframe-block? to) - (newframe-block-next-set! to (do-link to (newframe-block-next to))) - ; link start-block to rp blocks since they are, in reality, extra entry points that - ; need to be measured separately due to the potential for control operations - (let ([rplink* (map (lambda (rp) (do-link start-block rp)) (newframe-block-rp* to))] - [rplink (do-link start-block (newframe-block-rp to))]) - (start-block-link*-set! start-block (append rplink* (cons rplink (start-block-link* start-block)))) - ; and also record links in newframe-block for remove-link-records! - (newframe-block-rp*-set! to rplink*) - (newframe-block-rp-set! to rplink))] - [else (sorry! who "unrecognized block ~s" to)])) - link))) - (let ([all-block* (cons* start-block exit-block block*)]) - (for-each (lambda (block) (block-in-link*-set! block '())) all-block*) - (block-seen! start-block #t) - (let ([entry-link* (map (lambda (to) (do-link start-block to)) entry-block*)]) - (start-block-link*-set! start-block (append entry-link* (start-block-link* start-block))) - (for-each (lambda (block) (block-seen! block #f)) all-block*) - entry-link*)))) - - (define-who remove-link-records! - (lambda (block*) - (for-each - (lambda (block) - (cond - [(goto-block? block) (goto-block-next-set! block (link-to (goto-block-next block)))] - [(joto-block? block) (joto-block-next-set! block (link-to (joto-block-next block)))] - [(if-block? block) - (if-block-true-set! block (link-to (if-block-true block))) - (if-block-false-set! block (link-to (if-block-false block)))] - [(tail-block? block) (tail-block-exit-set! block #f)] - [(newframe-block? block) - (newframe-block-next-set! block (link-to (newframe-block-next block))) - (newframe-block-rp*-set! block (map link-to (newframe-block-rp* block))) - (newframe-block-rp-set! block (link-to (newframe-block-rp block)))] - [else (sorry! who "unrecognized block ~s" block)]) - (block-in-link*-set! block '())) - block*))) - - (define weight-graph! - (lambda (start-block exit-block block*) - (define sum-link-weights - (lambda (links) - ; using #3$fx+ to ensure that we wrap when we go over the fixnum range - (fold-left (lambda (n link) (#3%fx+ (link-weight link) n)) 0 links))) - (define-who process-link - (lambda (ls link) - (let ([block (link-to link)]) - (cond - [(block-finished? block) ls] - [(block-seen? block) ; cycle? - (link-weight-set! link 500) - ls] - [else - (block-seen! block #t) - (let ([ls (cond - [(goto-block? block) (process-link ls (goto-block-next block))] - [(joto-block? block) (process-link ls (joto-block-next block))] - [(if-block? block) (process-link (process-link ls (if-block-false block)) (if-block-true block))] - [(tail-block? block) ls] - [(newframe-block? block) (process-link ls (newframe-block-next block))] - [else (sorry! who "unrecognized block ~s" block)])]) - (block-finished! block #t) - (cons block ls))])))) - (define-who propagate-flow - (lambda (block) - (let ([sum (sum-link-weights (block-in-link* block))] - [links (cond - [(goto-block? block) (list (goto-block-next block))] - [(joto-block? block) (list (joto-block-next block))] - [(if-block? block) (list (if-block-true block) (if-block-false block))] - [(tail-block? block) (list (tail-block-exit block))] - [(newframe-block? block) (list (newframe-block-next block))] - [else (sorry! who "unrecognized block ~s" block)])]) - (safe-assert (not (null? links))) - ; AWK: we are missing the notion of those instructions that usually - ; succeed (dooverflow, dooverflood, call-error, fx+? and fx-? in - ; the original blocks.ss code) - (let-values ([(pariah* non-pariah*) - (partition (lambda (link) (block-pariah? (link-to link))) links)]) - (if (null? non-pariah*) - (divide-flow sum (length pariah*) pariah*) - (divide-flow sum (length non-pariah*) non-pariah*)))))) - (define divide-flow - (lambda (flow n ls) - (safe-assert (fx> n 0)) - (if (fx= n 1) - (link-weight-set! (car ls) flow) - (let ([x (fxquotient flow n)]) - (link-weight-set! (car ls) x) - (divide-flow (fx- flow x) (fx- n 1) (cdr ls)))))) - (let ([exit->start (goto-block-next exit-block)]) - (block-finished! start-block #t) - (block-finished! exit-block #t) - ; DFS to find cycles & determine order to propagate flow - (link-weight-set! exit->start 1000) - (for-each propagate-flow (fold-left process-link '() (start-block-link* start-block))) - (for-each (lambda (block) (block-seen! block #f)) (cons* start-block exit-block block*))))) - - (module (mst-top) - (define-who mst-top - (lambda (start-block exit-block block*) - (block-seen! start-block #t) - (block-seen! exit-block #t) - (let ([pq (pqinitialize (length block*))]) - (define (mst-in-link link) (pqupdate link (link-from link) pq)) - (define (mst-out-link link) (pqupdate link (link-to link) pq)) - ; add the exit->start link to the mst - (link-mst-set! (goto-block-next exit-block) exit-block) - (for-each mst-out-link (start-block-link* start-block)) - (let mst () - (unless (pqempty? pq) - (let ([r (pqremove pq)]) - (let ([block (cdr r)] [link (car r)]) - (link-mst-set! link block) - (for-each mst-in-link (block-in-link* block)) - (cond - [(goto-block? block) (mst-out-link (goto-block-next block))] - [(joto-block? block) (mst-out-link (joto-block-next block))] - [(if-block? block) (mst-out-link (if-block-true block)) (mst-out-link (if-block-false block))] - [(tail-block? block) (mst-out-link (tail-block-exit block))] - [(newframe-block? block) (mst-out-link (newframe-block-next block))] - [else (sorry! who "unrecognized block ~s" block)]) - (mst)))))))) - - (define pqinitialize - (let ([b (make-block)]) ;; add dummy first block in the priority-queue - (let ([l (make-link #f b)]) - (link-weight-set! l (most-positive-fixnum)) - (let ([pqfirst (cons l b)]) - (lambda (size) - (cons 0 (make-vector (fx+ size 1) pqfirst))))))) - - (define pqupheap - (lambda (heap k w) - (let ([y (vector-ref heap (fx/ k 2))]) - (if (fx> w (link-weight (car y))) - (begin - (vector-set! heap k y) - (block-seen! (cdr y) k) - (pqupheap heap (fx/ k 2) w)) - k)))) - - (define pqdownheap - (lambda (heap n k w) - (if (fx< (fx/ n 2) k) - k - (let ([j (fx* k 2)]) - (let ([y1 (vector-ref heap j)] - [y2 (and (fx< j n) (vector-ref heap (fx+ j 1)))]) - (let ([w1 (link-weight (car y1))] - [w2 (if y2 (link-weight (car y2)) (most-negative-fixnum))]) - (if (fx>= w1 w2) - (if (fx>= w w1) - k - (begin - (vector-set! heap k y1) - (block-seen! (cdr y1) k) - (pqdownheap heap n j w))) - (if (fx>= w w2) - k - (begin - (vector-set! heap k y2) - (block-seen! (cdr y2) k) - (pqdownheap heap n (fx+ j 1) w)))))))))) - - (define pqempty? - (lambda (pq) - (fx= (car pq) 0))) - - (define pqremove - (lambda (pq) - (let ([n (fx- (car pq) 1)] - [heap (cdr pq)]) - (set-car! pq n) - (let ([r (vector-ref heap 1)] - [x (vector-ref heap (fx+ n 1))]) - (let ([k (pqdownheap heap n 1 (link-weight (car x)))]) - (vector-set! heap k x) - (block-seen! (cdr x) k)) - (block-seen! (cdr r) #t) - r)))) - - (define pqupdate - (lambda (link block pq) - (let ([k (block-seen? block)]) - (cond - [(eq? k #t) (void)] - [(eq? k #f) - (let ([n (fx+ (car pq) 1)] [heap (cdr pq)]) - (set-car! pq n) - (let ([k (pqupheap heap n (link-weight link))]) - (vector-set! heap k (cons link block)) - (block-seen! block k)))] - [else - (let ([heap (cdr pq)]) - (let ([x (vector-ref heap k)] - [w (link-weight link)]) - (when (fx> w (link-weight (car x))) - (let ([k (pqupheap heap k w)]) - (vector-set! heap k (cons link block)) - (block-seen! block k)))))]))))) - - (define-who instrument - (lambda (start-block exit-block block*) - (define checks-cc? - (lambda (block) - (and (if-block? block) - (null? (block-effect* block)) - (nanopass-case (L15a Pred) (if-block-pred block) - [(inline ,live-info ,info ,pred-prim ,t* ...) (eq? pred-prim %condition-code)] - [else #f])))) - (define add-counter! - (lambda (block counter) - (define add-instr! - (lambda (block ir) - (let ([effect* (block-effect* block)]) - (block-effect*-set! block - (if (block-return-point? block) - ; rp-header / return-point form must be first - (cons* (car effect*) ir (cdr effect*)) - (cons ir effect*)))))) - (with-output-language (L15a Effect) - (add-instr! block - `(inline ,(make-live-info) ,null-info ,%inc-profile-counter - (literal ,(make-info-literal #t 'object counter (constant record-data-disp))) - (immediate 1)))))) - (define maybe-add-counter - (lambda (new* link) - (cond - [(link-counter link) => - (lambda (counter) - (let ([from (link-from link)] [to (link-to link)]) - (cond - [(and (fx= (length (block-in-link* to)) 1) (not (eq? to exit-block))) - (assert (not (checks-cc? to))) - (add-counter! to counter) - new*] - [(or (goto-block? from) (tail-block? from)) - (assert (not (checks-cc? from))) - (add-counter! from counter) - new*] - [else - (safe-assert (not (eq? to exit-block))) - (assert (not (checks-cc? to))) - (let* ([block (make-goto-block)] [l (make-link block to)]) - (let ([label (block-label to)]) - (if (and (eq? from start-block) (and (direct-call-label? label) (direct-call-label-referenced label))) - (begin - ; we're adding the new block between the (virtual) start block and one - ; of our (referenced) dcls. we need to move the dcl label to the new - ; block so the counter is incremented when we come in from the outside - (block-label-set! block label) - (local-label-block-set! label block) - (let ([label (make-local-label 'exdcl)]) - (block-label-set! to label) - (local-label-block-set! label to))) - (let ([label (make-local-label 'profile)]) - (block-label-set! block label) - (local-label-block-set! label block)))) - (link-to-set! link block) - ; set link mst for p-dot-graph/profiling's benefit - (link-mst-set! l block) - (block-in-link*-set! block (list link)) - (goto-block-next-set! block l) - (block-in-link*-set! to (cons l (remq link (block-in-link* to)))) - (add-counter! block counter) - (cons block new*))])))] - [else new*]))) - (fold-left - (lambda (new* block) - (fold-left maybe-add-counter - new* (block-in-link* block))) - block* - (cons exit-block block*)))) - - (define build-pinfo - (lambda (exit-block block*) - ; op -> counter | (plus-counter* . minus-counter*) - ; plus-counter* -> (op ...) - ; minus-counter* -> (op ...) - (define make-op - (lambda (plus minus) - ; optimize ((op) . ()) => op - (if (and (null? minus) (fx= (length plus) 1)) - (car plus) - (cons plus minus)))) - (define-who exit-ops - (lambda (block l) - (define maybe-build-op - (lambda (link ls) - (if (eq? link l) - ls - (cons (build-op link) ls)))) - (cond - [(goto-block? block) (maybe-build-op (goto-block-next block) '())] - [(joto-block? block) (maybe-build-op (joto-block-next block) '())] - [(if-block? block) (maybe-build-op (if-block-true block) (maybe-build-op (if-block-false block) '()))] - [(tail-block? block) (maybe-build-op (tail-block-exit block) '())] - [(newframe-block? block) (maybe-build-op (newframe-block-next block) '())] - [else (sorry! who "unrecognized block ~s" block)]))) - (define enter-ops - (lambda (n l) - (let ([ls (block-in-link* n)]) - (map build-op (if (not l) ls (remq l ls)))))) - (define build-op - (lambda (l) - (cond - [(link-mst l) => - (lambda (n) - (let ([op (if (eq? (link-to l) n) - (make-op (exit-ops n #f) (enter-ops n l)) - (make-op (enter-ops n #f) (exit-ops n l)))]) - (link-op-set! l op) - op))] - [else - (or (link-counter l) - (let ([counter (make-profile-counter 0)]) - (link-counter-set! l counter) - (link-op-set! l counter) - counter))]))) - (define (filter-src* block) - (cond - [(eq? ($compile-profile) 'source) (block-src* block)] - [(block-pseudo-src block) => list] - [else '()])) - (fold-left - (lambda (ls block) - (let ([src* (filter-src* block)]) - (if (null? src*) - ls - (cons (make-rblock src* (make-op (map build-op (block-in-link* block)) '())) ls)))) - '() block*))) - - (module (p-graph/profiling p-dot-graph/profiling) - (define-who block-link* - (lambda (block) - (cond - [(goto-block? block) `(,(goto-block-next block))] - [(joto-block? block) `(,(joto-block-next block))] - [(if-block? block) `(,(if-block-true block) ,(if-block-false block))] - ; leave out newframe-block => rp links, since we profiler uses its own start-block => rp links - [(newframe-block? block) `(,(newframe-block-next block))] - [(tail-block? block) `(,(tail-block-exit block))] - [(start-block? block) (start-block-link* block)] - [else (sorry! who "unrecognized block ~s" block)]))) - (define block->pretty-name - (lambda (block) - (define block->label - (lambda (block) - (let ([label (block-label block)]) - (or label - (let ([label (make-local-label 'unknown)]) - (block-label-set! block label) - label))))) - (parameterize ([print-gensym 'pretty/suffix]) (format "~s" (block->label block))))) - (define p-dot-graph/profiling - (lambda (block* exit-block p) - (define print-link - (lambda (reversed?) - (lambda (link) - (let-values ([(from to) (if reversed? - (values (link-to link) (link-from link)) - (values (link-from link) (link-to link)))]) - (display " " p) - (display (block->pretty-string from) p) - (display " -> " p) - (display (block->pretty-string to) p) - #;(when (and (block-non-tail-call? (link-from link)) (eq? (link-to link) exit-block)) - (display " [color=grey]" p)) - (if (link-mst link) - (if reversed? - (display " [color=blue]" p) - (display " [color=black]" p)) - (if reversed? - (display " [color=pink]" p) - (display " [color=red]" p))) - (write-char #\; p) - (newline p)) - ; print the tree in green - #;(when (link-mst link) - (let-values ([(from to) (if (eq? (link-mst link) (link-to link)) - (values (link-from link) (link-to link)) - (values (link-to link) (link-from link)))]) - (display " " p) - (display (block->pretty-string from) p) - (display " -> " p) - (display (block->pretty-string to) p) - (display " [color=green];\n" p)))))) - (define block->pretty-string - (lambda (block) - (list->string (subst #\_ #\. (subst #\_ #\- (string->list (block->pretty-name block))))))) - (newline p) - (display "digraph PROFILE {\n" p) - (display " node [shape = box];" p) - (let f ([block* block*] [link* '()] [in-link* '()]) - (if (null? block*) - (begin - (newline p) - (newline p) - (for-each (print-link #f) link*) - (when #f (for-each (print-link #t) in-link*)) - (display "}\n" p)) - (let ([block (car block*)]) - (display " " p) - (display (block->pretty-string block) p) - (f (cdr block*) - (append (block-link* block) link*) - (append (block-in-link* block) in-link*))))))) - (define-who p-graph/profiling - (lambda (block* name p) - (newline p) - (when name (fprintf p "~a:\n" name)) - (parameterize ([print-graph #t] [print-length 6] [print-level 3] [print-gensym 'pretty/suffix]) - (for-each - (lambda (block) - (fprintf p "~a: " (block->pretty-name block)) - (let loop ([links (block-link* block)]) - (unless (null? links) - (let ([link (car links)]) - (fprintf p "~a(~d)~a" - (block->pretty-name (link-to link)) - (link-weight link) - (if (link-mst link) - "" - "*")) - (unless (null? (cdr links)) (display ", " p)) - (loop (cdr links))))) - (fprintf p " in=~d:" (length (block-in-link* block))) - (begin - (newline p) - (for-each - (lambda (link) - (cond - [(link-counter link) (fprintf p " Bump count to ~a\n" (block->pretty-name (link-to link)))] - [(link-op link) (fprintf p " Link count to ~a computed from other counts\n" (block->pretty-name (link-to link)))]) - (fprintf p " ~a -> ~a -- ~s\n" (block->pretty-name (link-from link)) - (block->pretty-name (link-to link)) (link-op link))) - (block-link* block)) - ; We no longer have the code to report here, so we're reporting from source - (fprintf p "~{ ~s~%~}" (map unparse-L15a (block-effect* block))) - (cond - [(or (goto-block? block) (joto-block? block) (newframe-block? block) (start-block? block)) (void)] - [(if-block? block) (fprintf p " ~s~%" (unparse-L15a (if-block-pred block)))] - [(tail-block? block) (fprintf p " ~s~%" (unparse-L15a (tail-block-tail block)))] - [else (sorry! who "unrecognized block ~s" block)]))) - block*))))) - - (define-pass np-insert-profiling : L15a (ir) -> L15a () - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info ,max-fv (,local* ...) (,entry-block* ...) (,block* ...)) - (let* ([start-block (make-start-block)] - [exit-block (make-goto-block start-block)]) - (block-label-set! start-block 'start) - (block-label-set! exit-block 'exit) - (let ([entry-link* (add-link-records! start-block exit-block entry-block* block*)]) - (weight-graph! start-block exit-block block*) - (mst-top start-block exit-block block*) - (info-lambda-pinfo*-set! info (append (build-pinfo exit-block block*) (info-lambda-pinfo* info))) - ; now insert increments for counters added by build-pinfo - (let* ([block* (instrument start-block exit-block block*)] - [entry-block* (map link-to entry-link*)]) - (safe-assert (andmap (lambda (block) (not (null? (block-in-link* block)))) block*)) - (when ($assembly-output) - (let ([block* (cons start-block (append block* (list exit-block)))]) - (p-graph/profiling block* (info-lambda-name info) ($assembly-output)) - (p-dot-graph/profiling block* exit-block ($assembly-output)))) - (remove-link-records! block*) - (for-each (lambda (block) (block-seen! block #f) (block-finished! block #f)) block*) - (safe-assert (andmap block-label (append entry-block* block*))) - (safe-assert (lambda (b) (eq? (local-label-block (block-label b)) b)) (append entry-block* block*)) - `(lambda ,info ,max-fv (,local* ...) (,entry-block* ...) (,block* ...)))))]))) - - (module (p-graph p-dot-graph) - (define block->pretty-name - (lambda (block) - (define block->label - (lambda (block) - (let ([label (block-label block)]) - (or label - (let ([label (make-local-label 'unknown)]) - (block-label-set! block label) - label))))) - (parameterize ([print-gensym 'pretty/suffix]) (format "~s" (block->label block))))) - (define p-dot-graph - (lambda (block* p) - (define print-link - (lambda (link) - (display " " p) - (display (car link) p) - (display " -> " p) - (display (cdr link) p) - (write-char #\; p) - (newline p))) - (define block->pretty-string - (lambda (block) - (list->string (subst #\_ #\. (subst #\_ #\- (string->list (block->pretty-name block))))))) - (define-who block-link* - (lambda (block) - (let ([block-name (block->pretty-string block)]) - (map (lambda (x) (cons block-name (block->pretty-string x))) - (cond - [(goto-block? block) `(,(goto-block-next block))] - [(joto-block? block) `(,(joto-block-next block))] - [(if-block? block) `(,(if-block-true block) ,(if-block-false block))] - [(newframe-block? block) `(,(newframe-block-next block) ,@(newframe-block-rp* block) ,(newframe-block-rp block))] - [(tail-block? block) '()] - [else (sorry! who "unrecognized block ~s" block)]))))) - (display "digraph BLOCKS {\n" p) - (display " node [shape = box];" p) - (let f ([block* block*] [link* '()]) - (if (null? block*) - (begin - (newline p) - (newline p) - (for-each print-link link*) - (display "}\n" p)) - (let ([block (car block*)]) - (display " " p) - (display (block->pretty-string block) p) - (when (block-pariah? block) (display " [color=red]" p)) - (f (cdr block*) (append (block-link* block) link*))))))) - (define-who p-graph - (lambda (block* name p unparser) - (when name (fprintf p "\n~a:" name)) - (parameterize ([print-graph #t] [print-length 6] [print-level 3] [print-gensym 'pretty/suffix]) - (for-each - (lambda (block) - (fprintf p "~a (depth = ~s~@[, pariah~]):\n" (block->pretty-name block) (block-depth block) (block-pariah? block)) - (fprintf p "~{ ~s~%~}" (map unparser (block-effect* block))) - (cond - [(goto-block? block) (fprintf p " ~s\n" `(goto ,(block->pretty-name (goto-block-next block))))] - [(joto-block? block) (fprintf p " ~s\n" `(joto ,(block->pretty-name (joto-block-next block))))] - [(if-block? block) (fprintf p " ~s\n" `(if ,(unparser (if-block-pred block)) - (goto ,(block->pretty-name (if-block-true block))) - (goto ,(block->pretty-name (if-block-false block)))))] - [(tail-block? block) (fprintf p " ~s\n" (unparser (tail-block-tail block)))] - [(newframe-block? block) (fprintf p " ~s\n" `(goto ,(block->pretty-name (newframe-block-next block))))] - [else (sorry! who "unrecognized block ~s" block)])) - block*))))) - - (define-pass np-add-in-links! : L15a (ir) -> L15a () - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info ,max-fv (,local* ...) (,entry-block* ...) (,block* ...)) - (safe-assert (andmap (lambda (block) (eq? (block-in-link* block) '())) block*)) - (for-each - (lambda (from) - (define add-in-link! - (lambda (to) - (block-in-link*-set! to (cons from (block-in-link* to))))) - (cond - [(goto-block? from) (add-in-link! (goto-block-next from))] - [(if-block? from) (add-in-link! (if-block-true from)) (add-in-link! (if-block-false from))] - [(newframe-block? from) - (add-in-link! (newframe-block-next from)) - (for-each add-in-link! (newframe-block-rp* from)) - (add-in-link! (newframe-block-rp from))] - [(joto-block? from) (add-in-link! (joto-block-next from))] - [(tail-block? from) (void)] - [else (sorry! who "unrecognized block ~s" from)])) - block*) - ir])) - - (define-pass np-compute-loop-depth! : L15a (ir) -> L15a () - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info ,max-fv (,local* ...) (,entry-block* ...) (,block* ...)) - (safe-assert (not (ormap block-seen? block*)) (not (ormap block-finished? block*))) - (let ([lh* '()]) - (for-each - (rec f - (lambda (b) - (unless (block-finished? b) - (if (block-seen? b) - (begin - (block-loop-header! b #t) - (set! lh* (cons b lh*))) - (begin - (block-seen! b #t) - (cond - [(goto-block? b) (f (goto-block-next b))] - [(joto-block? b) (f (joto-block-next b))] - [(if-block? b) (f (if-block-true b)) (f (if-block-false b))] - [(tail-block? b) (void)] - [(newframe-block? b) - (f (newframe-block-next b)) - (for-each f (newframe-block-rp* b)) - (f (newframe-block-rp b))] - [else (sorry! who "unrecognized block ~s" b)]) - (block-seen! b #f) - (block-finished! b #t)))))) - entry-block*) - (unless (null? lh*) - (fold-left (lambda (i b) (block-index-set! b i) (fx+ i 1)) 0 lh*) - (let ([tree-size (length lh*)] [blockvec (list->vector lh*)] [lb* lh*]) - (define remove-block - (lambda (b tree) - (let ([index (block-index b)]) - (if index (tree-bit-unset tree tree-size index) tree)))) - ; invert sense of block-finished so we don't have to reset - (let ([block-finished? (lambda (b) (not (block-finished? b)))] - [block-finished! (lambda (b bool) (block-finished! b (not bool)))]) - (for-each - (rec f - (lambda (b) - (cond - [(block-finished? b) - (tree-fold-left (lambda (lhs index) - (let ([b (vector-ref blockvec index)]) - (if (block-finished? b) - lhs - (tree-bit-set lhs tree-size index)))) - tree-size empty-tree (block-loop-headers b))] - [(block-seen? b) - (safe-assert (block-index b)) - (tree-bit-set empty-tree tree-size (block-index b))] - [(tail-block? b) empty-tree] - [else - (block-seen! b #t) - (let ([lhs (remove-block b - (cond - [(goto-block? b) (f (goto-block-next b))] - [(joto-block? b) (f (joto-block-next b))] - [(if-block? b) - ; must follow same order as loop above so we find the same loop headers - (let ([lhs (f (if-block-true b))]) - (tree-merge lhs (f (if-block-false b)) tree-size))] - [(newframe-block? b) - ; must follow same order as loop above so we find the same loop headers - (fold-left (lambda (lhs b) (tree-merge lhs (f b) tree-size)) - (let ([lhs (f (newframe-block-next b))]) (tree-merge lhs (f (newframe-block-rp b)) tree-size)) - (newframe-block-rp* b))] - [else (sorry! who "unrecognized block ~s" b)]))]) - (unless (or (block-loop-header? b) (eqv? (block-loop-headers b) empty-tree)) - (set! lb* (cons b lb*))) - (block-seen! b #f) - (block-finished! b #t) - (block-loop-headers-set! b lhs) - lhs)]))) - ; seems like we should be able to use (reverse lh*) rather than entry-block* here - ; but we end up finding different loop headers in some cases - entry-block*)) - (for-each - (rec g - (lambda (b) - (if (block-seen? b) - (block-depth b) - (begin - (block-seen! b #t) - (let ([depth (tree-fold-left (lambda (depth index) (fxmax (g (vector-ref blockvec index)) depth)) - tree-size 0 (block-loop-headers b))]) - (let ([depth (if (block-loop-header? b) (fx+ depth 1) depth)]) - (block-depth-set! b depth) - depth)))))) - lb*)) - (for-each (lambda (b) (block-seen! b #f)) block*) - #;(p-dot-graph block* (current-output-port)) - #;(p-graph block* (info-lambda-name info) (current-output-port) unparse-L15a))) - (for-each (lambda (b) (block-finished! b #f)) block*) - ir])) - - (define-pass np-weight-references! : L15a (ir) -> L15a () - (definitions - (define weight-block! - (lambda (max-weight) - (lambda (block weight) - (let ([weight (if (and weight (not (fl= max-weight 0.0))) - (flonum->fixnum (fl/ weight (fl/ max-weight 1024.0))) - (if (block-pariah? block) - 0 - (expt 4 (fxmin (block-depth block) 5))))]) - (block-weight-set! block weight) - (unless (fx= weight 0) - (let () - (define fixnum (lambda (x) (if (fixnum? x) x (most-positive-fixnum)))) - ; refs and sets are weighted equally - (define process-var - (lambda (x) - (when (uvar? x) - (uvar-ref-weight-set! x (fixnum (+ (uvar-ref-weight x) weight)))))) - (define Lvalue - (lambda (lvalue) - (nanopass-case (L15a Lvalue) lvalue - [,x (process-var x)] - [(mref ,x1 ,x2 ,imm) (process-var x1) (process-var x2)]))) - (define Triv - (lambda (t) - (nanopass-case (L15a Triv) t - [,lvalue (Lvalue lvalue)] - [else (void)]))) - (define Rhs - (lambda (rhs) - (nanopass-case (L15a Rhs) rhs - [,lvalue (Lvalue lvalue)] - [(inline ,info ,value-prim ,t* ...) - (for-each Triv t*)] - [else (void)]))) - (define Pred - (lambda (p) - (nanopass-case (L15a Pred) p - [(inline ,live-info ,info ,pred-prim ,t* ...) - (for-each Triv t*)] - [else (sorry! who "unexpected pred ~s" p)]))) - (define Tail - (lambda (tl) - (nanopass-case (L15a Tail) tl - [(jump ,live-info ,t (,var* ...)) (Triv t)] - [else (void)]))) - (for-each - (lambda (instr) - (nanopass-case (L15a Effect) instr - [(set! ,live-info ,lvalue ,rhs) (Lvalue lvalue) (Rhs rhs)] - [(inline ,live-info ,info ,effect-prim ,t* ...) - (for-each Triv t*)] - [else (void)])) - (block-effect* block)) - (cond - [(or (goto-block? block) (joto-block? block)) (void)] - [(if-block? block) (Pred (if-block-pred block))] - [(newframe-block? block) - (let ([newframe-info (newframe-block-info block)]) - (info-newframe-weight-set! newframe-info - (fixnum (+ (info-newframe-weight newframe-info) weight))))] - [(tail-block? block) (Tail (tail-block-tail block))] - [else (sorry! who "unrecognized block ~s" block)])))))))) - ; now know for each block its loop nesting depth and pariahty - ; now weight calls and refs accordingly - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info ,max-fv (,local* ...) (,entry-block* ...) (,block* ...)) - (if ($profile-block-data?) - (let* ([weight* (map (lambda (block) - (let ([psrc (block-pseudo-src block)]) - (and psrc (profile-query-weight psrc)))) - block*)] - [max-weight (fold-left (lambda (m block weight) - (if weight (flmax m weight) m)) - 0.0 block* weight*)]) - (for-each (weight-block! max-weight) block* weight*)) - (let ([wb (weight-block! #f)]) - (for-each (lambda (block) (wb block #f)) block*))) - ir])) - - ; this must come before np-allocate-registers since asm-module is imported - ; by the included file -instructions.ss - (module (np-generate-code asm-module) - (define-threaded aop) - (define-threaded funcrel*) - (define-threaded current-func) - (define make-funcrel - (lambda (reloc l offset) - (let ([stuff (list offset l)]) - (set! funcrel* (cons stuff funcrel*)) - (cons reloc stuff)))) - ; TODO: generate code forward => backward and thread through a machine-state - ; record that says what each register contains, including the condition-code - ; register, so that we can avoid redundant loads and tests. For example, - ; second set! of td in (seq (set! td ,(%mref tc 20)) ... (set! td ,(%mref tc 20))) - ; should go away with no intervening assignment of td or tc[20]. Similarly, - ; in (seq (mset! tc 36 (incr ,(%mref tc 36))) (if (eq? ,(%mref tc 36) 0) L1 L2), - ; the test should reduce to a check of the 'z' flag. - ; plain chunks arise only as the destination for a rachunk - (define-record-type chunk - (nongenerative) - (fields size code*) - (protocol - (lambda (new) - (lambda (code*) (new (asm-size* code*) code*))))) - (define-record-type lchunk - (parent chunk) - (nongenerative) - (sealed #t) - (fields l) - (protocol - (lambda (pargs->new) - (lambda (l code*) - ((pargs->new code*) l))))) - (define-record-type gchunk - (parent chunk) - (nongenerative) - (sealed #t) - (fields l laddr next-offset) - (protocol - (lambda (pargs->new) - (lambda (l next-offset code*) - ((pargs->new code*) l (local-label-offset l) next-offset))))) - (define-record-type cgchunk - (parent chunk) - (nongenerative) - (sealed #t) - (fields info l1 l2 laddr1 laddr2 next-offset) - (protocol - (lambda (pargs->new) - (lambda (info l1 l2 next-offset code*) - (define label-offset - (lambda (l) - (and (local-label? l) (local-label-offset l)))) - ((pargs->new code*) info l1 l2 (label-offset l1) (label-offset l2) next-offset))))) - ; rachunks arise only during code generation to support machines like the ARM that determine - ; return addresses for Scheme calls using pc-relative add or lea instructions - (define-record-type rachunk - (parent chunk) - (nongenerative) - (sealed #t) - (fields dest l incr-offset laddr next-offset) - (protocol - (lambda (pargs->new) - (lambda (dest l incr-offset next-offset code*) - ((pargs->new code*) dest l incr-offset (local-label-offset l) next-offset))))) - - (define-pass np-generate-code : L16 (ir) -> * (code) - (definitions - (define munge-recur?) - (define c-trace - ; copied from compile.ss - (lambda (name size trace-list p) - (when p - (newline p) - (when name (fprintf p "~a: ~%" name)) - (parameterize ([print-length 5] [print-level 3] [print-gensym 'pretty/suffix]) - (let dump ([trace-list trace-list] [last-addr size]) - (when (pair? trace-list) - (apply (lambda (addr op . args) - (if (eq? op 'label) - (begin - (fprintf p "~{~s~^, ~}:\n" addr) - (dump (cdr trace-list) last-addr)) - (begin - (fprintf p "~d:~9t~a~24t" (- size last-addr) op) - (do ((args args (cdr args))) - ((null? args)) - (let ([arg (car args)]) - (if (string? arg) (display arg p) (write arg p))) - (unless (null? (cdr args)) (display ", " p))) - (newline p) - (dump (cdr trace-list) addr)))) - (car trace-list))))) - (fprintf p "~d:~9t\n" size name)))) - ; munge gets the code in forward order, but really wants to process it - ; backwards to find the label offsets. Maybe the size would be better - ; tracked by doing it more like cp2 does right now and then patching in - ; the forward jumps and tightening up the code. - (define-who munge - (lambda (c* size) - (define (munge-pass c* iteration) - (define get-local-label-offset - (lambda (l) - (local-label-iteration-set! l iteration) - (local-label-offset l))) - (let f ([rc* (reverse c*)] [c* '()] [offset 0]) - (if (null? rc*) - (values c* offset) - (let ([c (car rc*)] [rc* (cdr rc*)]) - (cond - [(lchunk? c) - (let ([l (lchunk-l c)] [offset (fx+ offset (chunk-size c))]) - (when l - (unless (eq? (get-local-label-offset l) offset) - (local-label-offset-set! l offset) - (when (fx= (local-label-iteration l) iteration) - (set! munge-recur? #t)))) - (f rc* (cons c c*) offset))] - [(gchunk? c) - (let ([l (gchunk-l c)]) - (if (and (eq? (get-local-label-offset l) (gchunk-laddr c)) - (eq? (gchunk-next-offset c) offset)) - (f rc* (cons c c*) (fx+ offset (chunk-size c))) - (let ([c (asm-jump l offset)]) - (f rc* (cons c c*) (fx+ offset (chunk-size c))))))] - [(cgchunk? c) - (let ([l1 (cgchunk-l1 c)] [l2 (cgchunk-l2 c)]) - (if (and (or (libspec-label? l1) (eq? (get-local-label-offset l1) (cgchunk-laddr1 c))) - (or (libspec-label? l2) (eq? (get-local-label-offset l2) (cgchunk-laddr2 c))) - (eq? (cgchunk-next-offset c) offset)) - (f rc* (cons c c*) (fx+ offset (chunk-size c))) - (let ([c (asm-conditional-jump (cgchunk-info c) l1 l2 offset)]) - (f rc* (cons c c*) (fx+ offset (chunk-size c))))))] - [(rachunk? c) - (let ([c (let ([l (rachunk-l c)]) - (if (and (eq? (get-local-label-offset l) (rachunk-laddr c)) - (eq? (rachunk-next-offset c) offset)) - c - (asm-return-address (rachunk-dest c) l (rachunk-incr-offset c) offset)))]) - (f rc* (cons c c*) (fx+ offset (chunk-size c))))] - ; NB: generic test, so must be last! - [(chunk? c) (f rc* (cons c c*) (fx+ offset (chunk-size c)))] - [else (sorry! who "unexpected chunk ~s" c)]))))) - (define (asm-fixup-opnd x) - (define-syntax tc-offset-map - (let ([q (datum->syntax #'* - (map (lambda (x) (cons (caddr x) (string->symbol (format "$~s" (car x))))) - (getprop 'tc '*fields*)))]) - (lambda (x) #`'#,q))) - (if (pair? x) - (record-case x - [(library) (x) `(library ,(libspec-name x))] - [(library-code) (x) `(library-code ,(libspec-name x))] - [(entry) (i) `(entry ,(vector-ref (constant c-entry-name-vector) i))] - [(disp) (offset reg) - (cond - [(and (eq? reg %tc) (assv offset tc-offset-map)) => cdr] - [else `(disp ,offset ,(reg-name reg))])] - [(index) (offset reg1 reg2) - `(index ,offset ,(reg-name reg1) ,(reg-name reg2))] - [(reg) r (reg-name r)] - [(label) (offset l) - (if (local-label? l) - (parameterize ([print-gensym 'pretty/suffix]) - (format "~s(~d)" l offset)) - (format "~s" l))] - [else x]) - x)) - (define (extract-trace-code code*) - (let-values ([(trace* size) - (let f ([code* code*]) - (if (null? code*) - (values '() 0) - (let ([code (car code*)]) - (let-values ([(trace* offset) (f (cdr code*))]) - (record-case code - [(asm) (op . opnd*) - (values - `((,offset ,op ,@(map asm-fixup-opnd opnd*)) ,@trace*) - offset)] - [(label) l* - (values - (if (null? l*) - trace* - `((,l* label) ,@trace*)) - offset)] - [else (values trace* (fx+ (asm-size code) offset))])))))]) - trace*)) - (define (extract-code c*) - (let f ([c* c*]) - (if (null? c*) - '() - (let ([c (car c*)]) - (let ([code (append (chunk-code* (car c*)) (f (cdr c*)))]) - (if (and aop (lchunk? c)) - (let ([l (lchunk-l c)]) - (if l (cons `(label ,l) code) code)) - code)))))) - (let f ([c* c*] [size size] [iteration 2]) - (if munge-recur? - (begin - (set! munge-recur? #f) - (let-values ([(c* new-size) (munge-pass c* iteration)]) - (f c* new-size (fx+ iteration 1)))) - (let ([code* (extract-code c*)]) - (if aop - (values - (remp (lambda (code) (record-case code [(asm label) stuff #t] [else #f])) code*) - (extract-trace-code code*) - size) - (values code* '() size))))))) - ; TODO: teach c-mkcode & c-faslcode how to indirect labels - (define-who resolve-funcrel! - (lambda (funcrel) - (let* ([l (cadr funcrel)] [code ($c-func-code-record (local-label-func l))]) - (record-case code - [(code) (func subtype free name arity-mask size code-list info) - (set-car! - funcrel - (let ([offset (local-label-offset l)]) - (if offset - (fx+ (fx- size offset) (car funcrel) (constant code-data-disp)) - (car funcrel)))) - (set-car! (cdr funcrel) code)] - [else (sorry! who "unexpected record ~s" code)])))) - (define touch-label! - (lambda (l) - (unless (libspec-label? l) (local-label-iteration-set! l 1)))) - (define LambdaBody - (lambda (entry-block* block* func) - #;(when (#%$assembly-output) - (p-dot-graph block* (current-output-port)) - (p-graph block* 'whatever (current-output-port) unparse-L16)) - (let ([block* (cons (car entry-block*) (remq (car entry-block*) block*))]) - (for-each (lambda (block) (let ([l (block-label block)]) (when l (local-label-iteration-set! l 0) (local-label-func-set! l func)))) block*) - (fluid-let ([current-func func]) - (let loop ([block* (reverse block*)] [chunk* '()] [offset 0]) - (if (null? block*) - (munge chunk* offset) - (let ([block (car block*)]) - (let-values ([(code* chunk* offset) (Block block chunk* offset)]) - (let ([chunk (make-lchunk (block-label block) code*)]) - (let ([offset (fx+ (chunk-size chunk) offset)]) - (let ([l (block-label block)]) - (when l - (local-label-offset-set! l offset) - (when (fx= (local-label-iteration l) 1) (set! munge-recur? #t)))) - (loop (cdr block*) (cons chunk chunk*) offset))))))))))) - (define Block - (lambda (block chunk* offset) - (let f ([e* (block-effect* block)]) - (if (null? e*) - (Exit block chunk* offset) - (let-values ([(code* chunk* offset) (f (cdr e*))]) - (Effect (car e*) code* chunk* offset)))))) - (define Exit - (lambda (block chunk* offset) - (define do-goto - (lambda (b) - (let ([l (block-label b)]) - (safe-assert l) - (touch-label! l) - (let ([chunk (asm-jump l offset)]) - (values '() (cons chunk chunk*) (fx+ (chunk-size chunk) offset)))))) - (cond - [(goto-block? block) (do-goto (goto-block-next block))] - [(joto-block? block) (do-goto (joto-block-next block))] - [(if-block? block) - (let ([l1 (block-label (if-block-true block))] [l2 (block-label (if-block-false block))]) - (safe-assert l1 l2) - (touch-label! l1) - (touch-label! l2) - (let-values ([(code* chunk) (Pred (if-block-pred block) l1 l2 offset)]) - (values code* (cons chunk chunk*) (fx+ (chunk-size chunk) offset))))] - [(tail-block? block) (Tail (tail-block-tail block) chunk* offset)] - [(newframe-block? block) (do-goto (newframe-block-next block))] - [else (sorry! who "unrecognized block ~s" block)])))) - (Tail : Tail (ir chunk* offset) -> * (code* chunk* offset) - [(asm-return) (values (asm-return) chunk* offset)] - [(asm-c-return ,info) (values (asm-c-return info) chunk* offset)] - [(jump (label-ref ,l ,offset0)) - (values (asm-direct-jump l offset0) chunk* offset)] - [(jump (literal ,info)) - (values (asm-literal-jump info) chunk* offset)] - [(jump ,t) - (values (asm-indirect-jump t) chunk* offset)] - [(goto ,l) - (safe-assert (libspec-label? l)) - (values (asm-library-jump l) chunk* offset)]) - (Program : Program (ir) -> * (code) - [(labels ([,l* ,[Lambda->func : le* -> func*]] ...) ,l) - (define-syntax traceit - (syntax-rules (x) - [(_ name) (set! name (let ([t name]) (lambda args (apply t args))))])) - (fluid-let ([funcrel* '()] [aop ($assembly-output)] [munge-recur? #f]) - (for-each local-label-func-set! l* func*) - (let ([ptrace* (map CaseLambdaExpr le* func*)]) - (for-each resolve-funcrel! funcrel*) - (when aop - (for-each (lambda (ptrace) (ptrace aop)) ptrace*) - (flush-output-port aop)) - (local-label-func l)))]) - (Lambda->func : CaseLambdaExpr (ir) -> * (func) - [(lambda ,info (,entry-block* ...) (,block* ...)) (make-$c-func)]) - ; the final version of code* (which has things resolved) - (CaseLambdaExpr : CaseLambdaExpr (ir func) -> * () - [(lambda ,info (,entry-block* ...) (,block* ...)) - #;(let () - (define block-printer - (lambda (unparser name block*) - (p-dot-graph block* (current-output-port)) - (p-graph block* name (current-output-port) unparser))) - (block-printer unparse-L16 (info-lambda-name info) block*)) - (let-values ([(code* trace* code-size) (LambdaBody entry-block* block* func)]) - ($c-make-code - func - (info-lambda-flags info) - (length (info-lambda-fv* info)) - (info-lambda-name info) - (interface*->mask (info-lambda-interface* info)) - code-size - code* - (cond - [(info-lambda-ctci info) => - (lambda (ctci) - (include "types.ss") - (make-code-info - (info-lambda-src info) - (info-lambda-sexpr info) - (and (eq? (info-lambda-closure-rep info) 'closure) - (let f ([fv* (info-lambda-fv* info)] [n 0]) - (if (null? fv*) - (make-vector n #f) - (let ([v (f (cdr fv*) (fx+ n 1))]) - (cond - [(uvar-source (car fv*)) => - (lambda (source) (vector-set! v n (unannotate source)))]) - v)))) - (ctci-live ctci) - (let ([v (vector-map - (let ([n (fx+ (constant code-data-disp) (constant size-rp-header) code-size)]) - (lambda (ctrpi) - (make-rp-info - (fx- n (local-label-offset (ctrpi-label ctrpi))) - (ctrpi-src ctrpi) - (ctrpi-sexpr ctrpi) - (ctrpi-mask ctrpi)))) - (list->vector (ctci-rpi* ctci)))]) - (vector-sort! (lambda (x y) (fx< (rp-info-offset x) (rp-info-offset y))) v) - v)))] - [(and (generate-procedure-source-information) - (info-lambda-src info)) => - (lambda (src) - (include "types.ss") - (make-code-info src #f #f #f #f))] - [else #f]) - (info-lambda-pinfo* info)) - (lambda (p) (c-trace (info-lambda-name info) code-size trace* p)))]) - (Effect : Effect (ir code* chunk* offset) -> * (code* chunk* offset) - [(rp-header ,mrvl ,fs ,lpm) (values (asm-rp-header code* mrvl fs lpm current-func #f) chunk* offset)] - [(set! ,x (label-ref ,l ,offset1)) - (guard (eq? (local-label-func l) current-func)) - (let ([chunk (make-chunk code*)]) - (let ([offset (fx+ (chunk-size chunk) offset)] [chunk* (cons chunk chunk*)]) - (let ([chunk (asm-return-address x l offset1 offset)]) - (values '() (cons chunk chunk*) (fx+ (chunk-size chunk) offset)))))] - [(set! ,lvalue (asm ,info ,proc ,t* ...)) (values (apply proc code* lvalue t*) chunk* offset)] - [(set! ,lvalue ,rhs) (values (asm-move code* lvalue rhs) chunk* offset)] - [(asm ,info ,proc ,t* ...) (values (apply proc code* t*) chunk* offset)]) - (Pred : Pred (ir l1 l2 offset) -> * (code* chunk) - [(asm ,info ,proc ,t* ...) (apply proc l1 l2 offset t*)]) - (Program ir)) - - (define-pass Triv->rand : (L16 Triv) (ir) -> * (operand) - (Triv : Triv (ir) -> * (operand) - [,x (cons 'reg x)] - [(mref ,x1 ,x2 ,imm) - (if (eq? x2 %zero) - `(disp ,imm ,x1) - `(index ,imm ,x2 ,x1))] - [(literal ,info) - `(,(if (info-literal-indirect? info) 'literal@ 'literal) - ,(info-literal-offset info) - ,(let ([type (info-literal-type info)]) - (if (eq? type 'closure) - ($c-make-closure (local-label-func (info-literal-addr info))) - `(,type ,(info-literal-addr info)))))] - [(immediate ,imm) `(imm ,imm)] - [(label-ref ,l ,offset) (make-funcrel 'literal l offset)]) - (Triv ir)) - - (define build-mem-opnd - (lambda (base index offset) - (let ([offset (nanopass-case (L16 Triv) offset [(immediate ,imm) imm])]) - (if (eq? index %zero) - `(disp ,offset ,base) - `(index ,offset ,base ,index))))) - - (define asm-size* - (lambda (x*) - (fold-left (lambda (size x) (fx+ size (asm-size x))) 0 x*))) - - (define-syntax Trivit - (syntax-rules () - [(_ (x ...) b0 b1 ...) (let ([x (Triv->rand x)] ...) b0 b1 ...)])) - - (define-syntax aop-cons* - (syntax-rules () - [(_ asm e1 e2 ...) - (let ([ls (cons* e1 e2 ...)]) - (if aop (cons asm ls) ls))])) - - (define interface*->mask - (lambda (i*) - (fold-left (lambda (mask i) - (logor mask - (if (< i 0) - (- (ash 1 (- -1 i))) - (ash 1 i)))) - 0 i*))) - - (architecture assembler) - - (import asm-module)) - - (module (np-allocate-registers) - (define-threaded spillable*) - (define-threaded unspillable*) - (define-threaded max-fv) - (define-threaded max-fs@call) - (define-threaded poison-cset) - - (define no-live* empty-tree) - - (define union-live - ; union live1 and live2. result is eq? to live1 if result is same as live1. - (lambda (live1 live2 live-size) - (tree-merge live1 live2 live-size))) - - (define same-live? - (lambda (live1 live2) - (tree-same? live1 live2))) - - (define live? - (lambda (live* live-size x) - (tree-bit-set? live* live-size (var-index x)))) - - (define get-live-vars - (lambda (live* live-size v) - (tree-extract live* live-size v))) - - (define make-add-var - (lambda (live-size) - ; add x to live*. result is eq? to live* if x is already in live*. - (lambda (live* x) - (let ([index (var-index x)]) - (if index - (let ([new (tree-bit-set live* live-size index)]) - (safe-assert (or (eq? new live*) (not (tree-same? new live*)))) - new) - live*))))) - - (define make-remove-var - ; remove x from live*. result is eq? to live* if x is not in live*. - (lambda (live-size) - (lambda (live* x) - (let ([index (var-index x)]) - (if index - (let ([new (tree-bit-unset live* live-size (var-index x))]) - (safe-assert (or (eq? new live*) (not (tree-same? new live*)))) - new) - live*))))) - - (module (make-empty-cset make-full-cset cset-full? conflict-bit-set! conflict-bit-unset! conflict-bit-set? conflict-bit-count cset-merge! cset-copy cset-for-each extract-conflicts) - (define-record-type cset - (nongenerative) - (fields size (mutable tree))) - - (define make-empty-cset - (lambda (size) - (make-cset size empty-tree))) - - (define make-full-cset - (lambda (size) - (make-cset size full-tree))) - - (define cset-full? - (lambda (cset) - (eq? (cset-tree cset) full-tree))) - - (define conflict-bit-set! - (lambda (cset offset) - (cset-tree-set! cset - (tree-bit-set (cset-tree cset) (cset-size cset) offset)))) - - (define conflict-bit-unset! - (lambda (cset offset) - (cset-tree-set! cset - (tree-bit-unset (cset-tree cset) (cset-size cset) offset)))) - - (define conflict-bit-set? - (lambda (cset offset) - (tree-bit-set? (cset-tree cset) (cset-size cset) offset))) - - (define conflict-bit-count - (lambda (cset) - (tree-bit-count (cset-tree cset) (cset-size cset)))) - - (define cset-merge! - (lambda (cset1 cset2) - (cset-tree-set! cset1 (tree-merge (cset-tree cset1) (cset-tree cset2) (cset-size cset1))))) - - (define cset-copy - (lambda (cset) - (make-cset (cset-size cset) (cset-tree cset)))) - - (define cset-for-each - (lambda (cset proc) - (tree-for-each (cset-tree cset) (cset-size cset) 0 (cset-size cset) proc))) - - (define extract-conflicts - (lambda (cset v) - (tree-extract (cset-tree cset) (cset-size cset) v))) - ) - - (define do-live-analysis! - (lambda (live-size entry-block*) - (define add-var (make-add-var live-size)) - (define remove-var (make-remove-var live-size)) - (define-who scan-block - ; if we maintain a list of kills and a list of useless variables for - ; each block, and we discover on entry to scan-block that the useless - ; variables are still useless (not live in "out"), we can compute the - ; new in set without scanning the block by removing the kills from - ; the out set and unioning the result with the saved in set. should - ; try this and see if it is enough of a win to justify the added - ; complexity. - (lambda (block out) - (define Triv - (lambda (out t) - (nanopass-case (L15a Triv) t - [(mref ,x1 ,x2 ,imm) (add-var (add-var out x2) x1)] - [,x (add-var out x)] - [else out]))) - (define Rhs - (lambda (out rhs) - (nanopass-case (L15a Rhs) rhs - [(inline ,info ,value-prim ,t* ...) - (let* ([out (if (info-kill*? info) (fold-left remove-var out (info-kill*-kill* info)) out)] - [out (if (info-kill*-live*? info) (fold-left add-var out (info-kill*-live*-live* info)) out)]) - (fold-left Triv out t*))] - [else (Triv out rhs)]))) - (define Pred - (lambda (out p) - (nanopass-case (L15a Pred) p - [(inline ,live-info ,info ,pred-prim ,t* ...) - (let* ([out (if (info-kill*? info) (fold-left remove-var out (info-kill*-kill* info)) out)] - [out (if (info-kill*-live*? info) (fold-left add-var out (info-kill*-live*-live* info)) out)]) - (live-info-live-set! live-info out) - (fold-left Triv out t*))] - [else (sorry! who "unexpected pred ~s" p)]))) - (define Tail - (lambda (out tl) - (nanopass-case (L15a Tail) tl - [(goto ,l) - (safe-assert (libspec-label? l)) - (fold-left add-var no-live* (libspec-label-live-reg* l))] - [(asm-return ,reg* ...) - (safe-assert (eq? out no-live*)) - (fold-left add-var no-live* reg*)] - [(asm-c-return ,info ,reg* ...) - (safe-assert (eq? out no-live*)) - (fold-left add-var no-live* reg*)] - [(jump ,live-info ,t (,var* ...)) - (let ([out (fold-left add-var out var*)]) - (live-info-live-set! live-info out) - (Triv out t))] - [else (sorry! who "unexpected tail instruction ~s" tl)]))) - (define Effect* - (lambda (out instr*) - (fold-left - (lambda (out instr) - (nanopass-case (L15a Effect) instr - [(set! ,live-info ,x ,rhs) - (if (var-index x) - (let ([new-out (remove-var out x)]) - (if (and (eq? new-out out) - (nanopass-case (L15a Rhs) rhs - [(inline ,info ,value-prim ,t* ...) (primitive-pure? value-prim)] - [else #t])) - (begin - (live-info-useless-set! live-info #t) - out) - (begin - (live-info-useless-set! live-info #f) - (live-info-live-set! live-info new-out) - (Rhs new-out rhs)))) - (begin - (live-info-live-set! live-info out) - (Rhs out rhs)))] - [(set! ,live-info (mref ,x1 ,x2 ,imm) ,rhs) - (live-info-live-set! live-info out) - (Rhs (add-var (add-var out x1) x2) rhs)] - [(inline ,live-info ,info ,effect-prim ,t* ...) - (let ([out (if (info-kill*? info) (fold-left remove-var out (info-kill*-kill* info)) out)]) - (live-info-live-set! live-info out) - (let ([out (fold-left Triv out t*)]) - (if (info-kill*-live*? info) - (fold-left add-var out (info-kill*-live*-live* info)) - out)))] - [(remove-frame ,live-info ,info) (live-info-live-set! live-info out) out] - [(restore-local-saves ,live-info ,info) (live-info-live-set! live-info out) out] - [(shift-arg ,live-info ,reg ,imm ,info) (live-info-live-set! live-info out) out] - [(overflow-check ,live-info) (live-info-live-set! live-info out) out] - [(overflood-check ,live-info) (live-info-live-set! live-info out) out] - [(fcallable-overflow-check ,live-info) (live-info-live-set! live-info out) out] - [(check-live ,live-info ,reg* ...) (live-info-live-set! live-info out) out] - [else out])) - out instr*))) - ; NB: consider storing instructions in reverse order back in expose-basic-blocks - (let ([effect* (reverse (block-effect* block))]) - (cond - [(or (goto-block? block) (joto-block? block) (newframe-block? block)) (Effect* out effect*)] - [(if-block? block) (Effect* (Pred out (if-block-pred block)) effect*)] - [(tail-block? block) (Effect* (Tail out (tail-block-tail block)) effect*)] - [else (sorry! who "unrecognized block ~s" block)])))) - (define force-live-in! - (lambda (block) - (when (eq? (block-live-in block) 'uninitialized) - (if (block-seen? block) - ; think we need need not recur on in-link* here even though we changed in - ; - if an in-link is seen, it's already on the worklist - ; - if an in-link is not seen, we must not have visited it yet or it would - ; have already forced us. someone will visit it later unless it's - ; orphaned, and we think we have no orphaned blocks - (block-live-in-set! block no-live*) - (begin - (block-seen! block #t) - (do-live! block)))))) - (define different? - (lambda (out old-out) - (or (eq? old-out 'uninitialized) - (not (same-live? out old-out))))) - (define propagate-live! - (lambda (block out) - ; NB: could record out, and if out hasn't changed, skip the scan - (let ([in (scan-block block out)]) - (when (different? in (block-live-in block)) - (block-live-in-set! block in) - (let f ([block* (block-in-link* block)]) - (unless (null? block*) - (let ([block (car block*)]) - (if (block-seen? block) - (f (cdr block*)) - (begin - (block-seen! block #t) - (f (cdr block*)) - (do-live! block)))))))))) - (define-who do-live! - (lambda (block) - (safe-assert (block-seen? block)) - (cond - [(goto-block? block) - (let ([next-block (goto-block-next block)]) - (force-live-in! next-block) - (block-seen! block #f) - (propagate-live! block (block-live-in next-block)))] - [(if-block? block) - (let ([true-block (if-block-true block)] [false-block (if-block-false block)]) - (force-live-in! true-block) - (force-live-in! false-block) - (block-seen! block #f) - (let ([out (union-live (block-live-in true-block) (block-live-in false-block) live-size)]) - (when (different? out (if-block-live-out block)) - (if-block-live-out-set! block out) - (propagate-live! block out))))] - [(joto-block? block) - (let ([next-block (joto-block-next block)]) - (force-live-in! next-block) - (block-seen! block #f) - (propagate-live! block - (let loop ([nfv* (joto-block-nfv* block)] [i 1] [next (block-live-in next-block)]) - (if (or (null? nfv*) (fx> i max-fv)) - next - (loop (cdr nfv*) (fx+ i 1) - (let ([new-next (remove-var next (get-fv i))]) - (if (eq? new-next next) - next - (add-var next (car nfv*)))))))))] - [(newframe-block? block) - (let ([next-block (newframe-block-next block)] - [rp-block* (newframe-block-rp* block)] - [rp-block (newframe-block-rp block)]) - (force-live-in! next-block) - (for-each force-live-in! rp-block*) - (force-live-in! rp-block) - (block-seen! block #f) - (let ([rp (block-live-in rp-block)] [newframe-info (newframe-block-info block)]) - (let ([call (if (eq? (newframe-block-live-rp block) rp) - (newframe-block-live-call block) - (begin - (newframe-block-live-rp-set! block rp) - (let ([call (add-var - (fold-left - (lambda (live* x*) (fold-left remove-var live* x*)) - rp - (cons* - ; could base set of registers to kill on expected return values - (reg-cons* %ret %ac0 arg-registers) - (info-newframe-cnfv* newframe-info) - (info-newframe-nfv** newframe-info))) - (get-fv 0))]) - (newframe-block-live-call-set! block call) - call)))]) - (let ([out (union-live - (fold-left (lambda (live b) (union-live (block-live-in b) live live-size)) - (block-live-in next-block) rp-block*) - (fold-left add-var call (info-newframe-cnfv* newframe-info)) - live-size)]) - (when (different? out (newframe-block-live-out block)) - (newframe-block-live-out-set! block out) - (propagate-live! block out))))))] - [(tail-block? block) - (block-seen! block #f) - (propagate-live! block no-live*)] - [else (sorry! who "unrecognized block ~s" block)]))) - (for-each - (lambda (entry-block) - (when (eq? (block-live-in entry-block) 'uninitialized) - (block-seen! entry-block #t) - (do-live! entry-block))) - entry-block*))) - - (define-who check-entry-live! - ; when enabled, spits out messages about uvars and unexpected registers that are live - ; on entry. there should never be any live uvars. for procedures that started life - ; as ordinary lambda expressions, there shouldn't be anything but ac0, cp, and argument - ; registers, which we weed out here. for library routines, there are often additional - ; registers, sometimes for good reason and sometimes because we are lazy and didn't give - ; ourselves a mechanism to prune out unneeded saves and restores. for foreign-callable - ; procedures, C argument registers and callee-save registers might show up live. - ; we could enable a variant of this always that just checks normal procedures. also, - ; it might be nice to make it a bit more efficient, though it probably doesn't matter. - (lambda (name live-size varvec entry-block*) - (for-each - (lambda (entry-block) - (define okay-live? - (lambda (x) - (or (fv? x) - (eq? x %ac0) - (meta-cond - [(real-register? '%cp) (eq? x %cp)] - [else #f]) - (memq x arg-registers)))) - (let ([undead (remp okay-live? (get-live-vars (block-live-in entry-block) live-size varvec))]) - (unless (null? undead) - (printf "Warning: live on entry to ~a: ~s\n" name undead)))) - entry-block*))) - - (define-who record-call-live! - (lambda (block* varvec) - (for-each - (lambda (block) - (when (newframe-block? block) - (let ([newframe-info (newframe-block-info block)]) - (let ([call-live* (get-live-vars (newframe-block-live-call block) (vector-length varvec) varvec)]) - (for-each - (lambda (x) - (define fixnum (lambda (x) (if (fixnum? x) x (most-positive-fixnum)))) - (when (uvar? x) - (uvar-spilled! x #t) - (unless (block-pariah? block) - (uvar-save-weight-set! x - (fixnum - (+ (uvar-save-weight x) - (* (info-newframe-weight newframe-info) 2))))))) - call-live*) - (info-newframe-call-live*-set! newframe-info call-live*))))) - block*))) - - ; maintain move sets as (var . weight) lists, sorted by weight (largest first) - ; 2014/06/26: allx move set size averages .79 elements with a max of 12, so no - ; need for anything fancier than this weighted version of insertion sort - (define $add-move! - (lambda (x1 x2 weight) - (when (uvar? x1) - (when (or (not (uvar-poison? x1)) (fv? x2)) - (uvar-move*-set! x1 - (call-with-values - (lambda () - (let f ([move* (uvar-move* x1)]) - (if (null? move*) - (values (cons x2 weight) move*) - (let ([move (car move*)] [move* (cdr move*)]) - (if (eq? (car move) x2) - (values (cons (car move) (fx+ (cdr move) weight)) move*) - (let-values ([(move2 move*) (f move*)]) - (if (fx> (cdr move2) (cdr move)) - (values move2 (cons move move*)) - (values move (cons move2 move*))))))))) - cons)))))) - - (define-who identify-poison! - (lambda (kspillable varvec live-size block*) - (define kpoison 0) - (define increment-live-counts! - (lambda (live) - (tree-for-each live live-size 0 kspillable - (lambda (offset) - (let ([x (vector-ref varvec offset)]) - (let ([range (fx+ (uvar-live-count x) 1)]) - (when (fx= range 2) - (uvar-poison! x #t) - (set! kpoison (fx+ kpoison 1))) - (uvar-live-count-set! x range))))))) - (define Effect - (lambda (live* e) - (nanopass-case (L15a Effect) e - [(set! ,live-info ,x ,rhs) - (guard (uvar? x)) - (if (live-info-useless live-info) - live* - (cons (live-info-live live-info) live*))] - [else live*]))) - (let ([vlive (list->vector (fold-left (lambda (live* block) (fold-left Effect live* (block-effect* block))) '() block*))]) - (let ([nvlive (vector-length vlive)]) - (let refine ([skip 64] [stride 64]) - (do ([i (fx- skip 1) (fx+ i stride)]) - ((fx>= i nvlive)) - (increment-live-counts! (vector-ref vlive i))) - (unless (or (fx= stride 16) (< (* (fx- kspillable kpoison) (fx* stride 2)) 1000000)) - (refine (fxsrl skip 1) skip))))))) - - (define-who do-spillable-conflict! - (lambda (kspillable kfv varvec live-size block*) - (define remove-var (make-remove-var live-size)) - (define add-move! - (lambda (x1 x2) - (when (var-index x2) - ($add-move! x1 x2 2) - ($add-move! x2 x1 2)))) - (define add-conflict! - (lambda (x out) - ; invariants: - ; all poison spillables explicitly point to all spillables - ; all non-poison spillables implicitly point to all poison spillables via poison-cset - (let ([x-offset (var-index x)]) - (when x-offset - (if (and (fx< x-offset kspillable) (uvar-poison? x)) - (tree-for-each out live-size kspillable (fx+ kspillable kfv) - (lambda (y-offset) - ; frame y -> poison spillable x - (conflict-bit-set! (var-spillable-conflict* (vector-ref varvec y-offset)) x-offset))) - (let ([cset (var-spillable-conflict* x)]) - (if (fx< x-offset kspillable) - (begin - (tree-for-each out live-size 0 kspillable - (lambda (y-offset) - (let ([y (vector-ref varvec y-offset)]) - (unless (uvar-poison? y) - ; non-poison spillable x -> non-poison spillable y - (conflict-bit-set! cset y-offset) - ; and vice versa - (conflict-bit-set! (var-spillable-conflict* y) x-offset))))) - (tree-for-each out live-size kspillable live-size - (lambda (y-offset) - (let ([y (vector-ref varvec y-offset)]) - ; frame or register y -> non-poison spillable x - (conflict-bit-set! (var-spillable-conflict* y) x-offset))))) - (if (fx< x-offset (fx+ kspillable kfv)) - (tree-for-each out live-size 0 kspillable - (lambda (y-offset) - ; frame x -> poison or non-poison spillable y - (conflict-bit-set! cset y-offset))) - (tree-for-each out live-size 0 kspillable - (lambda (y-offset) - (unless (uvar-poison? (vector-ref varvec y-offset)) - ; register x -> non-poison spillable y - (conflict-bit-set! cset y-offset)))))))))))) - (define Rhs - (lambda (rhs live) - (nanopass-case (L15a Rhs) rhs - [(inline ,info ,value-prim ,t* ...) - (guard (info-kill*? info)) - (for-each (lambda (x) (add-conflict! x live)) (info-kill*-kill* info))] - [else (void)]))) - (define Effect - (lambda (e new-effect*) - (nanopass-case (L15a Effect) e - [(set! ,live-info ,x ,rhs) - (if (live-info-useless live-info) - new-effect* - (let ([live (live-info-live live-info)]) - (when (var-index x) - (if (and (var? rhs) (var-index rhs)) - (begin - (add-conflict! x (remove-var live rhs)) - (add-move! x rhs)) - (add-conflict! x live))) - (Rhs rhs live) - (cons e new-effect*)))] - [(set! ,live-info ,lvalue ,rhs) (Rhs rhs (live-info-live live-info)) (cons e new-effect*)] - [(inline ,live-info ,info ,effect-prim ,t* ...) - (guard (info-kill*? info)) - (let ([live (live-info-live live-info)]) - (for-each (lambda (x) (add-conflict! x live)) (info-kill*-kill* info))) - (cons e new-effect*)] - [else (cons e new-effect*)]))) - (do ([i 0 (fx+ i 1)]) - ((fx= i kspillable)) - (let ([x (vector-ref varvec i)]) - (if (uvar-poison? x) - (begin - (conflict-bit-set! poison-cset i) - ; leaving each poison spillable in conflict with itself, but this shouldn't matter - ; since we never ask for the degree of a poison spillable - (var-spillable-conflict*-set! x (make-full-cset kspillable))) - (var-spillable-conflict*-set! x (make-empty-cset kspillable))))) - (do ([i kspillable (fx+ i 1)]) - ((fx= i live-size)) - (var-spillable-conflict*-set! (vector-ref varvec i) (make-empty-cset kspillable))) - (for-each - (lambda (block) - (block-effect*-set! block - (fold-right Effect '() (block-effect* block)))) - block*))) - - (define-who show-conflicts - (lambda (name varvec unvarvec) - (define any? #f) - (printf "\n~s conflicts:" name) - (for-each - (lambda (x) - (let ([ls (append - (let ([cset (var-spillable-conflict* x)]) - (if cset (extract-conflicts cset varvec) '())) - (let ([cset (var-unspillable-conflict* x)]) - (if cset (extract-conflicts cset unvarvec) '())))]) - (unless (null? ls) (set! any? #t) (printf "\n~s:~{ ~s~}" x ls)))) - (append spillable* unspillable* (vector->list regvec) (map get-fv (iota (fx+ max-fv 1))))) - (unless any? (printf " none")) - (newline))) - - (module (assign-frame! assign-new-frame!) - (define update-conflict! - (lambda (fv spill) - (let ([cset1 (var-spillable-conflict* fv)] - [cset2 (var-spillable-conflict* spill)]) - (if cset1 - (cset-merge! cset1 cset2) - ; tempting to set to cset2 rather than (cset-copy cset2), but this would not be - ; correct for local saves, which need their unaltered sets for later, and copying - ; is cheap anyway. - (var-spillable-conflict*-set! fv (cset-copy cset2)))) - (unless (uvar-poison? spill) (cset-merge! (var-spillable-conflict* fv) poison-cset)))) - - (define assign-frame! - (lambda (spill*) - (define sort-spill* - ; NB: sorts based on likelihood of successfully assigning move-related vars to the same location - ; NB: probably should sort based on value of assigning move-related vars to the same location, - ; NB: i.e., taking into account the ref-weight - (lambda (spill*) - (map car - (list-sort - (lambda (x y) (fx> (cdr x) (cdr y))) - (map (lambda (x) - (define relevant? - (lambda (x) - (or (fv? x) (and (uvar? x) (uvar-spilled? x))))) - (do ([move* (uvar-move* x) (cdr move*)] - [w 0 (let ([move (car move*)]) - (if (relevant? (car move)) - (fx+ w (cdr move)) - w))]) - ((null? move*) (cons x w)))) - spill*))))) - (define find-move-related-home - (lambda (x0 succ fail) - (define conflict-fv? - (lambda (x fv) - (let ([cset (var-spillable-conflict* fv)]) - (and cset (conflict-bit-set? cset (var-index x)))))) - (let f ([x x0] [work* '()] [clear-seen! void]) - (if (uvar-seen? x) - (if (null? work*) (begin (clear-seen!) (fail)) (f (car work*) (cdr work*) clear-seen!)) - (let ([clear-seen! (lambda () (uvar-seen! x #f) (clear-seen!))]) - (uvar-seen! x #t) - (let loop ([move* (uvar-move* x)] [work* work*]) - (if (null? move*) - (if (null? work*) (begin (clear-seen!) (fail)) (f (car work*) (cdr work*) clear-seen!)) - (let ([var (caar move*)] [move* (cdr move*)]) - (define try-fv - (lambda (fv) - (if (conflict-fv? x0 fv) - (loop move* work*) - (begin - (safe-assert (not (eq? fv (get-fv 0)))) - (begin (clear-seen!) (succ fv)))))) - (if (fv? var) - (try-fv var) - (if (uvar? var) - (let ([fv (uvar-location var)]) - (if (fv? fv) - (try-fv fv) - (loop move* (cons var work*)))) - (loop move* work*))))))))))) - (define find-home! - (lambda (spill max-fv first-open) - (define return - (lambda (home max-fv first-open) - (uvar-location-set! spill home) - (update-conflict! home spill) - (values max-fv first-open))) - (find-move-related-home spill - (lambda (home) (return home max-fv first-open)) - (lambda () - (let f ([first-open first-open]) - (let* ([fv (get-fv first-open)] [cset (var-spillable-conflict* fv)]) - (if (and cset (cset-full? cset)) - (f (fx+ first-open 1)) - (let ([spill-offset (var-index spill)]) - (let f ([fv-offset first-open] [fv fv] [cset cset]) - (if (and cset (conflict-bit-set? cset spill-offset)) - (let* ([fv-offset (fx+ fv-offset 1)] [fv (get-fv fv-offset)] [cset (var-spillable-conflict* fv)]) - (f fv-offset fv cset)) - (return fv (fxmax fv-offset max-fv) first-open))))))))))) - (define find-homes! - (lambda (spill* max-fv first-open) - (if (null? spill*) - max-fv - (let-values ([(max-fv first-open) (find-home! (car spill*) max-fv first-open)]) - (find-homes! (cdr spill*) max-fv first-open))))) - ; NOTE: call-live uvars should be sorted so that those that are call-live with few other - ; variables are earlier in the list (and more likely to get a low frame location); - ; additionally if they are live across many frames they should be prioritized over those - ; live across only a few (only when setup-nfv?) - (set! max-fv (find-homes! (sort-spill* spill*) max-fv 1)))) - - (define-pass assign-new-frame! : (L15a Dummy) (ir lambda-info live-size varvec block*) -> (L15b Dummy) () - (definitions - (define remove-var (make-remove-var live-size)) - (define find-max-fv - (lambda (call-live*) - (fold-left - (lambda (call-max-fv x) - (fxmax (fv-offset (if (uvar? x) (uvar-location x) x)) call-max-fv)) - -1 call-live*))) - (define cool? - (lambda (base nfv*) - (let loop ([nfv* nfv*] [offset base]) - (or (null? nfv*) - (and (or (not (car nfv*)) - (let ([cset (var-spillable-conflict* (get-fv offset))]) - (not (and cset (conflict-bit-set? cset (var-index (car nfv*))))))) - (loop (cdr nfv*) (fx+ offset 1))))))) - (define assign-new-frame! - (lambda (cnfv* nfv** call-live*) - (define set-offsets! - (lambda (nfv* offset) - (if (null? nfv*) - (set! max-fv (fxmax offset max-fv)) - (let ([nfv (car nfv*)] [home (get-fv offset)]) - (uvar-location-set! nfv home) - (update-conflict! home nfv) - (set-offsets! (cdr nfv*) (fx+ offset 1)))))) - (let ([arg-offset (fx+ (length cnfv*) 1)]) ; +1 for return address slot - (let loop ([base (fx+ (find-max-fv call-live*) 1)]) - (let ([arg-base (fx+ base arg-offset)]) - (if (and (cool? base cnfv*) (andmap (lambda (nfv*) (cool? arg-base nfv*)) nfv**)) - (begin - (set! max-fs@call (fxmax max-fs@call base)) ; max frame size @ call in ptrs - (set-offsets! cnfv* base) - (for-each (lambda (nfv*) (set-offsets! nfv* arg-base)) nfv**) - base) - (loop (fx+ base 1)))))))) - (define build-mask - (lambda (index*) - (define bucket-width (if (fx> (fixnum-width) 32) 32 16)) - (let* ([nbits (fx+ (fold-left (lambda (m index) (fxmax m index)) -1 index*) 1)] - [nbuckets (fxdiv (fx+ nbits (fx- bucket-width 1)) bucket-width)] - [buckets (make-fxvector nbuckets 0)]) - (for-each - (lambda (index) - (let-values ([(i j) (fxdiv-and-mod index bucket-width)]) - (fxvector-set! buckets i (fxlogbit1 j (fxvector-ref buckets i))))) - index*) - (let f ([base 0] [len nbuckets]) - (if (fx< len 2) - (if (fx= len 0) - 0 - (fxvector-ref buckets base)) - (let ([half (fxsrl len 1)]) - (logor - (bitwise-arithmetic-shift-left (f (fx+ base half) (fx- len half)) (fx* half bucket-width)) - (f base half)))))))) - (define build-live-pointer-mask - (lambda (live*) - (build-mask - (fold-left - (lambda (index* live) - (define (cons-fv fv index*) - (let ([offset (fv-offset fv)]) - (if (fx= offset 0) ; no bit for fv0 - index* - (cons (fx- offset 1) index*)))) - (cond - [(fv? live) (cons-fv live index*)] - [(eq? (uvar-type live) 'ptr) (cons-fv (uvar-location live) index*)] - [else index*])) - '() live*)))) - (define (process-info-newframe! info) - (unless (info-newframe-frame-words info) - (let ([call-live* (info-newframe-call-live* info)]) - (info-newframe-frame-words-set! info - (let ([cnfv* (info-newframe-cnfv* info)]) - (fx+ (assign-new-frame! cnfv* (cons (info-newframe-nfv* info) (info-newframe-nfv** info)) call-live*) - (length cnfv*)))) - (info-newframe-local-save*-set! info - (filter (lambda (x) (and (uvar? x) (uvar-local-save? x))) call-live*))))) - (define record-inspector-info! - (lambda (src sexpr rpl call-live* lpm) - (safe-assert (if call-live* rpl (not rpl))) - (cond - [(and call-live* (info-lambda-ctci lambda-info)) => - (lambda (ctci) - (let ([mask (build-mask - (fold-left - (lambda (i* x) - (cond - [(and (uvar? x) (uvar-iii x)) => - (lambda (index) - (safe-assert - (let ([name.offset (vector-ref (ctci-live ctci) index)]) - (logbit? (fx- (cdr name.offset) 1) lpm))) - (cons index i*))] - [else i*])) - '() call-live*))]) - (when (or src sexpr (not (eqv? mask 0))) - (ctci-rpi*-set! ctci (cons (make-ctrpi rpl src sexpr mask) (ctci-rpi* ctci))))))])))) - (Pred : Pred (ir) -> Pred ()) - (Tail : Tail (ir) -> Tail () - [(jump ,live-info ,[t] (,var* ...)) `(jump ,live-info ,t)] - [(asm-return ,reg* ...) `(asm-return)] - [(asm-c-return ,info ,reg* ...) `(asm-c-return ,info)]) - (Effect : Effect (ir) -> Effect ()) - (foldable-Effect : Effect (ir new-effect*) -> * (new-effect*) - [(return-point ,info ,rpl ,mrvl (,cnfv* ...)) - (process-info-newframe! info) - (let ([lpm (build-live-pointer-mask (append cnfv* (info-newframe-call-live* info)))]) - (record-inspector-info! (info-newframe-src info) (info-newframe-sexpr info) rpl (info-newframe-call-live* info) lpm) - (with-output-language (L15b Effect) - (safe-assert (< -1 lpm (ash 1 (fx- (info-newframe-frame-words info) 1)))) - (cons `(rp-header ,mrvl ,(fx* (info-newframe-frame-words info) (constant ptr-bytes)) ,lpm) new-effect*)))] - [(remove-frame ,live-info ,info) - (process-info-newframe! info) - (with-output-language (L15b Effect) - (let ([live (live-info-live live-info)]) - (cons* - `(fp-offset ,live-info ,(fx- (fx* (info-newframe-frame-words info) (constant ptr-bytes)))) - `(overflood-check ,(make-live-info live)) - new-effect*)))] - [(restore-local-saves ,live-info ,info) - (with-output-language (L15b Effect) - (let ([live (live-info-live live-info)]) - (let loop ([x* (filter (lambda (x) (live? live live-size x)) (info-newframe-local-save* info))] - [live live] - [new-effect* new-effect*]) - (if (null? x*) - new-effect* - (let* ([x (car x*)] [live (remove-var live x)]) - (loop (cdr x*) live - (cons `(set! ,(make-live-info live) ,x ,(uvar-location x)) new-effect*)))))))] - [(shift-arg ,live-info ,reg ,imm ,info) - (process-info-newframe! info) - (with-output-language (L15b Effect) - (let ([frame-words (info-newframe-frame-words info)]) - (safe-assert (not (fx= frame-words 0))) - (let ([shift-offset (fx* frame-words (constant ptr-bytes))]) - (safe-assert (fx> shift-offset 0)) - (cons `(set! ,live-info (mref ,reg ,%zero ,imm) (mref ,reg ,%zero ,shift-offset)) new-effect*))))] - [(check-live ,live-info ,reg* ...) - (let ([live (fold-left (lambda (live reg) - (let ([t (remove-var live reg)]) - (when (eqv? t live) (sorry! who "(check-live) ~s is not live" reg)) - t)) - (live-info-live live-info) - reg*)]) - (unless (eqv? live no-live*) - (sorry! who "(check-live) unexpected live vars ~s" (get-live-vars live live-size varvec)))) - new-effect*] - [else (cons (Effect ir) new-effect*)]) - (begin - (for-each - (lambda (x) - ; NB: experiment with different comparisions. might want ref weight - ; NB: to be at least more than save weight to relieve register pressure. - (when (and (uvar-spilled? x) (not (uvar-poison? x)) (fx>= (uvar-ref-weight x) (uvar-save-weight x))) - (uvar-local-save! x #t))) - spillable*) - (for-each - (lambda (block) - (block-effect*-set! block - (fold-right foldable-Effect - (cond - [(or (goto-block? block) (joto-block? block)) '()] - [(if-block? block) (if-block-pred-set! block (Pred (if-block-pred block))) '()] - [(tail-block? block) (tail-block-tail-set! block (Tail (tail-block-tail block))) '()] - [(newframe-block? block) - (let ([info (newframe-block-info block)]) - (process-info-newframe! info) - (safe-assert (andmap (lambda (x) (live? (newframe-block-live-call block) live-size x)) (info-newframe-local-save* info))) - (with-output-language (L15b Effect) - (let ([live (newframe-block-live-out block)]) - (fold-left - (lambda (new-effect* x) - (let ([loc (uvar-location x)]) - ($add-move! x loc 2) - (cons `(set! ,(make-live-info live) ,loc ,x) new-effect*))) - (cons `(fp-offset ,(make-live-info live) ,(fx* (info-newframe-frame-words info) (constant ptr-bytes))) '()) - (info-newframe-local-save* info)))))] - [else (sorry! who "unrecognized block ~s" block)]) - (block-effect* block)))) - block*) - (for-each - (lambda (x) - (when (uvar-local-save? x) - (uvar-location-set! x #f) - (uvar-spilled! x #f) - (uvar-save-weight-set! x 0))) - spillable*) - `(dummy)))) - - (define record-fp-offsets! - (lambda (block*) - (define-who record-fp-offsets! - (lambda (block cur-off) - (define Effect - (lambda (cur-off effect) - (nanopass-case (L15b Effect) effect - [(fp-offset ,live-info ,imm) - (let ([cur-off (fx+ cur-off imm)]) - (safe-assert (fx>= cur-off 0)) - cur-off)] - [else cur-off]))) - (let ([block-off (block-fp-offset block)]) - (if block-off - (unless (fx= cur-off block-off) - (sorry! who "conflicting fp-offset value for block ~s" block)) - (let ([effect* (block-effect* block)]) - (block-fp-offset-set! block cur-off) - (cond - [(goto-block? block) - (record-fp-offsets! (goto-block-next block) (fold-left Effect cur-off effect*))] - [(joto-block? block) - (record-fp-offsets! (joto-block-next block) 0)] - [(if-block? block) - (let ([cur-off (fold-left Effect cur-off effect*)]) - (record-fp-offsets! (if-block-true block) cur-off) - (record-fp-offsets! (if-block-false block) cur-off))] - [(tail-block? block) (void)] - [(newframe-block? block) - (let ([cur-off (fold-left Effect cur-off effect*)]) - (record-fp-offsets! (newframe-block-next block) cur-off) - (for-each (lambda (rp) (record-fp-offsets! rp cur-off)) (newframe-block-rp* block)) - (record-fp-offsets! (newframe-block-rp block) cur-off))] - [else (sorry! who "unrecognized block ~s" block)])))))) - (for-each (lambda (block) (record-fp-offsets! block 0)) block*))) - - (define-pass finalize-frame-locations! : (L15b Dummy) (ir block*) -> (L15c Dummy) () - (definitions - (define var->loc - (lambda (x) - (or (and (uvar? x) (uvar-location x)) x))) - (define fv->mref - (lambda (x cur-off) - (if (fv? x) - (with-output-language (L15c Lvalue) - `(mref ,%sfp ,%zero ,(fx- (fx* (fv-offset x) (constant ptr-bytes)) cur-off))) - x)))) - (Lvalue : Lvalue (ir cur-off) -> Lvalue () - [(mref ,x0 ,x1 ,imm) - `(mref ,(fv->mref (var->loc x0) cur-off) ,(fv->mref (var->loc x1) cur-off) ,imm)] - [,x (fv->mref (var->loc x) cur-off)]) - ; NB: defining Triv & Rhs with cur-off argument so we actually get to our version of Lvalue - (Triv : Triv (ir cur-off) -> Triv ()) - (Rhs : Rhs (ir cur-off) -> Rhs ()) - (Pred : Pred (ir cur-off) -> Pred ()) - (Tail : Tail (ir cur-off) -> Tail ()) - (Effect : Effect (ir cur-off) -> Effect ()) - (begin - (for-each - (lambda (block) - (block-effect*-set! block - (let f ([effect* (block-effect* block)] [cur-off (block-fp-offset block)]) - (if (null? effect*) - (begin - (cond - [(or (goto-block? block) (joto-block? block) (newframe-block? block)) (void)] - [(if-block? block) (if-block-pred-set! block (Pred (if-block-pred block) cur-off))] - [(tail-block? block) (tail-block-tail-set! block (Tail (tail-block-tail block) cur-off))] - [else (sorry! who "unrecognized block ~s" block)]) - '()) - (with-output-language (L15c Effect) - (nanopass-case (L15b Effect) (car effect*) - [(fp-offset ,live-info ,imm) - (cons `(set! ,live-info ,%sfp - ,(if (fx< imm 0) - ; subtract just to make the generated code more clear - `(inline ,null-info ,%- ,%sfp (immediate ,(fx- imm))) - `(inline ,null-info ,%+ ,%sfp (immediate ,imm)))) - (f (cdr effect*) (fx+ cur-off imm)))] - [(set! ,live-info ,x0 ,x1) - (let ([x0 (var->loc x0)] [x1 (var->loc x1)]) - (if (eq? x0 x1) - (f (cdr effect*) cur-off) - (cons `(set! ,live-info ,(fv->mref x0 cur-off) ,(fv->mref x1 cur-off)) (f (cdr effect*) cur-off))))] - [else (cons (Effect (car effect*) cur-off) (f (cdr effect*) cur-off))])))))) - block*) - `(dummy))) - - (module (select-instructions!) - (define make-tmp - (lambda (x) - (import (only np-languages make-unspillable)) - (let ([tmp (make-unspillable x)]) - (set! unspillable* (cons tmp unspillable*)) - tmp))) - (define make-restricted-unspillable - (lambda (x reg*) - (import (only np-languages make-restricted-unspillable)) - (safe-assert (andmap reg? reg*) (andmap var-index reg*)) - (let ([tmp (make-restricted-unspillable x reg*)]) - (set! unspillable* (cons tmp unspillable*)) - tmp))) - (define make-precolored-unspillable - ; instead of using machine registers like eax explicitly, we use an unspillable that - ; conflicts with everything but the machine register. this is semantically equivalent - ; for correct code but causes a spilled unspillable error if we try to use the same - ; machine register for two conflicting variables - (lambda (name reg) - (or (reg-precolored reg) - (let ([tmp (make-restricted-unspillable name (remq reg (vector->list regvec)))]) - (safe-assert (memq reg (vector->list regvec))) - (reg-precolored-set! reg tmp) - tmp)))) - - (define-syntax build-set! - (lambda (x) - (syntax-case x () - [(k lhs rhs) - (with-implicit (k quasiquote with-output-language) - #`(with-output-language (L15d Effect) - `(set! ,(make-live-info) lhs rhs)))]))) - (define imm? - (lambda (x) - (nanopass-case (L15c Triv) x - [(immediate ,imm) #t] - [(literal ,info) (not (info-literal-indirect? info))] - [(label-ref ,l ,offset) #t] - [else #f]))) - (define imm0? - (lambda (x) - (nanopass-case (L15c Triv) x - [(immediate ,imm) (eqv? imm 0)] - [else #f]))) - (define imm32? - (lambda (x) - (nanopass-case (L15c Triv) x - [(immediate ,imm) - (constant-case ptr-bits - [(32) #t] ; allows 2^31...2^32-1 per immediate? - [(64) (signed-32? imm)])] ; 2^31...2^32-1 aren't 32-bit values on 64-bit machines - [(literal ,info) - (constant-case ptr-bits - [(32) (not (info-literal-indirect? info))] - [(64) #f])] - [(label-ref ,l ,offset) - (constant-case ptr-bits - [(32) #t] - [(64) #f])] - [else #f]))) - (define literal@? - (lambda (x) - (nanopass-case (L15c Triv) x - [(literal ,info) (info-literal-indirect? info)] - [else #f]))) - (define mref? - (lambda (x) - (nanopass-case (L15c Triv) x - [(mref ,lvalue1 ,lvalue2 ,imm) #t] - [else #f]))) - (define same? - (lambda (a b) - (or (eq? a b) - (nanopass-case (L15c Triv) a - [(mref ,lvalue11 ,lvalue12 ,imm1) - (nanopass-case (L15c Triv) b - [(mref ,lvalue21 ,lvalue22 ,imm2) - (and (or (and (eq? lvalue11 lvalue21) (eq? lvalue12 lvalue22)) - (and (eq? lvalue11 lvalue22) (eq? lvalue12 lvalue21))) - (eqv? imm1 imm2))] - [else #f])] - [else #f])))) - - (define-pass imm->imm : (L15c Triv) (ir) -> (L15d Triv) () - (Lvalue : Lvalue (ir) -> Lvalue () - [(mref ,lvalue1 ,lvalue2 ,imm) (sorry! who "unexpected mref ~s" ir)]) - (Triv : Triv (ir) -> Triv ())) - - (define-pass literal@->literal : (L15c Triv) (ir) -> (L15d Triv) () - (Triv : Triv (ir) -> Triv () - [(literal ,info) - `(literal - ,(make-info-literal #f (info-literal-type info) - (info-literal-addr info) (info-literal-offset info)))] - [else (sorry! who "unexpected literal ~s" ir)])) - - (define-pass select-instructions! : (L15c Dummy) (ir block* live-size force-overflow?) -> (L15d Dummy) () - (definitions - (module (handle-jump handle-effect-inline handle-pred-inline handle-value-inline) - (define add-var (make-add-var live-size)) - (define Triv - (lambda (out t) - (nanopass-case (L15d Triv) t - [(mref ,x1 ,x2 ,imm) (add-var (add-var out x2) x1)] - [,x (add-var out x)] - [else out]))) - (define Rhs - (lambda (out rhs) - (nanopass-case (L15d Rhs) rhs - [(asm ,info ,proc ,t* ...) (fold-left Triv out t*)] - [else (Triv out rhs)]))) - (define Pred - (lambda (out pred) - (nanopass-case (L15d Pred) pred - [(asm ,info ,proc ,t* ...) (fold-left Triv out t*)]))) - (define Tail - (lambda (out tail) - (nanopass-case (L15d Tail) tail - [(jump ,t) (Triv out t)]))) - (define unwrap - (lambda (etree effect* out) - (safe-assert (not (eq? out 'uninitialized))) - (with-values - (let f ([etree etree] [effect* effect*] [out out]) - (if (pair? etree) - (let-values ([(effect* out) (f (cdr etree) effect* out)]) - (f (car etree) effect* out)) - (if (null? etree) - (values effect* out) - (values - (cons etree effect*) - (nanopass-case (L15d Effect) etree - [(set! ,live-info ,x ,rhs) - (live-info-live-set! live-info out) - (Rhs out rhs)] - [(set! ,live-info ,lvalue ,rhs) - (live-info-live-set! live-info out) - (Triv (Rhs out rhs) lvalue)] - [(asm ,info ,proc ,t* ...) (fold-left Triv out t*)] - [else out]))))) - (lambda (effect* out) effect*)))) - (define-who handle-jump - (lambda (t live) - (let-values ([(etree tail) (md-handle-jump t)]) - (values (unwrap etree '() (Tail live tail)) tail)))) - (define-who handle-effect-inline - (lambda (effect-prim info new-effect* t* live) - (unwrap (apply (primitive-handler effect-prim) info t*) new-effect* live))) - (define-who handle-pred-inline - (lambda (pred-prim info t* live) - (let-values ([(etree pred) (apply (primitive-handler pred-prim) info t*)]) - (values (unwrap etree '() (Pred live pred)) pred)))) - (define-who handle-value-inline - (lambda (lvalue value-prim info new-effect* t* live) - (unwrap (apply (primitive-handler value-prim) info lvalue t*) new-effect* live)))) - (define compute-overage - (lambda (max-fs@call) - (if force-overflow? - (fxmax - (fx- (fx* max-fs@call (constant ptr-bytes)) 0) - (fx- (fx* (fx+ max-fv 1) (constant ptr-bytes)) (fx- (constant stack-slop) (fx* (constant stack-frame-limit) 2)))) - (fxmax - (fx- (fx* max-fs@call (constant ptr-bytes)) (constant stack-frame-limit)) - (fx- (fx* (fx+ max-fv 1) (constant ptr-bytes)) (fx- (constant stack-slop) (constant stack-frame-limit))))))) - (define overage (compute-overage max-fs@call)) - (define handle-overflow-check - (lambda (reg info new-effect* live) - (let-values ([(xnew-effect* pred) (handle-pred-inline %u< null-info - (list - reg - (meta-cond - [(real-register? '%esp) %esp] - [else (with-output-language (L15c Triv) - `(mref ,%tc ,%zero ,(tc-disp %esp)))])) - live)]) - (append xnew-effect* - (cons (with-output-language (L15d Effect) - `(overflow-check ,pred - ,(handle-effect-inline %asmlibcall! info '() '() live) - ...)) - new-effect*))))) - (define maybe-incr-instr-count - (lambda (block e*) - (define checks-cc? ; copied from instrument - (lambda (block) - (and (if-block? block) - (null? (block-effect* block)) - (nanopass-case (L15c Pred) (if-block-pred block) - [(inline ,live-info ,info ,pred-prim ,t* ...) (eq? pred-prim %condition-code)] - [else #f])))) - (define count - (lambda (n e) - ; overflow-check counts as one instruction...close enough, since it rarely fails - (nanopass-case (L15d Effect) e - [(rp-header ,mrvl ,fs ,lpm) n] - [(move-related ,x1 ,x2) n] - [else (fx+ n 1)]))) - (if (generate-instruction-counts) - (let* ([n (fold-left count (if (goto-block? block) 0 1) e*)] - [f (lambda (e*) - (handle-effect-inline %inc-cc-counter null-info e* - (list %tc - (with-output-language (L15c Triv) `(immediate ,(constant tc-instr-counter-disp))) - (with-output-language (L15c Triv) `(immediate ,n))) - (block-live-in block)))]) - (if (and (not (null? e*)) - (nanopass-case (L15d Effect) (car e*) - [(rp-header ,mrvl ,fs ,lpm) #t] - [else #f])) - (cons (car e*) (f (cdr e*))) - (begin - (assert (not (checks-cc? block))) - (f e*)))) - e*)))) - (Rhs : Rhs (ir lvalue new-effect* live) -> * (new-effect*) - [(inline ,info ,value-prim ,t* ...) - (handle-value-inline lvalue value-prim info new-effect* t* live)] - [else (handle-value-inline lvalue %move null-info new-effect* (list ir) live)]) - (Tail : Tail (ir) -> Tail () - [(jump ,live-info ,t) (handle-jump t (live-info-live live-info))] - [(goto ,l) (values '() `(goto ,l))] - [(asm-return) (values '() `(asm-return))] - [(asm-c-return ,info) (values '() `(asm-c-return ,info))]) - (Effect : Effect (ir new-effect*) -> * (new-effect*) - [(set! ,live-info ,lvalue ,rhs) (Rhs rhs lvalue new-effect* (live-info-live live-info))] - [(inline ,live-info ,info ,effect-prim ,t* ...) - (handle-effect-inline effect-prim info new-effect* t* (live-info-live live-info))] - [(rp-header ,mrvl ,fs ,lpm) - (cons (with-output-language (L15d Effect) `(rp-header ,mrvl ,fs ,lpm)) new-effect*)] - [(overflow-check ,live-info) - (if (fx> 1 overage (fx- (constant stack-frame-limit) (constant stack-slop))) - (handle-overflow-check %sfp (intrinsic-info-asmlib dooverflow #f) new-effect* (live-info-live live-info)) - new-effect*)] - [(overflood-check ,live-info) - (if (fx> overage 0) - ; dooverflood protocol requires %xp be set where we need esp to be - (let ([uxp (make-precolored-unspillable 'uxp %xp)]) - (handle-value-inline uxp %+ null-info - (handle-overflow-check uxp (intrinsic-info-asmlib dooverflood #f) new-effect* (live-info-live live-info)) - (list %sfp (with-output-language (L15c Triv) `(immediate ,overage))) - (live-info-live live-info))) - new-effect*)] - [(fcallable-overflow-check ,live-info) - ; max-fs@call = 2: the return address and c-chain stored by C-call->XXX - (if (fx> 1 (compute-overage 2) (fx- (constant stack-frame-limit) (constant stack-slop))) - (handle-overflow-check %sfp (intrinsic-info-asmlib dooverflow #f) new-effect* (live-info-live live-info)) - new-effect*)]) - (Pred : Pred (ir) -> Pred () - [(inline ,live-info ,info ,pred-prim ,t* ...) - (handle-pred-inline pred-prim info t* (live-info-live live-info))]) - (begin - (for-each - (lambda (block) - (block-effect*-set! block - (maybe-incr-instr-count block - (fold-right Effect - (cond - [(or (goto-block? block) (joto-block? block) (newframe-block? block)) '()] - [(if-block? block) - (let-values ([(new-effect* pred) (Pred (if-block-pred block))]) - (if-block-pred-set! block pred) - new-effect*)] - [(tail-block? block) - (let-values ([(new-effect* tail) (Tail (tail-block-tail block))]) - (tail-block-tail-set! block tail) - new-effect*)] - [else (sorry! who "unrecognized block ~s" block)]) - (block-effect* block))))) - block*) - `(dummy))) - - ; NB: try to reuse unspillables to reduce the number we create - (architecture instructions) - ) - - (define-who do-unspillable-conflict! - (lambda (kfv kspillable varvec live-size kunspillable unvarvec block*) - (define remove-var (make-remove-var live-size)) - (define unspillable? - (lambda (x) - (and (uvar? x) (uvar-unspillable? x)))) - (define add-unspillable - (lambda (unspillable* x) - (if (and (unspillable? x) (not (uvar-seen? x))) - (begin - (uvar-seen! x #t) - (cons x unspillable*)) - unspillable*))) - (define add-move! - (lambda (x1 x2) - (when (var-index x2) - ($add-move! x1 x2 2) - ($add-move! x2 x1 2)))) - (define add-move-hint! - (lambda (x1 x2) - (when (var-index x2) - ($add-move! x1 x2 1) - ($add-move! x2 x1 1)))) - (define add-static-conflict! - (lambda (u reg*) - (let ([u-offset (var-index u)]) - (for-each - (lambda (reg) (conflict-bit-set! (var-unspillable-conflict* reg) u-offset)) - reg*)))) - (define add-us->s-conflicts! - (lambda (x out) ; x is an unspillable - (let ([x-offset (var-index x)] [cset (var-spillable-conflict* x)]) - (tree-for-each out live-size 0 live-size - (lambda (y-offset) - (let* ([y (vector-ref varvec y-offset)] [y-cset (var-unspillable-conflict* y)]) - (when y-cset - ; if y is a spillable, point the unspillable x at y - (when (fx< y-offset kspillable) (conflict-bit-set! cset y-offset)) - ; point y at the unspillable x - (conflict-bit-set! y-cset x-offset)))))))) - (define add-us->us-conflicts! - (lambda (x unspillable*) ; x is a unspillable - (let ([x-offset (var-index x)] [cset (var-unspillable-conflict* x)]) - (for-each - (lambda (y) - (let ([y-offset (var-index y)]) - (conflict-bit-set! cset y-offset) - (conflict-bit-set! (var-unspillable-conflict* y) x-offset))) - unspillable*)))) - (define add-s->us-conflicts! - (lambda (x unspillable*) ; x is a spillable or register - (let ([x-offset (var-index x)] [cset (var-unspillable-conflict* x)]) - (for-each - (lambda (y) - (let ([y-offset (var-index y)]) - ; point x at unspillable y - (conflict-bit-set! cset y-offset) - ; if x is a spillable, point unspillable y at x - (when (fx< x-offset kspillable) (conflict-bit-set! (var-spillable-conflict* y) x-offset)))) - unspillable*)))) - (define Triv - (lambda (unspillable* t) - (nanopass-case (L15d Triv) t - [(mref ,x1 ,x2 ,imm) (add-unspillable (add-unspillable unspillable* x2) x1)] - [,x (add-unspillable unspillable* x)] - [else unspillable*]))) - (define Rhs - (lambda (unspillable* rhs) - (nanopass-case (L15d Rhs) rhs - [(asm ,info ,proc ,t* ...) (fold-left Triv unspillable* t*)] - [else (Triv unspillable* rhs)]))) - (define Pred - (lambda (p) - (nanopass-case (L15d Pred) p - [(asm ,info ,proc ,t* ...) (fold-left Triv '() t*)] - [else (sorry! who "unexpected pred ~s" p)]))) - (define Tail - (lambda (tl) - (nanopass-case (L15d Tail) tl - [(jump ,t) (Triv '() t)] - [else '()]))) - (define Effect* - (lambda (e* unspillable*) - (if (null? e*) - (safe-assert (null? unspillable*)) - (Effect* (cdr e*) - (nanopass-case (L15d Effect) (car e*) - [(set! ,live-info ,x ,rhs) - (let ([spillable-live (live-info-live live-info)]) - (if (unspillable? x) - (let ([unspillable* (remq x unspillable*)]) - (safe-assert (uvar-seen? x)) - (uvar-seen! x #f) - (if (and (var? rhs) (var-index rhs)) - (begin - (if (unspillable? rhs) - (begin - (add-us->us-conflicts! x (remq rhs unspillable*)) - (add-us->s-conflicts! x spillable-live)) - (begin - (add-us->us-conflicts! x unspillable*) - (add-us->s-conflicts! x (remove-var spillable-live rhs)))) - (add-move! x rhs)) - (begin - (add-us->us-conflicts! x unspillable*) - (add-us->s-conflicts! x spillable-live))) - (Rhs unspillable* rhs)) - (begin - (when (var-unspillable-conflict* x) - (if (unspillable? rhs) - (begin - (add-s->us-conflicts! x (remq rhs unspillable*)) - (add-move! x rhs)) - (add-s->us-conflicts! x unspillable*))) - (Rhs unspillable* rhs))))] - [(set! ,live-info ,lvalue ,rhs) (Triv (Rhs unspillable* rhs) lvalue)] - [(asm ,info ,proc ,t* ...) (fold-left Triv unspillable* t*)] - [(move-related ,x1 ,x2) (add-move-hint! x1 x2) unspillable*] - [(overflow-check ,p ,e* ...) (Effect* (reverse e*) '()) (Pred p)] - [else unspillable*]))))) - (for-each (lambda (x) (var-spillable-conflict*-set! x (make-empty-cset kspillable))) unspillable*) - (let ([f (lambda (x) (var-unspillable-conflict*-set! x (make-empty-cset kunspillable)))]) - (vector-for-each f regvec) - (for-each f spillable*) - (vector-for-each f unvarvec)) - (vector-for-each (lambda (x) (add-static-conflict! x (uvar-conflict* x))) unvarvec) - (for-each - (lambda (block) - (Effect* (reverse (block-effect* block)) - (cond - [(or (goto-block? block) (joto-block? block) (newframe-block? block)) '()] - [(if-block? block) (Pred (if-block-pred block))] - [(tail-block? block) (Tail (tail-block-tail block))] - [else (sorry! who "unrecognized block ~s" block)]))) - block*))) - - (define-who assign-registers! - (lambda (lambda-info varvec unvarvec) - (define k (vector-length regvec)) - (define uvar-weight - (lambda (x) - (fx- (uvar-ref-weight x) (uvar-save-weight x)))) - ; could also be calculated when the conflict set is built, which would be more - ; efficient for low-degree variables - (define compute-degrees! - (lambda (x*) - ; account for uvar -> uvar conflicts - (for-each - (lambda (x) - (uvar-degree-set! x - (fx+ - ; spills have been trimmed from the var-spillable-conflict* sets - (conflict-bit-count (var-spillable-conflict* x)) - (conflict-bit-count (var-unspillable-conflict* x))))) - x*) - ; account for reg -> uvar conflicts - (vector-for-each - (lambda (reg) - (cset-for-each (var-spillable-conflict* reg) - (lambda (x-offset) - (let ([x (vector-ref varvec x-offset)]) - (unless (uvar-location x) - (uvar-degree-set! x (fx+ (uvar-degree x) 1)))))) - (cset-for-each (var-unspillable-conflict* reg) - (lambda (x-offset) - (let ([x (vector-ref unvarvec x-offset)]) - (uvar-degree-set! x (fx+ (uvar-degree x) 1)))))) - regvec))) - (define-who find-home! - (lambda (x) - (define conflict? - (lambda (reg x) - (let ([cset (if (uvar-unspillable? x) (var-unspillable-conflict* reg) (var-spillable-conflict* reg))]) - (conflict-bit-set? cset (var-index x))))) - (define find-move-related-home - (lambda (x0 succ fail) - (let f ([x x0] [work* '()] [clear-seen! void]) - (if (uvar-seen? x) - (if (null? work*) (begin (clear-seen!) (fail)) (f (car work*) (cdr work*) clear-seen!)) - (let ([clear-seen! (lambda () (uvar-seen! x #f) (clear-seen!))]) - (uvar-seen! x #t) - (let loop ([move* (uvar-move* x)] [work* work*]) - (if (null? move*) - (if (null? work*) (begin (clear-seen!) (fail)) (f (car work*) (cdr work*) clear-seen!)) - (let ([var (caar move*)] [move* (cdr move*)]) - (define try-reg - (lambda (reg) - (if (conflict? reg x0) - (loop move* work*) - (begin (clear-seen!) (succ reg))))) - (if (reg? var) - (try-reg var) - (if (uvar? var) - (let ([reg (uvar-location var)]) - (if (reg? reg) - (try-reg reg) - (loop move* (cons var work*)))) - (loop move* work*))))))))))) - (define set-home! - (lambda (home) - (define update-conflict! - (lambda (reg x) - (cset-merge! (var-spillable-conflict* reg) (var-spillable-conflict* x)) - (cset-merge! (var-unspillable-conflict* reg) (var-unspillable-conflict* x)))) - (uvar-location-set! x home) - (update-conflict! home x))) - (find-move-related-home x - set-home! - (lambda () - (let f ([offset (fx- k 1)]) - (cond - [(fx< offset 0) - (uvar-spilled! x #t) - (when (uvar-unspillable? x) - (sorry! who "spilled unspillable ~s" x))] - [(conflict? (vector-ref regvec offset) x) (f (fx- offset 1))] - [else (set-home! (vector-ref regvec offset))])))))) - (define pick-victims - (lambda (x*) - (define low-degree? (lambda (x) (fx< (uvar-degree x) k))) - (define pick-potential-spill - ; x* is already sorted by weight, so this effectively picks uvar with - ; the highest degree among those with the lowest weight - (lambda (x*) - (let ([x (let f ([x* (cdr x*)] [max-degree (uvar-degree (car x*))] [max-x (car x*)]) - (if (null? x*) - max-x - (let ([x (car x*)] [x* (cdr x*)]) - (if (or (uvar-unspillable? x) (fx> (uvar-weight x) (uvar-weight max-x))) - max-x - (let ([degree (uvar-degree x)]) - (if (fx> degree max-degree) - (f x* degree x) - (f x* max-degree max-x)))))))]) - (values x (remq x x*))))) - (define remove-victim! - (lambda (victim) - (cset-for-each (var-spillable-conflict* victim) - (lambda (offset) - (let ([x (vector-ref varvec offset)]) - (uvar-degree-set! x (fx- (uvar-degree x) 1))))) - (cset-for-each (var-unspillable-conflict* victim) - (lambda (offset) - (let ([x (vector-ref unvarvec offset)]) - (uvar-degree-set! x (fx- (uvar-degree x) 1))))))) - (define sort-victims - ; NB: sorts based on likelihood of successfully assigning move-related vars to the same register - ; NB: probably should sort based on value of assigning move-related vars to the same register, - ; NB: i.e., taking into account the ref-weight - (lambda (victim*) - (map car - (list-sort - (lambda (x y) (fx> (cdr x) (cdr y))) - (map (lambda (x) - (define relevant? - (lambda (x) - (or (reg? x) (and (uvar? x) (not (uvar-spilled? x)))))) - (do ([move* (uvar-move* x) (cdr move*)] - [w 0 (let ([move (car move*)]) - (if (relevant? (car move)) - (fx+ w (cdr move)) - w))]) - ((null? move*) (cons x w)))) - victim*))))) - (let-values ([(victim* keeper*) (partition low-degree? x*)]) - (if (null? victim*) - (let-values ([(victim keeper*) (pick-potential-spill x*)]) - ; note: victim can be an unspillable if x* contains only precolored unspillables - (remove-victim! victim) - (values (list victim) keeper*)) - (begin - (unless (null? keeper*) - ; tried creating a mask from victim*, logand with bv for each x, count the bits, - ; and subtract from x's uvar-degree-set!. code in chaff. didn't help at this point. - ; perhaps if fxbit-count were implemented better it would - (for-each remove-victim! victim*)) - (values (sort-victims victim*) keeper*)))))) - (let ([x* (append (sort (lambda (x y) (fx< (uvar-weight x) (uvar-weight y))) spillable*) unspillable*)]) - (compute-degrees! x*) - (let f ([x* x*]) - (unless (null? x*) - (let-values ([(victim* x*) (pick-victims x*)]) - (f x*) - (for-each find-home! victim*))))))) - - (define everybody-home? - (lambda () - (safe-assert (andmap uvar-location unspillable*)) - (andmap uvar-location spillable*))) - - (define record-inspector-information! - (lambda (info) - (define get-closure-fv-names - (lambda (info ctci) - (define (get-name fv) (unannotate (uvar-source fv))) - (or (ctci-closure-fv-names ctci) - (case (info-lambda-closure-rep info) - [(pair) - (let ([p (cons (get-name (car (info-lambda-fv* info))) - (get-name (cadr (info-lambda-fv* info))))]) - (ctci-closure-fv-names-set! ctci p) - p)] - [(vector) - (let ([v (list->vector (map get-name (info-lambda-fv* info)))]) - (ctci-closure-fv-names-set! ctci v) - v)] - [else #f])))) - (cond - [(info-lambda-ctci info) => - (lambda (ctci) - (ctci-live-set! ctci - (let f ([i 0] [spillable* spillable*]) - (if (null? spillable*) - (make-vector i) - (let ([spillable (car spillable*)]) - (cond - [(and (uvar-spilled? spillable) (uvar-source spillable)) => - (lambda (source) - (if (eq? source (let () (include "types.ss") cpsymbol)) - (case (info-lambda-closure-rep info) - [(singleton) - (cond - [(uvar-source (car (info-lambda-fv* info))) => - (lambda (source) - (let ([v (f (fx+ i 1) (cdr spillable*))]) - (uvar-iii-set! spillable i) - (vector-set! v i (cons (unannotate source) (fv-offset (uvar-location spillable)))) - v))] - [else (f i (cdr spillable*))])] - [(pair vector) - (let ([v (f (fx+ i 1) (cdr spillable*))]) - (uvar-iii-set! spillable i) - (vector-set! v i - (cons (get-closure-fv-names info ctci) - (fv-offset (uvar-location spillable)))) - v)] - [(closure) - (let ([v (f (fx+ i 1) (cdr spillable*))]) - (uvar-iii-set! spillable i) - (vector-set! v i (cons (unannotate source) (fv-offset (uvar-location spillable)))) - v)] - [else (f i (cdr spillable*))]) - (let ([v (f (fx+ i 1) (cdr spillable*))]) - (uvar-iii-set! spillable i) - (vector-set! v i (cons (unannotate source) (fv-offset (uvar-location spillable)))) - v)))] - [else (f i (cdr spillable*))]))))))]))) - - (define-pass finalize-register-locations! : (L15d Dummy) (ir block*) -> (L15e Dummy) () - (definitions - (define var->loc - (lambda (x) - (if (uvar? x) - (or (uvar-location x) (sorry! who "no location assigned to uvar ~s" x)) - x)))) - (Lvalue : Lvalue (ir) -> Lvalue () - [(mref ,x0 ,x1 ,imm) `(mref ,(var->loc x0) ,(var->loc x1) ,imm)] - [,x (var->loc x)]) - (Pred : Pred (ir) -> Pred ()) - (Tail : Tail (ir) -> Tail ()) - (Effect : Effect (ir) -> Effect () - [(set! ,live-info ,[lvalue] ,[rhs]) `(set! ,lvalue ,rhs)]) - (foldable-Effect : Effect (ir new-effect*) -> * (new-effect*) - [(move-related ,x1 ,x2) new-effect*] - [(set! ,live-info ,x0 ,x1) - (let ([x0 (var->loc x0)] [x1 (var->loc x1)]) - (if (eq? x0 x1) - new-effect* - (cons (Effect ir) new-effect*)))] - [else (cons (Effect ir) new-effect*)]) - (begin - (for-each - (lambda (block) - (block-effect*-set! block (fold-right foldable-Effect '() (block-effect* block))) - (cond - [(or (goto-block? block) (joto-block? block) (newframe-block? block)) (void)] - [(if-block? block) (if-block-pred-set! block (Pred (if-block-pred block)))] - [(tail-block? block) (tail-block-tail-set! block (Tail (tail-block-tail block)))] - [else (sorry! who "unrecognized block ~s" block)])) - block*) - `(dummy))) - - (define-pass expose-overflow-check-blocks! : (L15e Dummy) (ir entry-block0* block0*) -> (L16 Dummy) (entry-block* block*) - (definitions - (define block* block0*) - (define entry-block* entry-block0*) - (define-who redirect-link! - (lambda (old new) - (lambda (from) - (cond - [(goto-block? from) - (cond - [(eq? (goto-block-next from) old) (goto-block-next-set! from new)] - [else (sorry! who "goto-block in-link not found")])] - [(joto-block? from) - (cond - [(eq? (joto-block-next from) old) (joto-block-next-set! from new)] - [else (sorry! who "joto-block in-link not found")])] - [(if-block? from) - (cond - [(eq? (if-block-true from) old) (if-block-true-set! from new)] - [(eq? (if-block-false from) old) (if-block-false-set! from new)] - [else (sorry! who "if-block in-link not found")])] - [(newframe-block? from) - (cond - [(eq? (newframe-block-next from) old) (newframe-block-next-set! from new)] - [(eq? (newframe-block-rp from) old) (newframe-block-rp-set! from new)] - [(memq old (newframe-block-rp* from)) (newframe-block-rp*-set! from (subst new old (newframe-block-rp* from)))] - [else (sorry! who "newframe-block in-link not found")])] - [else (sorry! who "unexpected block ~s" from)])))) - (define insert-check! - (lambda (block rebefore* p ehere* eafter*) - (let ([libcall-block (make-goto-block)]) - (goto-block-next-set! libcall-block block) - (block-pariah! libcall-block #t) - (let ([check-block (make-if-block block libcall-block)]) - (if-block-pred-set! check-block p) - (block-effect*-set! check-block (reverse rebefore*)) - (block-effect*-set! libcall-block ehere*) - (set! entry-block* (subst check-block block entry-block*)) - (let ([label (block-label block)]) - (block-label-set! check-block label) - (local-label-block-set! label check-block)) - (let ([label (make-local-label 'post-overflow-check)]) - (block-label-set! block label) - (local-label-block-set! label block)) - (let ([label (make-local-label 'overflowed)]) - (block-label-set! libcall-block label) - (local-label-block-set! label libcall-block)) - (for-each (redirect-link! block check-block) (block-in-link* block)) - (block-in-link*-set! block (list check-block libcall-block)) - (set! block* (cons* check-block libcall-block block*)) - (Effect* block '() eafter*))))) - (define Effect* - (lambda (block rebefore* eafter*) - (if (null? eafter*) - (block-effect*-set! block (reverse rebefore*)) - (let ([e (car eafter*)] [eafter* (cdr eafter*)]) - (nanopass-case (L15e Effect) e - [(overflow-check ,[Pred : p] ,[Effect : e*] ...) (insert-check! block rebefore* p e* eafter*)] - [else (Effect* block (cons (Effect e) rebefore*) eafter*)])))))) - (Pred : Pred (ir) -> Pred ()) - (Tail : Tail (ir) -> Tail ()) - (Effect : Effect (ir) -> Effect ()) - ; NB: without the begin, seems to ignore all but the first subform below - (begin - (for-each - (lambda (block) - (Effect* block '() (block-effect* block)) - (cond - [(or (goto-block? block) (joto-block? block) (newframe-block? block)) (void)] - [(if-block? block) (if-block-pred-set! block (Pred (if-block-pred block)))] - [(tail-block? block) (tail-block-tail-set! block (Tail (tail-block-tail block)))] - [else (sorry! who "unrecognized block ~s" block)])) - block0*) - (values `(dummy) entry-block* block*))) - - (define-syntax with-live-info-record-writer - (lambda (x) - (syntax-case x () - [(_ live-size varvec e1 e2 ...) - #'(parameterize ([(case-lambda - [() (record-writer (record-type-descriptor live-info))] - [(x) (record-writer (record-type-descriptor live-info) x)]) - (lambda (x p wr) - (when (live-info-useless x) (fprintf p "useless ")) - (fprintf p ""))]) - e1 e2 ...)]))) - - (define-pass np-allocate-registers : L15a (ir) -> L16 () - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info ,max-fv0 (,local* ...) (,entry-block* ...) (,block* ...)) - (let () - (define block-printer - (lambda (unparser name block*) - (p-dot-graph block* (current-output-port)) - (p-graph block* name (current-output-port) unparser))) - (module (RApass) - (define RAprinter - (lambda (unparser) - (lambda (val*) - (block-printer unparser (info-lambda-name info) block*)))) - (define-syntax RApass - (lambda (x) - (syntax-case x () - [(_ ?unparser pass-name ?arg ...) - #'(xpass pass-name (RAprinter ?unparser) (list ?arg ...))])))) - (safe-assert (andmap (lambda (x) (eq? (uvar-location x) #f)) local*)) - (let ([kspillable (length local*)] [kfv (fx+ max-fv0 1)] [kreg (vector-length regvec)]) - (fluid-let ([spillable* local*] [unspillable* '()] [max-fv max-fv0] [max-fs@call 0] [poison-cset (make-empty-cset kspillable)]) - (let* ([live-size (fx+ kfv kreg kspillable)] [varvec (make-vector live-size)]) - ; set up var indices & varvec mapping from indices to vars - (fold-left (lambda (i x) (var-index-set! x i) (vector-set! varvec i x) (fx+ i 1)) 0 spillable*) - (do ([i 0 (fx+ i 1)]) ((fx= i kfv)) (let ([fv (get-fv i)] [i (fx+ i kspillable)]) (var-index-set! fv i) (vector-set! varvec i fv))) - (do ([i 0 (fx+ i 1)]) ((fx= i kreg)) (let ([reg (vector-ref regvec i)] [i (fx+ i kspillable kfv)]) (var-index-set! reg i) (vector-set! varvec i reg))) - (with-live-info-record-writer live-size varvec - ; run intra/inter-block live analysis - (RApass unparse-L15a do-live-analysis! live-size entry-block*) - ; this is worth enabling from time to time... - #;(check-entry-live! (info-lambda-name info) live-size varvec entry-block*) - ; rerun intra-block live analysis and record (fv v reg v spillable) x spillable conflicts - (RApass unparse-L15a record-call-live! block* varvec) - ;; NB: we could just use (vector-length varvec) to get live-size - (when (fx> kspillable 1000) ; NB: parameter? - (RApass unparse-L15a identify-poison! kspillable varvec live-size block*)) - (RApass unparse-L15a do-spillable-conflict! kspillable kfv varvec live-size block*) - #;(show-conflicts (info-lambda-name info) varvec '#()) - ; find frame homes for call-live variables; adds new fv x spillable conflicts - (RApass unparse-L15a assign-frame! (filter uvar-spilled? spillable*)) - #;(show-homes) - (RApass unparse-L15a record-inspector-information! info) - ; determine frame sizes at nontail-call sites and assign homes to new-frame variables - ; adds new fv x spillable conflicts - (let ([dummy (RApass unparse-L15b assign-new-frame! (with-output-language (L15a Dummy) `(dummy)) info live-size varvec block*)]) - ; record fp offset on entry to each block - (RApass unparse-L15b record-fp-offsets! entry-block*) - ; assign frame homes to poison variables - (let ([spill* (filter (lambda (x) (and (not (uvar-location x)) (uvar-poison? x))) spillable*)]) - (unless (null? spill*) - (for-each (lambda (x) (uvar-spilled! x #t)) spill*) - (RApass unparse-L15b assign-frame! spill*))) - ; on entry to loop, have assigned call-live and new-frame variables to frame homes, determined frame sizes, and computed block-entry fp offsets - (let ([saved-reg-csets (vector-map (lambda (reg) (cset-copy (var-spillable-conflict* reg))) regvec)] - [bcache* (map cache-block-info block*)]) - (let loop () - (for-each - (lambda (spill) - ; remove each spill from each other spillable's spillable conflict set - (unless (uvar-poison? spill) - (let ([spill-index (var-index spill)]) - (cset-for-each (var-spillable-conflict* spill) - (lambda (i) - (let ([x (vector-ref varvec i)]) - (unless (uvar-location x) - (conflict-bit-unset! (var-spillable-conflict* x) spill-index))))))) - ; release the spill's conflict* set - (var-spillable-conflict*-set! spill #f)) - (filter uvar-location spillable*)) - (set! spillable* (remp uvar-location spillable*)) - (let ([saved-move* (map uvar-move* spillable*)]) - #;(show-homes) - (let ([dummy (RApass unparse-L15c finalize-frame-locations! dummy block*)]) - (let ([dummy (RApass unparse-L15d select-instructions! dummy block* live-size - (let ([libspec (info-lambda-libspec info)]) - (and libspec (libspec-does-not-expect-headroom? libspec))))]) - (vector-for-each (lambda (reg) (reg-precolored-set! reg #f)) regvec) - (let* ([kunspillable (length unspillable*)] [unvarvec (make-vector kunspillable)]) - ; set up var indices & unvarvec mapping from indices to unspillables - (fold-left (lambda (i x) (var-index-set! x i) (vector-set! unvarvec i x) (fx+ i 1)) 0 unspillable*) - ; rerun intra-block live analysis and record (reg v spillable v unspillable) x unspillable conflicts - (RApass unparse-L15d do-unspillable-conflict! kfv kspillable varvec live-size kunspillable unvarvec block*) - #;(show-conflicts (info-lambda-name info) varvec unvarvec) - (RApass unparse-L15d assign-registers! info varvec unvarvec) - ; release the unspillable conflict sets - (for-each (lambda (x) (var-unspillable-conflict*-set! x #f)) spillable*) - (vector-for-each (lambda (x) (var-unspillable-conflict*-set! x #f)) regvec) - #;(show-homes unspillable*) - (if (everybody-home?) - (let ([dummy (RApass unparse-L15e finalize-register-locations! dummy block*)]) - ; release the spillable conflict sets - (vector-for-each (lambda (reg) (var-spillable-conflict*-set! reg #f)) regvec) - (do ([i max-fv (fx- i 1)]) ((fx< i 0)) (var-spillable-conflict*-set! (get-fv i) #f)) - (let-values ([(dummy entry-block* block*) - (xpass expose-overflow-check-blocks! - (lambda (val*) - (apply (lambda (dummy entry-block* block*) - (block-printer unparse-L16 (info-lambda-name info) block*)) - val*)) - (list dummy entry-block* block*))]) - (safe-assert (andmap block-label (append entry-block* block*))) - (safe-assert (lambda (b) (eq? (local-label-block (block-label b)) b)) (append entry-block* block*)) - `(lambda ,info (,entry-block* ...) (,block* ...)))) - (begin - (for-each restore-block-info! block* bcache*) - (vector-for-each var-spillable-conflict*-set! regvec saved-reg-csets) - (for-each (lambda (x) (uvar-location-set! x #f)) spillable*) - (for-each uvar-move*-set! spillable* saved-move*) - (set! unspillable* '()) - (RApass unparse-L15b assign-frame! (filter uvar-spilled? spillable*)) - (loop)))))))))))))))]))) - - ; NB: commonize with earlier - (define-pass np-remove-repeater-blocks-again! : L16 (ir) -> L16 () - (definitions - (define path-compress! - (lambda (b) - (cond - [(block-repeater? b) (goto-block-next b)] - ; NB: ignoring block-src* here, post-profiling - [(and (goto-block? b) (null? (block-effect* b))) - (block-repeater! b #t) - (let ([end (path-compress! (goto-block-next b))]) - (goto-block-next-set! b end) - end)] - [else b]))) - (define resolve - (lambda (b) - (if (block-repeater? b) - (goto-block-next b) - b)))) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info (,entry-block* ...) (,block* ...)) - (for-each path-compress! block*) - (for-each - (lambda (from) - (define resolve! - (lambda (get put!) - (let ([to (get from)]) - (when (block-repeater? to) - (put! from (goto-block-next to)))))) - (cond - [(goto-block? from) - (unless (block-repeater? from) - (resolve! goto-block-next goto-block-next-set!))] - [(joto-block? from) - (resolve! joto-block-next joto-block-next-set!)] - [(if-block? from) - (resolve! if-block-true if-block-true-set!) - (resolve! if-block-false if-block-false-set!)] - [(newframe-block? from) - (resolve! newframe-block-next newframe-block-next-set!) - (newframe-block-rp*-set! from (map resolve (newframe-block-rp* from))) - (resolve! newframe-block-rp newframe-block-rp-set!)] - [(tail-block? from) (void)] - [else (sorry! who "unrecognized block ~s" from)])) - block*) - (for-each (lambda (dcl) - (let* ([b0 (local-label-block dcl)] [b (and b0 (resolve b0))]) - (unless (eq? b b0) - (local-label-block-set! dcl b) - (block-label-set! b dcl)))) - (info-lambda-dcl* info)) - `(lambda ,info - (,(map resolve entry-block*) ...) - (,(filter (lambda (b) (or (not (block-repeater? b)) (eq? (goto-block-next b) b))) block*) ...))])) - - ; NB: might instead sort blocks in np-generate-code, which is in a better position - ; NB: to deal with block ordering when branch displacement sizes are limited - (define-pass np-optimize-block-order! : L16 (ir) -> L16 () - (definitions - (define invertible? - (lambda (pred) - (nanopass-case (L16 Pred) pred - [(asm ,info ,proc ,t* ...) - (safe-assert (info-condition-code? info)) - (info-condition-code-invertible? info)]))) - (define block-likeliness - (lambda (b) - (or (block-weight b) 0))) - (define block-in-degree - (lambda (b) - (fold-left (lambda (n b) (if (block-seen? b) n (fx+ n 1))) 0 (block-in-link* b))))) - (CaseLambdaExpr : CaseLambdaExpr (ir) -> CaseLambdaExpr () - [(lambda ,info (,entry-block* ...) (,block* ...)) - (safe-assert (not (ormap block-seen? block*))) - (safe-assert (not (null? entry-block*))) - (let loop ([b (car entry-block*)] [w* '()] [pariah* (cdr entry-block*)] [rblock* '()]) - (define next-worklist-entry - (lambda (w* pariah* rblock*) - (if (null? w*) - (if (null? pariah*) - (begin - (safe-assert (andmap block-label (append entry-block* rblock*))) - (safe-assert (lambda (b) (eq? (local-label-block (block-label b)) b)) (append entry-block* rblock*)) - (for-each (lambda (b) (block-seen! b #f)) block*) - `(lambda ,info (,entry-block* ...) (,(reverse rblock*) ...))) - (loop (car pariah*) '() (cdr pariah*) rblock*)) - (loop (car w*) (cdr w*) pariah* rblock*)))) - (if (block-seen? b) - (next-worklist-entry w* pariah* rblock*) - (let ([rblock* (cons b rblock*)]) - (block-seen! b #t) - (cond - [(goto-block? b) (loop (goto-block-next b) w* pariah* rblock*)] - [(joto-block? b) (loop (joto-block-next b) w* pariah* rblock*)] - [(if-block? b) - (let ([true (if-block-true b)] [false (if-block-false b)]) - (if (block-seen? true) - (loop false w* pariah* rblock*) - (if (block-seen? false) - (loop true w* pariah* rblock*) - (if (invertible? (if-block-pred b)) - (let ([llntrue (block-likeliness true)] [llnfalse (block-likeliness false)]) - (if (or (and (fx= llnfalse llntrue) - (fx< (block-in-degree false) (block-in-degree true))) - (fx< llntrue llnfalse)) - (if (fx< llntrue 0) - (loop false w* (cons true pariah*) rblock*) - (loop false (cons true w*) pariah* rblock*)) - (if (fx< llnfalse 0) - (loop true w* (cons false pariah*) rblock*) - (loop true (cons false w*) pariah* rblock*)))) - (if (fx< (block-likeliness false) 0) - (loop true w* (cons false pariah*) rblock*) - (loop true (cons false w*) pariah* rblock*))))))] - [(newframe-block? b) - (loop (newframe-block-next b) - (append (newframe-block-rp* b) (cons (newframe-block-rp b) w*)) - pariah* rblock*)] - [(tail-block? b) (next-worklist-entry w* pariah* rblock*)] - [else (sorry! who "unrecognized block ~s" b)]))))])) - - (define (np-after-calling-conventions ir) - (compose ir - (pass np-expand-hand-coded unparse-L13.5) - (pass np-expose-allocation-pointer unparse-L14) - (pass np-expose-basic-blocks unparse-L15a) - (pass np-remove-repeater-blocks! unparse-L15a) - (lambda (ir) - (if (and (or (eq? ($compile-profile) 'block) ($profile-block-data?)) ($sfd)) - ((pass np-add-block-source! unparse-L15a) ir) - ir)) - (pass np-propagate-pariahty! unparse-L15a) - (lambda (ir) - (if (or (eq? ($compile-profile) 'source) - (and (eq? ($compile-profile) 'block) ($sfd))) - ((pass np-insert-profiling unparse-L15a) ir) - ir)) - (pass np-add-in-links! unparse-L15a) - (pass np-compute-loop-depth! unparse-L15a) - (pass np-weight-references! unparse-L15a) - np-allocate-registers ; aggregate pass...don't use pass macro, or it will show up in timings - (pass np-remove-repeater-blocks-again! unparse-L16) - (pass np-optimize-block-order! unparse-L16) - (pass np-generate-code))) - - (set! $np-compile - (lambda (original-input-expression pt?) - (with-initialized-registers - (fluid-let ([frame-vars (make-vector 8 #f)] - [next-lambda-seqno 0] - [pass-time? pass-time?]) - (compose original-input-expression - (pass cpnanopass unparse-L1) - (pass np-recognize-let unparse-L2) - (pass np-discover-names unparse-L3) - #;(lambda (ir) (unless (eqv? (optimize-level) 3) ((pass np-check-flags) ir)) ir) - (pass np-convert-assignments unparse-L4) - (pass np-sanitize-bindings unparse-L4) - (pass np-suppress-procedure-checks unparse-L4) - (pass np-recognize-mrvs unparse-L4.5) - (pass np-expand-foreign unparse-L4.75) - (pass np-recognize-loops unparse-L4.875) - (pass np-name-anonymous-lambda unparse-L5) - (pass np-convert-closures unparse-L6) - (pass np-optimize-direct-call unparse-L6) - (pass np-identify-scc unparse-L6) - (if ($optimize-closures) - (pass np-expand/optimize-closures unparse-L7) - (pass np-expand-closures unparse-L7)) - (lambda (ir) - (if (fxzero? ($loop-unroll-limit)) - ir - ((pass np-profile-unroll-loops unparse-L7) ir))) - (pass np-simplify-if unparse-L7) - (pass np-expand-primitives unparse-L9) - (pass np-place-overflow-and-trap unparse-L9.5) - (pass np-rebind-on-ruined-path unparse-L9.5) - (pass np-finalize-loops unparse-L9.75) - (pass np-optimize-pred-in-value unparse-L9.75) - (pass np-remove-complex-opera* unparse-L10) - (pass np-push-mrvs unparse-L10.5) - (pass np-normalize-context unparse-L11) - (pass np-insert-trap-check unparse-L11.5) - (pass np-flatten-case-lambda unparse-L12) - (pass np-impose-calling-conventions unparse-L13) - np-after-calling-conventions))))) - - (set! $np-boot-code - (lambda (which) - (with-initialized-registers - ($c-func-code-record - (fluid-let ([frame-vars (make-vector 8 #f)] - [next-lambda-seqno 0] - [pass-time? #t]) - (parameterize ([generate-inspector-information #f] [$compile-profile #f]) - (np-after-calling-conventions - (with-output-language (L13 Program) - (let ([l (make-local-label 'Linvoke)]) - `(labels ([,l (hand-coded ,which)]) ,l)))))))))) - ) - - (set! $np-tracer tracer) - - (set! $np-last-pass last-pass) - - (set! $track-dynamic-closure-counts track-dynamic-closure-counts) - - (set! $track-static-closure-counts track-static-closure-counts) - - (set! $optimize-closures (make-parameter #t (lambda (x) (and x #t)))) -) diff --git a/ta6ob/s/cpnanopass.ta6ob b/ta6ob/s/cpnanopass.ta6ob deleted file mode 100644 index dc68a07..0000000 Binary files a/ta6ob/s/cpnanopass.ta6ob and /dev/null differ diff --git a/ta6ob/s/cprep.ss b/ta6ob/s/cprep.ss deleted file mode 100644 index 9b1f4bd..0000000 --- a/ta6ob/s/cprep.ss +++ /dev/null @@ -1,305 +0,0 @@ -;;; cprep.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - - -(let () - (import (nanopass)) - (include "types.ss") - (include "base-lang.ss") - (include "expand-lang.ss") - - (define-who Lexpand-to-go - (lambda (x go) - (define-pass go-Inner : (Lexpand Inner) (ir) -> * (val) - (Inner : Inner (ir) -> * (val) - [,lsrc (go lsrc)] - [(program ,uid ,body) (go ($build-invoke-program uid body))] - [(library/ct ,uid (,export-id* ...) ,import-code ,visit-code) - (go ($build-install-library/ct-code uid export-id* import-code visit-code))] - [(library/rt ,uid (,dl* ...) (,db* ...) (,dv* ...) (,de* ...) ,body) - (go ($build-install-library/rt-code uid dl* db* dv* de* body))] - [(library/ct-info ,linfo/ct) - `(library/ct-info ,(library-info-uid linfo/ct) ,(library/ct-info-import-req* linfo/ct) - ,(library/ct-info-visit-visit-req* linfo/ct) - ,(library/ct-info-visit-req* linfo/ct))] - [(library/rt-info ,linfo/rt) `(library/rt-info ,(library-info-uid linfo/rt) ,(library/rt-info-invoke-req* linfo/rt))] - [(program-info ,pinfo) `(program-info ,(program-info-invoke-req* pinfo))]) - (Inner ir)) - (let ([x* (let f ([x x] [x* '()]) - (nanopass-case (Lexpand Outer) x - [(group ,outer1 ,outer2) (f outer1 (f outer2 x*))] - [(visit-only ,inner) (cons `(eval-when (visit) ,(go-Inner inner)) x*)] - [(revisit-only ,inner) (cons `(eval-when (revisit) ,(go-Inner inner)) x*)] - [,inner (cons (go-Inner inner) x*)] - [(recompile-info ,rcinfo) (cons `(recompile-requirements ,(recompile-info-import-req* rcinfo) ,(recompile-info-include-req* rcinfo)) x*)] - [else (sorry! who "unexpected language form ~s" x)]))]) - (safe-assert (not (null? x*))) - (cond - [(= (length x*) 1) (car x*)] - [else `(begin ,@x*)])))) - - (set-who! $uncprep - (rec $uncprep - (case-lambda - [(x) ($uncprep x #f)] - [(x sexpr?) - (define cache-sexpr - (lambda (preinfo thunk) - (if sexpr? - (or (preinfo-sexpr preinfo) - (let ([sexpr (thunk)]) - (preinfo-sexpr-set! preinfo sexpr) - sexpr)) - (thunk)))) - (define get-name - (lambda (x) - (if sexpr? (prelex-name x) (prelex-uname x)))) - (define uncprep-lambda-clause - (lambda (cl) - (nanopass-case (Lsrc CaseLambdaClause) cl - [(clause (,x* ...) ,interface ,body) - `(,(if (fx< interface 0) - (let f ((x* x*)) - (if (pair? (cdr x*)) - (cons (get-name (car x*)) (f (cdr x*))) - (get-name (car x*)))) - (map get-name x*)) - ,@(uncprep-sequence body '()))]))) - (define uncprep-sequence - (lambda (x ls) - (nanopass-case (Lsrc Expr) x - [(profile ,src) (guard (not (null? ls))) ls] - [(seq ,e1 ,e2) - (uncprep-sequence e1 - (uncprep-sequence e2 ls))] - [else (cons (uncprep x) ls)]))) - (define uncprep-fp-conv - (lambda (x*) - (map (lambda (x) - (case x - [(i3nt-stdcall) '__stdcall] - [(i3nt-com) '__com] - [(adjust-active) '__collect_safe] - [else #f])) - x*))) - (define-who uncprep-fp-specifier - (lambda (x) - (nanopass-case (Ltype Type) x - [(fp-void) 'void] - [(fp-integer ,bits) - (case bits - [(8) 'integer-8] - [(16) 'integer-16] - [(32) 'integer-32] - [(64) 'integer-64] - [else ($oops who "invalid integer size ~s" bits)])] - [(fp-unsigned ,bits) - (case bits - [(8) 'unsigned-8] - [(16) 'unsigned-16] - [(32) 'unsigned-32] - [(64) 'unsigned-64] - [else ($oops who "invalid unsigned size ~s" bits)])] - [(fp-scheme-object) 'scheme-object] - [(fp-u8*) 'u8*] - [(fp-u16*) 'u16*] - [(fp-u32*) 'u32*] - [(fp-fixnum) 'fixnum] - [(fp-double-float) 'double-float] - [(fp-single-float) 'single-float] - [(fp-ftd ,ftd) 'ftype] - [(fp-ftd& ,ftd) 'ftype]))) - (define uncprep - (lambda (x) - (define keyword? - (lambda (x) - (memq x - ; UPDATE THIS if new keywords are added - '(let $primitive quote begin case-lambda - library-case-lambda lambda if set! - letrec letrec* $foreign-procedure - $foreign-callable eval-when)))) - (nanopass-case (Lsrc Expr) x - [(ref ,maybe-src ,x) (get-name x)] - [(call ,preinfo0 (case-lambda ,preinfo1 (clause (,x* ...) ,interface ,body)) ,e* ...) - (guard (fx= (length e*) interface)) - (cache-sexpr preinfo0 - (lambda () - (if (null? x*) - (uncprep body) - `(let ,(map (lambda (x e) - `(,(get-name x) ,(uncprep e))) - x* e*) - ,@(uncprep-sequence body '())))))] - [(call ,preinfo ,pr (quote ,d)) - (guard (eq? (primref-name pr) '$top-level-value) (symbol? d) - (not (or (eq? ($real-sym-name d (interaction-environment)) d) (keyword? d)))) - (cache-sexpr preinfo - (lambda () - ($real-sym-name d (interaction-environment))))] - [(call ,preinfo ,pr (quote ,d) ,e) - (guard (eq? (primref-name pr) '$set-top-level-value!) (symbol? d) - (not (or (eq? ($real-sym-name d (interaction-environment)) d) (keyword? d)))) - (cache-sexpr preinfo - (lambda () - `(set! ,($real-sym-name d (interaction-environment)) ,(uncprep e))))] - [(call ,preinfo ,e ,e* ...) - (cache-sexpr preinfo - (lambda () - `(,(uncprep e) ,@(map uncprep e*))))] - [,pr (let ([sym (primref-name pr)]) - (if sexpr? - ($sgetprop sym '*unprefixed* sym) - `($primitive ,(primref-level pr) ,sym)))] - [(quote ,d) - (cond - [(eq? d (void)) '(#2%void)] - [(self-evaluating? d) d] - [else `(quote ,d)])] - [(seq ,e1 ,e2) - (let ([ls (uncprep-sequence x '())]) - (if (null? (cdr ls)) - (car ls) - `(begin ,@ls)))] - [(case-lambda ,preinfo ,cl* ...) - (cache-sexpr preinfo - (lambda () - (let ((cl* (map uncprep-lambda-clause cl*))) - (if (and (not (null? cl*)) (null? (cdr cl*))) - `(lambda ,@(car cl*)) - `(case-lambda ,@cl*)))))] - [(if ,[e0] ,[e1] ,[e2]) `(if ,e0 ,e1 ,e2)] - [(set! ,maybe-src ,x ,[e]) `(set! ,(get-name x) ,e)] - [(letrec ([,x* ,[e*]] ...) ,body) - `(letrec ,(map (lambda (x e) `(,(get-name x) ,e)) x* e*) - ,@(uncprep-sequence body '()))] - [(letrec* ([,x* ,[e*]] ...) ,body) - `(letrec* ,(map (lambda (x e) `(,(get-name x) ,e)) x* e*) - ,@(uncprep-sequence body '()))] - [(foreign (,conv* ...) ,name ,[e] (,arg-type* ...) ,result-type) - `($foreign-procedure ,(uncprep-fp-conv conv*) ,name ,e - ,(map uncprep-fp-specifier arg-type*) - ,(uncprep-fp-specifier result-type))] - [(fcallable (,conv* ...) ,[e] (,arg-type* ...) ,result-type) - `($foreign-callable ,(uncprep-fp-conv conv*) ,e - ,(map uncprep-fp-specifier arg-type*) - ,(uncprep-fp-specifier result-type))] - [(record-ref ,rtd ,type ,index ,[e]) `(record-ref ,rtd ',type ,e ,index)] - [(record-set! ,rtd ,type ,index ,[e1] ,[e2]) `(record-set! ,rtd ',type ,e1 ,index ,e2)] - [(record ,rtd ,[rtd-expr] ,[e*] ...) `(record ,rtd ,rtd-expr ,@e*)] - [(record-type ,rtd ,[e]) `(record-type ,rtd ,e)] - [(record-cd ,rcd ,rtd-expr ,[e]) `(record-cd ,rcd ,e)] - [(immutable-list (,e* ...) ,[e]) e] - [(moi) ''moi] - [(pariah) `(pariah (void))] - [(profile ,src) `(void)] - [(cte-optimization-loc ,box ,[e]) e] - ; for debugging: - [(cpvalid-defer ,[e]) `(cpvalid-defer ,e)] - [else ($oops who "unexpected record ~s" x)]))) - (Lexpand-to-go x uncprep)]))) - - (let () - (define (default-env) - (if (eq? (subset-mode) 'system) - ($system-environment) - (interaction-environment))) - (define e/o - (lambda (who cte? x env) - (define (go x) - ($uncprep - ($cpcommonize - ($cpcheck - (let ([cpletrec-ran? #f]) - (let ([x ((run-cp0) - (lambda (x) - (set! cpletrec-ran? #t) - ($cpletrec ($cp0 x $compiler-is-loaded?))) - ($cpvalid x))]) - (if cpletrec-ran? x ($cpletrec x)))))))) - (unless (environment? env) - ($oops who "~s is not an environment" env)) - ; claim compiling-a-file to get cte as well as run-time code - (Lexpand-to-go (expand x env #t cte?) go))) - (set-who! expand/optimize - (case-lambda - [(x) (e/o who #f x (default-env))] - [(x env) (e/o who #f x env)])) - (set-who! $expand/cte/optimize - (case-lambda - [(x) (e/o who #t x (default-env))] - [(x env) (e/o who #t x env)])) - (set-who! $expand/cte - (rec expand/cte - (case-lambda - [(x) (expand/cte x (default-env))] - [(x env) - (unless (environment? env) - ($oops who "~s is not an environment" env)) - ; claim compiling-a-file to get cte as well as run-time code - ($uncprep (expand x env #t #t))])))) - - (set-who! $cpcheck-prelex-flags - (lambda (x after-pass) - (import (nanopass)) - (include "base-lang.ss") - - (define-pass cpcheck-prelex-flags : Lsrc (ir) -> Lsrc () - (definitions - #;(define sorry! - (lambda (who str . arg*) - (apply fprintf (console-output-port) str arg*) - (newline (console-output-port)))) - (define initialize-id! - (lambda (id) - (prelex-flags-set! id - (let ([flags (prelex-flags id)]) - (fxlogor - (fxlogand flags (constant prelex-sticky-mask)) - (fxsll (fxlogand flags (constant prelex-is-mask)) - (constant prelex-was-flags-offset)))))))) - (Expr : Expr (ir) -> Expr () - [(ref ,maybe-src ,x) - (when (prelex-operand x) (sorry! who "~s has an operand after ~s (src ~s)" x after-pass maybe-src)) - (unless (prelex-was-referenced x) (sorry! who "~s referenced but not so marked after ~s (src ~s)" x after-pass maybe-src)) - (when (prelex-referenced x) - (unless (prelex-was-multiply-referenced x) (sorry! who "~s multiply referenced but not so marked after ~s (src ~s)" x after-pass maybe-src)) - (set-prelex-multiply-referenced! x #t)) - (set-prelex-referenced! x #t) - `(ref ,maybe-src ,x)] - [(set! ,maybe-src ,x ,[e]) - (unless (prelex-was-assigned x) (sorry! who "~s assigned but not so marked after ~s (src ~s)" x after-pass maybe-src)) - (set-prelex-assigned! x #t) - `(set! ,maybe-src ,x ,e)] - [(letrec ([,x* ,e*] ...) ,body) - (for-each initialize-id! x*) - `(letrec ([,x* ,(map Expr e*)] ...) ,(Expr body))] - [(letrec* ([,x* ,e*] ...) ,body) - (for-each initialize-id! x*) - `(letrec* ([,x* ,(map Expr e*)] ...) ,(Expr body))]) - (CaseLambdaClause : CaseLambdaClause (ir) -> CaseLambdaClause () - [(clause (,x* ...) ,interface ,body) - (for-each initialize-id! x*) - `(clause (,x* ...) ,interface ,(Expr body))])) - (Lexpand-to-go x cpcheck-prelex-flags))) - - (set-who! $insert-profile-src! ; called from compiler only - (lambda (st x) - ; NB: the output should be *, but nanopass won't autogenerate the pass - (define-pass record-coverage-info! : Lsrc (ir) -> Lsrc () - (Expr : Expr (ir) -> Expr () - [(profile ,src) (source-table-set! st src 0) `(profile ,src)])) - (Lexpand-to-go x record-coverage-info!))) - ) diff --git a/ta6ob/s/cprep.ta6ob b/ta6ob/s/cprep.ta6ob deleted file mode 100644 index 3ba9c27..0000000 Binary files a/ta6ob/s/cprep.ta6ob and /dev/null differ diff --git a/ta6ob/s/cpvalid.ss b/ta6ob/s/cpvalid.ss deleted file mode 100644 index e01d12a..0000000 --- a/ta6ob/s/cpvalid.ss +++ /dev/null @@ -1,564 +0,0 @@ -;;; cpvalid.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; see comments relating to both cpvalid and cpletrec at front of -;;; cpletrec.ss - -(begin -(define undefined-variable-warnings - ($make-thread-parameter #f (lambda (x) (and x #t)))) - -(let () - (import (nanopass)) - (include "base-lang.ss") - - (define-pass cpvalid : Lsrc (x) -> Lsrc () - (definitions - (with-output-language (Lsrc Expr) - (define build-let - (lambda (ids vals body) - (if (null? ids) - body - `(call ,(make-preinfo) - (case-lambda ,(make-preinfo-lambda) - (clause (,ids ...) ,(length ids) ,body)) - ,vals ...)))) - (define build-letrec - (lambda (ids vals body) - (if (null? ids) - ; dropping source here; could attach to body or add source record - body - `(letrec ([,ids ,vals] ...) ,body)))) - (define build-letrec* - (lambda (ids vals body) - (if (null? ids) - ; dropping source here; could attach to body or add source record - body - `(letrec* ([,ids ,vals] ...) ,body))))) - - (define-record-type proxy - (fields (mutable state)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda () - (new 'protectable))))) - - (define-syntax with-protected - (syntax-rules () - [(_ p e) - (identifier? #'p) - (begin - (when p (proxy-state-set! p 'protected)) - (let-values ([t (let () - (define-syntax p - (lambda (x) - (syntax-error x "can't reference proxy inside with-protected"))) - e)]) - (when p (proxy-state-set! p 'protectable)) - (apply values t)))])) - - (define-syntax with-unprotected - (syntax-rules () - [(_ p e) - (identifier? #'p) - (begin - (when p (proxy-state-set! p 'unprotected)) - (let-values ([t (let () - (define-syntax p - (lambda (x) - (syntax-error x "can't reference proxy inside with-unprotected"))) - e)]) - (when p (proxy-state-set! p 'protectable)) - (apply values t)))])) - - (module (with-info with-valid* with-valid** with-proxy with-proxy* - prelex-info-proxy prelex-info-valid-flag - set-prelex-info-unsafe! prelex-info-unsafe - set-prelex-info-referenced! prelex-info-referenced) - (define-record-type info - (fields (mutable proxy) (mutable unsafe) (mutable valid-flag) (mutable referenced)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda () - (new #f #f #f #f))))) - - (define-syntax with-info - (syntax-rules () - [(_ ids-expr e) - (let ([ids ids-expr]) - (for-each - (lambda (id) - (safe-assert (not (prelex-operand id))) - (prelex-operand-set! id (make-info))) - ids) - (let-values ([t e]) - (for-each - (lambda (id) - (safe-assert (prelex-operand id)) - (prelex-operand-set! id #f)) - ids) - (apply values t)))])) - - (define set-prelex-info-valid-flag! - (lambda (id val) - (info-valid-flag-set! (prelex-operand id) val))) - - (define prelex-info-valid-flag - (lambda (id) - (let ([info (prelex-operand id)]) - (and info (info-valid-flag info))))) - - (define-syntax with-valid* - (syntax-rules () - [(_ valid-flag-expr ids-expr e) - (let ([valid-flag valid-flag-expr] [ids ids-expr]) - (for-each (lambda (id) (set-prelex-info-valid-flag! id valid-flag)) ids) - (let-values ([t e]) - (for-each (lambda (id) (set-prelex-info-valid-flag! id #f)) ids) - (apply values t)))])) - - (define-syntax with-valid** - (syntax-rules () - [(_ valid-flags-expr ids-expr e) - (let ([valid-flags valid-flags-expr] [ids ids-expr]) - (for-each (lambda (id vf) (set-prelex-info-valid-flag! id vf)) ids valid-flags) - (let-values ([t e]) - (for-each (lambda (id) (set-prelex-info-valid-flag! id #f)) ids) - (apply values t)))])) - - (define-who set-prelex-info-proxy! - (lambda (id val) - (let ([info (prelex-operand id)]) - (safe-assert info) - (info-proxy-set! info val)))) - - (define prelex-info-proxy - (lambda (id) - (let ([info (prelex-operand id)]) - (and info (info-proxy info))))) - - (define-syntax with-proxy - (syntax-rules () - [(_ proxy-expr id-expr e) - (let ([proxy proxy-expr] [id id-expr]) - (set-prelex-info-proxy! id proxy) - (let ([t e]) - (set-prelex-info-proxy! id #f) - t))])) - - (define-syntax with-proxy* - (syntax-rules () - [(_ proxy-expr ids-expr e) - (let ([proxy proxy-expr] [ids ids-expr]) - (for-each (lambda (id) (set-prelex-info-proxy! id proxy)) ids) - (let-values ([t e]) - (for-each (lambda (id) (set-prelex-info-proxy! id #f)) ids) - (apply values t)))])) - - (define set-prelex-info-unsafe! - (lambda (id val) - (info-unsafe-set! (prelex-operand id) val))) - - (define prelex-info-unsafe - (lambda (id) - (info-unsafe (prelex-operand id)))) - - (define set-prelex-info-referenced! - (lambda (id val) - (let ([info (prelex-operand id)]) - (when info (info-referenced-set! info val))))) - - (define prelex-info-referenced - (lambda (id) - (info-referenced (prelex-operand id))))) - - (with-output-language (Lsrc Expr) - (define insert-valid-check - (lambda (what maybe-src id p x) - (if (and p (not (eq? (proxy-state p) 'protected))) - (let ([valid-flag (prelex-info-valid-flag id)]) - (if valid-flag - (let ([name (prelex-name id)]) - (let ([mesg (format "attempt to ~a undefined variable ~~s" what)]) - (when (undefined-variable-warnings) - ($source-warning #f maybe-src #t (format "possible ~a" mesg) name)) - (if (prelex-referenced valid-flag) - (set-prelex-multiply-referenced! valid-flag #t) - (set-prelex-referenced! valid-flag #t)) - `(seq - (if (ref #f ,valid-flag) - (quote ,(void)) - (call ,(make-preinfo) ,(lookup-primref 2 '$source-violation) - (quote #f) - (quote ,maybe-src) - (quote #t) - (quote ,mesg) - (quote ,name))) - ,x))) - x)) - x)))) - - ; wl = worklist - ; dl = deferred list - (define (process-letrec-bindings cpvalid proxy proxy-ids ids vals unsafe* dl?) - (let f ([wl (map list ids vals unsafe*)] [dl '()] [oops #f]) - (if (null? wl) - (if oops - (f dl '() #f) - (with-proxy* proxy proxy-ids - (map/ormap - (lambda (x) - (apply (lambda (id val unsafe) - (let-values ([(val dl?) (cpvalid val proxy dl?)]) - (values (cons id val) dl?))) - x)) - dl))) - (apply (lambda (id val unsafe) - (define update - (lambda (x) - (apply (lambda (id val unsafe) - (if (or unsafe (prelex-info-referenced id)) - (begin (set-prelex-info-referenced! id #f) - (list id val #t)) - x)) - x))) - (if unsafe - (let ([val (with-unprotected proxy - (let ([proxy (make-proxy)]) - (with-proxy* proxy proxy-ids - (first-value (cpvalid val proxy #f)))))]) - (let-values ([(ls dl?) (f (map update (cdr wl)) (map update dl) #t)]) - (values (cons (cons id val) ls) dl?))) - (f (cdr wl) (cons (car wl) dl) oops))) - (car wl))))) - - (define map/ormap - (case-lambda - [(p ls) - (if (null? ls) - (values '() #f) - (let-values ([(x b1) (p (car ls))] - [(ls b2) (map/ormap p (cdr ls))]) - (values (cons x ls) (or b1 b2))))] - [(p ls1 ls2) - (if (null? ls1) - (values '() #f) - (let-values ([(x b1) (p (car ls1) (car ls2))] - [(ls b2) (map/ormap p (cdr ls1) (cdr ls2))]) - (values (cons x ls) (or b1 b2))))])) - - (define deferred? - (lambda (x) - (nanopass-case (Lsrc Expr) x - [(cpvalid-defer ,e) #t] - [else #f]))) - - (with-output-language (Lsrc Expr) - (define defer-or-not - (lambda (dl? x) - (values - (if (and dl? (not (deferred? x))) - `(cpvalid-defer ,x) - x) - dl?)))) - - (define-syntax first-value - (syntax-rules () - [(_ e) (let-values ([(x . r) e]) x)])) - - (define undefer* - (lambda (ls proxy dl?) - (map/ormap - (lambda (x) (undefer x proxy dl?)) - ls)))) - - (undefer : Expr (x proxy dl?) -> Expr (dl?) - [(cpvalid-defer ,[undefer-helper : e dl?]) (values e dl?)] - [else (values x #f)]) - - (undefer-helper : Expr (x proxy dl?) -> Expr (dl?) - [(ref ,maybe-src ,x) (values x #f)] - [(quote ,d) (values x #f)] - [,pr (values x #f)] - ; recognize canonical form of a let after expansion - [(call ,preinfo0 - (case-lambda ,preinfo1 (clause (,x* ...) ,interface ,[undefer : body body-dl?])) - ,e* ...) - (guard (fx= (length e*) interface)) - (let-values ([(e* args-dl?) (undefer* e* proxy dl?)]) - (defer-or-not (or body-dl? args-dl?) - `(call ,preinfo0 - (case-lambda ,preinfo1 - (clause (,x* ...) ,interface ,body)) - ,e* ...)))] - [(call ,preinfo ,[undefer : e fun-dl?] ,e* ...) - (let-values ([(e* args-dl?) (undefer* e* proxy dl?)]) - (defer-or-not (or fun-dl? args-dl?) - `(call ,preinfo ,e ,e* ...)))] - [(if ,[undefer : e0 dl0?] ,[undefer : e1 dl1?] ,[undefer : e2 dl2?]) - (defer-or-not (or dl0? dl1? dl2?) `(if ,e0 ,e1 ,e2))] - [(case-lambda ,preinfo ,cl* ...) - (cpvalid `(case-lambda ,preinfo ,cl* ...) proxy dl?)] - [(seq ,[undefer : e1 dl1?] ,[undefer : e2 dl2?]) - (defer-or-not (or dl1? dl2?) `(seq ,e1 ,e2))] - [(set! ,maybe-src ,x ,[undefer : e dl?]) - (defer-or-not dl? `(set! ,maybe-src ,x ,e))] - [(letrec ([,x* ,e*] ...) ,[undefer : body body-dl?]) - (let-values ([(e* vals-dl?) (undefer* e* proxy dl?)]) - (defer-or-not (or body-dl? vals-dl?) - `(letrec ([,x* ,e*] ...) ,body)))] - [(letrec* ([,x* ,e*] ...) ,[undefer : body body-dl?]) - (let-values ([(e* vals-dl?) (undefer* e* proxy dl?)]) - (defer-or-not (or body-dl? vals-dl?) - `(letrec* ([,x* ,e*] ...) ,body)))] - [(foreign (,conv* ...) ,name ,[undefer : e dl?] (,arg-type* ...) ,result-type) - (defer-or-not dl? `(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type))] - [(fcallable (,conv* ...) ,[undefer : e dl?] (,arg-type* ...) ,result-type) - (defer-or-not dl? `(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type))] - [(cte-optimization-loc ,box ,[undefer : e dl?]) - (defer-or-not dl? `(cte-optimization-loc ,box ,e))] - [(pariah) (values x #f)] - [(profile ,src) (values x #f)] - [(moi) (values x #f)] - [else (sorry! who "unexpected record ~s" x)]) - - (CaseLambdaClause : CaseLambdaClause (ir proxy) -> CaseLambdaClause () - [(clause (,x* ...) ,interface ,body) - (let-values ([(body dl?) (with-protected proxy (cpvalid body #f #f))]) - `(clause (,x* ...) ,interface ,body))]) - - (cpvalid : Expr (x proxy dl?) -> Expr (dl?) - [(ref ,maybe-src ,x) - (set-prelex-info-referenced! x #t) - (values - (let ([p (prelex-info-proxy x)]) - ; unsafe => x might be called. this can only happen if x has - ; gotten into the unprotected state - (when (and p (eq? (proxy-state p) 'unprotected)) - (set-prelex-info-unsafe! x #t)) - (insert-valid-check "reference" maybe-src x p `(ref ,maybe-src ,x))) - #f)] - [,pr (values x #f)] - [(quote ,d) (values x #f)] - [(call ,preinfo ,pr ,e* ...) - (guard (all-set? (prim-mask (or proc discard)) (primref-flags pr))) - (let-values ([(e* dl?) (map/ormap (lambda (e) (cpvalid e proxy dl?)) e*)]) - (defer-or-not dl? `(call ,preinfo ,pr ,e* ...)))] - ; recognize canonical form of a let after expansion - [(call ,preinfo0 (case-lambda ,preinfo1 (clause (,x* ...) ,interface ,body)) ,e* ...) - (guard (fx= (length e*) interface)) - (let ([proxy (or proxy (make-proxy))]) - (with-info x* - (with-proxy* proxy x* - (let-values ([(body body-dl?) (cpvalid body proxy dl?)]) - (let-values ([(e* dl?) - (map/ormap - (lambda (arg id) - (if (prelex-info-unsafe id) - (with-unprotected proxy (cpvalid arg #f #f)) - (cpvalid arg proxy dl?))) - e* x*)]) - (defer-or-not (or dl? body-dl?) - `(call ,preinfo0 - (case-lambda ,preinfo1 - (clause (,x* ...) ,interface ,body)) - ,e* ...)))))))] - [(call ,preinfo ,e ,e* ...) - (values - (with-unprotected proxy - `(call ,preinfo - ,(first-value (cpvalid e #f #f)) - ,(map (lambda (x) (first-value (cpvalid x #f #f))) e*) ...)) - #f)] - [(case-lambda ,preinfo ,cl* ...) - (if dl? - (values `(cpvalid-defer ,x) #t) - (values - `(case-lambda ,preinfo ,(map (lambda (cl) (CaseLambdaClause cl proxy)) cl*) ...) - #f))] - [(set! ,maybe-src ,x ,e) - (let-values ([(e dl?) - ; rhs is unsafe only if x is referenced - (if (prelex-referenced x) - (with-unprotected proxy (cpvalid e #f #f)) - (cpvalid e proxy dl?))]) - (defer-or-not dl? - (insert-valid-check "assign" maybe-src x (prelex-info-proxy x) - (first-value - (defer-or-not dl? - `(set! ,maybe-src ,x ,e))))))] - [(letrec ([,x* ,e*] ...) ,body) - (with-info x* - (let*-values ([(proxy) (or proxy (make-proxy))] - [(valid-flag) (make-prelex* 'valid?)] - [(body body-dl?) (with-proxy* proxy x* (cpvalid body proxy dl?))] - [(unsafe*) (map prelex-info-unsafe x*)]) - (for-each - (lambda (id) - (set-prelex-info-unsafe! id #f) - (set-prelex-info-referenced! id #f)) - x*) - (let*-values ([(alist dl?) (with-valid* valid-flag x* - (process-letrec-bindings cpvalid proxy x* x* e* unsafe* dl?))] - [(e*) (map (lambda (id) (cdr (assq id alist))) x*)]) - (defer-or-not (or dl? body-dl?) - (if (prelex-referenced valid-flag) - (begin - (set-prelex-assigned! valid-flag #t) - (build-let (list valid-flag) (list `(quote #f)) - (first-value - (let-values ([(body body-dl?) (defer-or-not body-dl? - `(seq - (set! #f ,valid-flag (quote #t)) - ,body))]) - (defer-or-not (or dl? body-dl?) - (build-letrec x* e* body)))))) - (build-letrec x* e* body))))))] - [(letrec* ([,x* ,e*] ...) ,body) - ; - we do unprotected parts of each rhs plus unsafe lambda pieces - ; first and leave remaining lambda expressions to do later. - ; - a full-blown flow analysis could be even nicer and even make it - ; possible to detect references and assignments that are surely - ; bad. - (with-info x* - (let*-values ([(proxy) (or proxy (make-proxy))] - [(valid-flags) (map (lambda (id) (make-prelex* 'valid?)) x*)] - [(body body-dl?) (with-proxy* proxy x* (cpvalid body proxy dl?))] - [(unsafe*) (map prelex-info-unsafe x*)]) - (define-record-type welt (nongenerative) (sealed #t) - (fields id (mutable val) unsafe (mutable forbidden-ids) (mutable valid-flags))) - (define (make-welts x* e* unsafe* valid-flags) - (let f ([x* x*] [e* e*] [unsafe* unsafe*] [valid-flags valid-flags]) - (if (null? x*) - '() - (cons (make-welt (car x*) (car e*) (car unsafe*) x* valid-flags) - (f (cdr x*) (cdr e*) (cdr unsafe*) (cdr valid-flags)))))) - (define (process-ws w* d*) - (if (null? w*) - (process-letrec-bindings undefer proxy '() - (map welt-id d*) - (map welt-val d*) - (map welt-unsafe d*) - dl?) - (let ([w (car w*)]) - (let ([id (welt-id w)] - [val (welt-val w)] - [unsafe (welt-unsafe w)] - [forbidden-ids (welt-forbidden-ids w)] - [valid-flags (welt-valid-flags w)]) - (if (prelex-info-referenced id) - (let ([val (with-proxy* proxy forbidden-ids - (with-unprotected proxy - (with-valid** valid-flags forbidden-ids - (first-value - ; could obviate this test with - ; cpvalid-defer case in cpvalid - (if (deferred? val) - (undefer val #f #f) - (cpvalid val #f #f))))))]) - (let-values ([(ls dl?) (process-ds (cdr w*) d* id (car valid-flags))]) - (values (cons (cons id val) ls) dl?))) - (let-values ([(val dl?) (with-proxy* proxy forbidden-ids - (with-unprotected proxy - (with-valid** valid-flags forbidden-ids - (cpvalid val #f #t))))]) - (if dl? - (begin - ; deferred parts of rhs can reference own lhs, so remove it from forbidden list - (welt-val-set! w val) - (welt-forbidden-ids-set! w (cdr forbidden-ids)) - (welt-valid-flags-set! w (cdr valid-flags)) - (process-ds (cdr w*) (cons w d*) id (car valid-flags))) - (let-values ([(ls dl?) (process-ds (cdr w*) d* id (car valid-flags))]) - (values (cons (cons id val) ls) dl?))))))))) - (define (process-ds w* d* okay-before-id okay-before-valid-flags) - ; it's okay to reference any rhs before okay-before-id - ; trim forbidden lists accordingly - (for-each - (lambda (w) - (cond - [(memq okay-before-id (welt-forbidden-ids w)) => - (lambda (x*) - (welt-forbidden-ids-set! w x*) - (welt-valid-flags-set! w - (memq okay-before-valid-flags (welt-valid-flags w))))])) - d*) - (let f ([d* d*] [new-d* '()] [oops? #f]) - (if (null? d*) - (if oops? - (f new-d* '() #f) - (process-ws w* new-d*)) - (let* ([w (car d*)] [id (welt-id w)]) - (if (prelex-info-referenced id) - (let ([val (with-proxy* proxy (welt-forbidden-ids w) - (with-unprotected proxy - (with-valid** (welt-valid-flags w) (welt-forbidden-ids w) - (first-value (undefer (welt-val w) #f #f)))))]) - (let-values ([(ls dl?) (f (cdr d*) new-d* #t)]) - (values (cons (cons id val) ls) dl?))) - (f (cdr d*) (cons w new-d*) oops?)))))) - (for-each - (lambda (id) - (set-prelex-info-unsafe! id #f) - (set-prelex-info-referenced! id #f)) - x*) - (let*-values ([(alist dl?) (process-ws (make-welts x* e* unsafe* valid-flags) '())] - [(e*) (map (lambda (id) (cdr (assq id alist))) x*)] - [(x* e* valid-flags) - (let f ([x* x*] [e* e*] [valid-flags valid-flags]) - (if (null? x*) - (values '() '() '()) - (let ([id (car x*)] [val (car e*)] [vf (car valid-flags)]) - (let-values ([(x* e* valid-flags) (f (cdr x*) (cdr e*) (cdr valid-flags))]) - (if (prelex-referenced vf) - (begin - (set-prelex-assigned! vf #t) - (values - (list* id (make-prelex* 'dummy) x*) - (list* val `(set! #f ,vf (quote #t)) e*) - (cons vf valid-flags))) - (values - (cons id x*) - (cons val e*) - valid-flags))))))]) - (defer-or-not (or dl? body-dl?) - (build-let valid-flags (make-list (length valid-flags) `(quote #f)) - (first-value - (defer-or-not (or dl? body-dl?) - (build-letrec* x* e* body))))))))] - [(if ,[cpvalid : e0 dl0?] ,[cpvalid : e1 dl1?] ,[cpvalid : e2 dl2?]) - (defer-or-not (or dl0? dl1? dl2?) `(if ,e0 ,e1 ,e2))] - [(seq ,[cpvalid : e1 dl1?] ,[cpvalid : e2 dl2?]) - (defer-or-not (or dl1? dl2?) `(seq ,e1 ,e2))] - [(foreign (,conv* ...) ,name ,[cpvalid : e dl?] (,arg-type* ...) ,result-type) - (defer-or-not dl? `(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type))] - [(fcallable (,conv* ...) ,[cpvalid : e dl?] (,arg-type* ...) ,result-type) - (defer-or-not dl? `(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type))] - [(cte-optimization-loc ,box ,[cpvalid : e dl?]) - (defer-or-not dl? `(cte-optimization-loc ,box ,e))] - [(pariah) (values x #f)] - [(profile ,src) (values x #f)] - [(moi) (values x #f)] - [else (sorry! who "unexpected record ~s" x)]) - (first-value (cpvalid x #f #f))) - - (set! $cpvalid - (lambda (x) - (if (= (optimize-level) 3) x (cpvalid x))))) -) diff --git a/ta6ob/s/cpvalid.ta6ob b/ta6ob/s/cpvalid.ta6ob deleted file mode 100644 index 706a65d..0000000 Binary files a/ta6ob/s/cpvalid.ta6ob and /dev/null differ diff --git a/ta6ob/s/date.ss b/ta6ob/s/date.ss deleted file mode 100644 index b34e0af..0000000 --- a/ta6ob/s/date.ss +++ /dev/null @@ -1,453 +0,0 @@ -;;; date.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; disagreements with SRFI 19: -;;; - nanoseconds are limited to 999,999,999 (SRFI 19: 9,999,999) -;;; - seconds are limited to 61 (SRFI 19: 60) -;;; - days range from 1 to 31, inclusive (SRFI 19: 0 to 31, inclusive) -;;; - years range from 1901 to about 2038, inclusive (SRFI 19: not clear) -;;; - years start at 1970 under Windows -;;; - current-date tz-offset defaults to local offset (SRFI 19: not specified) - -;;; questions about SRFI 19: -;;; - must tai times be supported? - -;;; can't read past copyright notice in srfi 19 reference implementation. -;;; is it really as restrictive as it appears? - -;;; suck in srfi 19 tests, which seem only to be covered by license in -;;; srfi 19 description. - -;;; won't be implemented from SRFI 19 except as add-on: -;;; - constants time-duration, time-monotonic, time-process, time-tai, -;;; time-thread, and time-utc (violates no non-procedure value policy) - -;;; not yet implemented from SRFI 19: -;;; - time procedures -;;; time-resolution [ts-time] -;;; time-monotonic->time-utc ; may be impossible unless we roll our own -;;; time-monotonic->time-utc! ; monotonic (= tai) based on utc plus leap -;;; time-utc->time-monotonic ; seconds. yuck. -;;; time-utc->time-monotonic! -;;; - date procedures -;;; date-week-number -;;; date->time-monotonic -;;; time-monotonic->date -;;; date->string -;;; string->date -;;; - julian dates -;;; current-julian-day -;;; current-modified-julian-day -;;; date->julian-day -;;; date->modified-julian-day -;;; julian-day->date -;;; julian-day->time-monotonic -;;; julian-day->time-utc -;;; modified-julian-day->date -;;; modified-julian-day->time-monotonic -;;; modified-julian-day->time-utc -;;; time-monotonic->julian-day -;;; time-monotonic->modified-julian-day -;;; time-utc->julian-day -;;; time-utc->modified-julian-day -;;; - tai times -;;; ts-type 'time-tai -;;; date->time-tai -;;; time-monotonic->time-tai -;;; time-monotonic->time-tai! -;;; time-tai->date -;;; time-tai->time-monotonic -;;; time-tai->time-monotonic! -;;; time-tai->time-utc -;;; time-tai->time-utc! -;;; time-utc->time-tai -;;; time-utc->time-tai! -;;; julian-day->time-tai -;;; modified-julian-day->time-tai -;;; time-tai->julian-day -;;; time-tai->modified-julian-day - -(let () - (define $clock-gettime ; clock_id -> tspair - (foreign-procedure "(cs)clock_gettime" - (integer-32) - scheme-object)) - - (define $gmtime ; #f|tzoff X #f|tspair -> dtvec (returns #f on error) - (foreign-procedure "(cs)gmtime" - (scheme-object scheme-object) - scheme-object)) - - (define $asctime ; #f | dtvec -> string (returns #f on error) - (foreign-procedure "(cs)asctime" - (scheme-object) - scheme-object)) - - (define $mktime ; dtvec -> tspair (returns #f on error) - (foreign-procedure "(cs)mktime" - (scheme-object) - scheme-object)) - - (define-record-type ts ; keep in sync with S_condition_wait in c/thread.c - (fields (mutable typeno) (immutable pair)) - (nongenerative #{ts a5dq4nztnmq6xlgp-a}) - (sealed #t)) - - (define ts-type->typeno - (lambda (who type) - (case type - [(time-process) (constant time-process)] - [(time-thread) (constant time-thread)] - [(time-duration) (constant time-duration)] - [(time-monotonic) (constant time-monotonic)] - [(time-utc) (constant time-utc)] - [(time-collector-cpu) (constant time-collector-cpu)] - [(time-collector-real) (constant time-collector-real)] - [else ($oops who "unrecognized time type ~s" type)]))) - - (define ts-typeno->type - (lambda (typeno) - (cond - [(eq? typeno (constant time-process)) 'time-process] - [(eq? typeno (constant time-thread)) 'time-thread] - [(eq? typeno (constant time-duration)) 'time-duration] - [(eq? typeno (constant time-monotonic)) 'time-monotonic] - [(eq? typeno (constant time-utc)) 'time-utc] - [(eq? typeno (constant time-collector-cpu)) 'time-collector-cpu] - [(eq? typeno (constant time-collector-real)) 'time-collector-real] - [else ($oops 'time-internal "unexpected typeno ~s" typeno)]))) - - (define ts-sec (lambda (ts) (car (ts-pair ts)))) - (define ts-nsec (lambda (ts) (cdr (ts-pair ts)))) - (define set-ts-sec! (lambda (ts n) (set-car! (ts-pair ts) n))) - (define set-ts-nsec! (lambda (ts n) (set-cdr! (ts-pair ts) n))) - - (define (check-ts who ts) - (unless (ts? ts) - ($oops who "~s is not a time record" ts))) - - (define (check-ts-sec who sec) - (unless (or (fixnum? sec) (bignum? sec)) - ($oops who "invalid number of seconds ~s" sec))) - - (define (check-same-type who t1 t2) - (unless (fx= (ts-typeno t1) (ts-typeno t2)) - ($oops who "types of ~s and ~s differ" t1 t2))) - - (define (check-type-duration who t) - (unless (fx= (ts-typeno t) (constant time-duration)) - ($oops who "~s does not have type time-duration" t))) - - (define-record-type dt - (fields (immutable vec)) - (nongenerative #{dt a5jhglnb7tr8ubed-a}) - (sealed #t)) - - (define (check-dt who dt) - (unless (dt? dt) - ($oops who "~s is not a date record" dt))) - - (define (check-nsec who nsec) - (unless (and (or (fixnum? nsec) (bignum? nsec)) (<= 0 nsec 999999999)) - ($oops who "invalid nanosecond ~s" nsec))) - - (define (check-sec who sec) - (unless (and (fixnum? sec) (fx<= 0 sec 61)) - ($oops who "invalid second ~s" sec))) - - (define (check-min who min) - (unless (and (fixnum? min) (fx<= 0 min 59)) - ($oops who "invalid minute ~s" min))) - - (define (check-hour who hour) - (unless (and (fixnum? hour) (fx<= 0 hour 23)) - ($oops who "invalid hour ~s" hour))) - - (define (check-day who day) - (unless (and (fixnum? day) (fx<= 1 day 31)) - ($oops who "invalid day ~s" day))) - - (define (check-mon who mon) - (unless (and (fixnum? mon) (fx<= 1 mon 12)) - ($oops who "invalid month ~s" mon))) - - (define (check-year who year) - (unless (and (fixnum? year) (fx>= year 1901)) - ($oops who "invalid year ~s" year))) - - (define (check-tz who tz) - (unless (and (fixnum? tz) - ; being generous here... - (fx<= (* -24 60 60) tz (* 24 60 60))) - ($oops who "invalid time-zone offset ~s" tz))) - - (define $copy-time - (lambda (t) - (let ([p (ts-pair t)]) - (make-ts (ts-typeno t) (cons (car p) (cdr p)))))) - - (record-writer (type-descriptor ts) - (lambda (x p wr) - (let ([type (ts-typeno->type (ts-typeno x))] [sec (ts-sec x)] [nsec (ts-nsec x)]) - (if (and (< sec 0) (> nsec 0)) - (fprintf p "#<~s -~d.~9,'0d>" type (- -1 sec) (- 1000000000 nsec)) - (fprintf p "#<~s ~d.~9,'0d>" type sec nsec))))) - - (record-writer (type-descriptor dt) - (lambda (x p wr) - (fprintf p "#" - ($asctime (dt-vec x))))) - - (set-who! make-time - (lambda (type nsec sec) - (let ([typeno (ts-type->typeno who type)]) - (check-nsec who nsec) - (check-ts-sec who sec) - (make-ts typeno (cons sec nsec))))) - - (set! time? (lambda (x) (ts? x))) - - (set-who! time-type - (lambda (ts) - (check-ts who ts) - (ts-typeno->type (ts-typeno ts)))) - - (set-who! time-second - (lambda (ts) - (check-ts who ts) - (ts-sec ts))) - - (set-who! time-nanosecond - (lambda (ts) - (check-ts who ts) - (ts-nsec ts))) - - (set-who! set-time-type! - (lambda (ts type) - (check-ts who ts) - (ts-typeno-set! ts (ts-type->typeno who type)))) - - (set-who! set-time-second! - (lambda (ts sec) - (check-ts who ts) - (check-ts-sec who sec) - (set-ts-sec! ts sec))) - - (set-who! set-time-nanosecond! - (lambda (ts nsec) - (check-ts who ts) - (check-nsec who nsec) - (set-ts-nsec! ts nsec))) - - (set-who! time=? - (lambda (t1 t2) - (check-ts who t1) - (check-ts who t2) - (check-same-type who t1 t2) - (and (= (ts-sec t1) (ts-sec t2)) - (= (ts-nsec t1) (ts-nsec t2))))) - - (set-who! time=? - (lambda (t1 t2) - (check-ts who t1) - (check-ts who t2) - (check-same-type who t1 t2) - (or (> (ts-sec t1) (ts-sec t2)) - (and (= (ts-sec t1) (ts-sec t2)) - (>= (ts-nsec t1) (ts-nsec t2)))))) - - (set-who! time>? - (lambda (t1 t2) - (check-ts who t1) - (check-ts who t2) - (check-same-type who t1 t2) - (or (> (ts-sec t1) (ts-sec t2)) - (and (= (ts-sec t1) (ts-sec t2)) - (> (ts-nsec t1) (ts-nsec t2)))))) - - (let ([f (lambda (t1 t2 who) - (check-ts who t1) - (check-ts who t2) - (check-same-type who t1 t2) - (let-values ([(sec nsec) - (let ([sec (- (ts-sec t1) (ts-sec t2))] - [nsec (- (ts-nsec t1) (ts-nsec t2))]) - (if (< nsec 0) (values (- sec 1) (+ nsec 1000000000)) (values sec nsec)))]) - (make-ts (constant time-duration) (cons sec nsec))))]) - (set-who! time-difference (lambda (t1 t2) (f t1 t2 who))) - (set-who! time-difference! (lambda (t1 t2) (f t1 t2 who)))) - - (let ([f (lambda (t1 t2 who) - (check-ts who t1) - (check-ts who t2) - (check-type-duration who t2) - (let-values ([(sec nsec) - (let ([sec (- (ts-sec t1) (ts-sec t2))] - [nsec (- (ts-nsec t1) (ts-nsec t2))]) - (if (< nsec 0) (values (- sec 1) (+ nsec 1000000000)) (values sec nsec)))]) - (make-ts (ts-typeno t1) (cons sec nsec))))]) - (set-who! subtract-duration (lambda (t1 t2) (f t1 t2 who))) - (set-who! subtract-duration! (lambda (t1 t2) (f t1 t2 who)))) - - (let ([f (lambda (t1 t2 who) - (check-ts who t1) - (check-ts who t2) - (check-type-duration who t2) - (let-values ([(sec nsec) - (let ([sec (+ (time-second t1) (time-second t2))] - [nsec (+ (time-nanosecond t1) (time-nanosecond t2))]) - (if (>= nsec 1000000000) (values (+ sec 1) (- nsec 1000000000)) (values sec nsec)))]) - (make-ts (ts-typeno t1) (cons sec nsec))))]) - (set-who! add-duration (lambda (t1 t2) (f t1 t2 who))) - (set-who! add-duration! (lambda (t1 t2) (f t1 t2 who)))) - - (set-who! copy-time - (lambda (t) - (check-ts who t) - ($copy-time t))) - - (set-who! current-time - (case-lambda - [() (let ([typeno (constant time-utc)]) - (make-ts typeno ($clock-gettime typeno)))] - [(type) - (case type - [(time-collector-cpu) ($copy-time ($gc-cpu-time))] - [(time-collector-real) ($copy-time ($gc-real-time))] - [else (let ([typeno (ts-type->typeno who type)]) - (make-ts typeno ($clock-gettime typeno)))])])) - - (set-who! current-date - (case-lambda - [() - (let ([dtvec ($gmtime #f #f)]) - (unless dtvec ($oops who "failed")) - (make-dt dtvec))] - [(tz) - (check-tz who tz) - (let ([dtvec ($gmtime tz #f)]) - (unless dtvec ($oops who "failed")) - (make-dt dtvec))])) - - (set-who! date-and-time ; ptime|#f -> string - (case-lambda - [() (or ($asctime #f) ($oops who "failed"))] - [(dt) - (check-dt who dt) - (or ($asctime (dt-vec dt)) - ($oops who "failed for date record ~s" dt))])) - - (set-who! make-date - (let ([do-make-date - (lambda (nsec sec min hour day mon year tz tz-provided?) - (check-nsec who nsec) - (check-sec who sec) - (check-min who min) - (check-hour who hour) - ; need more accurate check for day based on year and month - (check-day who day) - (check-mon who mon) - (check-year who year) - (when tz-provided? - (check-tz who tz)) - ; keep in sync with cmacros.ss declarations of dtvec-nsec, etc. - (let ([dtvec (vector nsec sec min hour day mon (- year 1900) 0 #f 0 tz #f)]) - (unless ($mktime dtvec) ; for effect on dtvec - ($oops who "invalid combination of arguments")) - (unless (fx= (vector-ref dtvec (constant dtvec-mday)) day) - ($oops who "invalid day ~s for month ~s and year ~s" day mon year)) - (make-dt dtvec)))]) - (case-lambda - [(nsec sec min hour day mon year tz) - (do-make-date nsec sec min hour day mon year tz #t)] - [(nsec sec min hour day mon year) - (do-make-date nsec sec min hour day mon year #f #f)]))) - - (set! date? (lambda (x) (dt? x))) - - (let () - (define-syntax date-getter - (syntax-rules () - [(_ name index) - (set! name - (lambda (dt) - (check-dt 'name dt) - (vector-ref (dt-vec dt) index)))])) - - (date-getter date-nanosecond (constant dtvec-nsec)) - (date-getter date-second (constant dtvec-sec)) - (date-getter date-minute (constant dtvec-min)) - (date-getter date-hour (constant dtvec-hour)) - (date-getter date-day (constant dtvec-mday)) - (date-getter date-month (constant dtvec-mon)) - ; date-year is below - (date-getter date-week-day (constant dtvec-wday)) - (date-getter date-year-day (constant dtvec-yday)) - (date-getter date-dst? (constant dtvec-isdst)) - (date-getter date-zone-offset (constant dtvec-tzoff)) - (date-getter date-zone-name (constant dtvec-tzname))) - - (set-who! date-year - (lambda (dt) - (check-dt who dt) - (+ (vector-ref (dt-vec dt) (constant dtvec-year)) 1900))) - - #;(set-who! date-week-number - (lambda (dt dowsw) - (unless (or (eq? dossw 0) (eq? dossw 1)) - ($oops who "invalid week starting day" dossw)) - ???)) - - (set-who! time-utc->date - (case-lambda - [(t) - (unless (and (ts? t) (eq? (ts-typeno t) (constant time-utc))) - ($oops who "~s is not a utc time record" t)) - (let ([dtvec ($gmtime #f (ts-pair t))]) - (unless dtvec ($oops who "failed")) - (make-dt dtvec))] - [(t tz) - (unless (and (ts? t) (eq? (ts-typeno t) (constant time-utc))) - ($oops who "~s is not a utc time record" t)) - (check-tz who tz) - (let ([dtvec ($gmtime tz (ts-pair t))]) - (unless dtvec ($oops who "failed")) - (make-dt dtvec))])) - - (set-who! date->time-utc - (lambda (dt) - (check-dt who dt) - (let ([p ($mktime (vector-copy (dt-vec dt)))]) - (unless p ($oops who "conversion failed for ~s" dt)) - (make-ts (constant time-utc) p)))) -) diff --git a/ta6ob/s/date.ta6ob b/ta6ob/s/date.ta6ob deleted file mode 100644 index 187d01b..0000000 Binary files a/ta6ob/s/date.ta6ob and /dev/null differ diff --git a/ta6ob/s/debug.ss b/ta6ob/s/debug.ss deleted file mode 100644 index 86c266e..0000000 --- a/ta6ob/s/debug.ss +++ /dev/null @@ -1,271 +0,0 @@ -;;; debug.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(current-eval interpret) - -(subset-mode 'system) - -(generate-inspector-information #f) - -(eval-syntax-expanders-when '(load eval)) - -(disable-unbound-warning compile-with-asm compile-with-setup-closure-counts compile-with-closure-counts) - -(require-nongenerative-clause #t) - -(define compile-with-asm - (lambda (ss so mach) - (let ([file (format "~a.asm" (path-root so))]) - (parameterize ([#%$assembly-output (open-output-file file '(buffered replace))]) - (compile-file ss so mach) - (close-output-port (#%$assembly-output)))))) - -#;(define compile-with-closure-counts - (lambda (ss* so* mach) - (time (for-each (lambda (x y) - (collect 2) - (compile-file (symbol->string x) (symbol->string y) mach)) - ss* so*)))) - -#;(module (compile-with-setup-closure-counts compile-with-closure-counts) - (module (csv-cell csv-row csv-row* csv-rowv) - (define ->string - (lambda (x) - (cond - [(string? x) x] - [(symbol? x) (symbol->string x)] - [(char? x) (list->string (list x))] - [(number? x) (number->string x)] - [(identifier? x) (symbol->string (syntax->datum x))] - [else (format "~s" x)]))) - - (define needs-double-quote? - (lambda (str) - (let ([len (string-length str)]) - (let f ([i 0]) - (and (< i len) - (let ([c (string-ref str i)]) - (or (char=? c #\,) (char=? c #\") (f (fx+ i 1))))))))) - - (define double-double-quote - (lambda (str) - (let ([len (string-length str)]) - (let f ([i 0] [new-len 0]) - (if (fx= i len) - (make-string new-len) - (let ([c (string-ref str i)]) - (if (char=? c #\") - (let ([new-str (f (fx+ i 1) (fx+ new-len 2))]) - (string-set! new-str new-len #\") - (string-set! new-str (fx+ new-len 1) #\") - new-str) - (let ([new-str (f (fx+ i 1) (fx+ new-len 1))]) - (string-set! new-str new-len c) - new-str)))))))) - - (define csv-cell - (lambda (op x) - (let ([str (->string x)]) - (if (needs-double-quote? str) - (fprintf op "\"~a\"" (double-double-quote str)) - (display str op))))) - - (define csv-row - (lambda (op xs) - (let f ([xs xs]) - (if (null? xs) - (begin (newline op) (newline)) - (let ([x (car xs)] [xs (cdr xs)]) - (csv-cell (current-output-port) x) - (csv-cell op x) - (unless (null? xs) (display ",")) - (unless (null? xs) (display "," op)) - (f xs)))))) - - (define csv-rowv - (lambda (op . xs) - (let f ([xs xs]) - (if (null? xs) - (newline op) - (let ([x (car xs)] [xs (cdr xs)]) - (cond - [(vector? x) - (let ([len (vector-length x)]) - (do ([i 0 (fx+ i 1)]) - ((= i len)) - (csv-cell op (vector-ref x i)) - (unless (= (fx+ i 1) len) (display "," op))) - (newline op))] - [else - (csv-cell op x) - (unless (null? xs) (display "," op)) - (f xs)])))))) - - (define csv-row* - (lambda (op . xs) - (csv-row op xs)))) - - (define compile-with-setup-closure-counts - (lambda (opts ss* so* mach with-header?) - (include "types.ss") - (assert (or (eq? opts 'all) (equal? opts '(all)))) - (let ([ci (make-static-closure-info)]) - (time (for-each (lambda (x y) - (collect 2) - (parameterize ([#%$track-static-closure-counts ci] - [#%$track-dynamic-closure-counts #t]) - (compile-file (symbol->string x) (symbol->string y) mach))) - ss* so*)) - (let ([v (#%$dynamic-closure-counts)]) - (call-with-output-file "static-compiler.csv" - (lambda (op) - (let* ([final-cl-count (+ (static-closure-info-wk-pair-count ci) - (static-closure-info-wk-vector-count ci) - (static-closure-info-nwk-closure-count ci))] - [final-fv-count (+ (* (static-closure-info-wk-pair-count ci) 2) - (static-closure-info-wk-vector-free-var-count ci) - (static-closure-info-nwk-closure-free-var-count ci))] - [orig-var/closure (if (zero? (static-closure-info-raw-closure-count ci)) - (quote n/a) - (inexact (/ (static-closure-info-raw-free-var-count ci) - (static-closure-info-raw-closure-count ci))))] - [final-var/closure (if (zero? final-cl-count) - (quote n/a) - (inexact (/ final-fv-count final-cl-count)))] - [wk-var/vector (if (zero? (static-closure-info-wk-vector-count ci)) - (quote n/a) - (inexact (/ (static-closure-info-wk-vector-free-var-count ci) - (static-closure-info-wk-vector-count ci))))] - [nwk-var/closure (if (zero? (static-closure-info-nwk-closure-count ci)) - (quote n/a) - (inexact (/ (static-closure-info-nwk-closure-free-var-count ci) - (static-closure-info-nwk-closure-count ci))))]) - (when with-header? - (csv-row* op "Opts" "Orig. Closure Count" "Orig. Total Free Vars" "Orig. Avg. Free Var/Closure" - "Final Closure Count" "Final Total Free Vars" "Final Avg. Free Var/Closure" - "WK Borrowed" "WK Empty" "WK Single" "WK Pair" "WK Vector" "WK Vector Total Vars" "WK Vector Vars/Vector" - "NWK Empty" "NWK Closure" "NWK Closure Total Vars" "NWK Closure Vars/Closure" - "% Closures Eliminated" "% Size Reduction")) - #| - (printf "compiler closure elimination\n") - (printf " original closures: ~d\n" (static-closure-info-raw-closure-count ci)) - (printf " original free var total: ~d\n" (static-closure-info-raw-free-var-count ci)) - (printf " fv/closure: ~s\n" orig-var/closure) - (printf " final closure count: ~d\n" final-cl-count) - (printf " final free var total: ~d\n" final-fv-count) - (printf " fv/closure: ~s\n" final-var/closure) - (printf " wk empty: ~d\n" (static-closure-info-wk-empty-count ci)) - (printf " wk borrowed: ~d\n" (static-closure-info-wk-borrowed-count ci)) - (printf " wk single: ~d\n" (static-closure-info-wk-single-count ci)) - (printf " wk pair: ~d\n" (static-closure-info-wk-pair-count ci)) - (printf " wk vector: ~d\n" (static-closure-info-wk-vector-count ci)) - (printf " wk vector free var: ~d\n" (static-closure-info-wk-vector-free-var-count ci)) - (printf " fv/vector: ~s\n" wk-var/vector) - (printf " nwk empty: ~s\n" (static-closure-info-nwk-empty-count ci)) - (printf " nwk closure: ~s\n" (static-closure-info-nwk-closure-count ci)) - (printf " nwk closure free var: ~s\n" (static-closure-info-nwk-closure-free-var-count ci)) - (printf " fv/closure: ~s\n" nwk-var/closure) - (printf " % closures eliminated: ~s\n" - (inexact (/ (* (- (static-closure-info-raw-closure-count ci) final-cl-count) 100) - (static-closure-info-raw-closure-count ci)))) - (printf " % free-vars eliminated: ~s\n" - (inexact (/ (* (- (static-closure-info-raw-free-var-count ci) final-fv-count) 100) - (static-closure-info-raw-free-var-count ci)))) - |# - (printf "printing static row!!!\n") - (csv-row* op opts (static-closure-info-raw-closure-count ci) - (static-closure-info-raw-free-var-count ci) orig-var/closure - final-cl-count final-fv-count final-var/closure - (static-closure-info-wk-borrowed-count ci) - (static-closure-info-wk-empty-count ci) - (static-closure-info-wk-single-count ci) - (static-closure-info-wk-pair-count ci) - (static-closure-info-wk-vector-count ci) - (static-closure-info-wk-vector-free-var-count ci) - wk-var/vector - (static-closure-info-nwk-empty-count ci) - (static-closure-info-nwk-closure-count ci) - (static-closure-info-nwk-closure-free-var-count ci) - nwk-var/closure - (inexact (/ (* (- (static-closure-info-raw-closure-count ci) final-cl-count) 100) - (static-closure-info-raw-closure-count ci))) - (inexact (/ (* (- (static-closure-info-raw-free-var-count ci) final-fv-count) 100) - (static-closure-info-raw-free-var-count ci)))))) - (if with-header? 'replace 'append)))))) - - (define compile-with-closure-counts - (lambda (opts ss* so* mach with-header?) - (assert (or (eq? opts 'all) (equal? opts '(all)))) - (#%$clear-dynamic-closure-counts) - (time (for-each (lambda (x y) - (collect 2) - (parameterize ([#%$track-dynamic-closure-counts #t]) ; true, but could be false - (compile-file (symbol->string x) (symbol->string y) mach))) - ss* so*)) - (let ([v (#%$dynamic-closure-counts)]) - (call-with-output-file "dynamic-compiler.csv" - (lambda (op) - - (when with-header? - (csv-row* op "Name" - "Raw ref count" "Ref count" "% Ref Elim" - "Raw create count" "Pair create count" "Vector create count" "Closure create count" - "Total create count" "% Create Elim" - "Raw alloc" "Vector alloc" "Closure alloc" "Total alloc" "% Alloc Elim" - "Padded closure alloc count" "Padded vector alloc count")) - (let* ([%ref-elim (if (zero? (vector-ref v 0)) - 'n/a - (* (/ (- (vector-ref v 0) (vector-ref v 3)) - (vector-ref v 0)) - 100.0))] - [total-create (+ (vector-ref v 4) (vector-ref v 5) (vector-ref v 8))] - [%create-elim (if (zero? (vector-ref v 1)) - 'n/a - (* (/ (- (vector-ref v 1) total-create) (vector-ref v 1)) - 100.0))] - [total-alloc (+ (* 2 (vector-ref v 4)) (vector-ref v 6) (vector-ref v 9))] - [%alloc-elim (if (zero? (vector-ref v 2)) - 'n/a - (* (/ (- (vector-ref v 2) total-alloc) - (vector-ref v 2)) - 100.0))]) - #| - (printf "compiler dynamic closure counts:\n") - (printf " original references: ~d\n" (vector-ref v 0)) - (printf " original closure creations: ~d\n" (vector-ref v 1)) - (printf " original closure allocation: ~d\n" (vector-ref v 2)) - (printf " final references: ~d\n" (vector-ref v 3)) - (printf " % eliminated: ~s\n" %ref-elim) - (printf " pairs created: ~d\n" (vector-ref v 4)) - (printf " vectors created: ~d\n" (vector-ref v 5)) - (printf " closures created: ~d\n" (vector-ref v 8)) - (printf " total creation: ~d\n" total-create) - (printf " % eliminated: ~s\n" %create-elim) - (printf " vector allocation: ~d\n" (vector-ref v 6)) - (printf " closure allocation: ~d\n" (vector-ref v 9)) - (printf " total allocation: ~d\n" total-alloc) - (printf " % eliminated: ~s\n" %alloc-elim) - (printf " padded vector allocation: ~d\n" (vector-ref v 7)) - (printf " padded closure allocation: ~d\n" (vector-ref v 10)) - |# - (printf "printing dynamic row!!!\n") - (csv-row* op opts - (vector-ref v 0) (vector-ref v 3) %ref-elim - (vector-ref v 1) (vector-ref v 4) (vector-ref v 5) (vector-ref v 8) - total-create %create-elim - (vector-ref v 2) (vector-ref v 6) (vector-ref v 9) total-alloc %alloc-elim - (vector-ref v 7) (vector-ref v 10)))) - (if with-header? 'replace 'append)))))) - diff --git a/ta6ob/s/engine.ss b/ta6ob/s/engine.ss deleted file mode 100644 index 01fea2b..0000000 --- a/ta6ob/s/engine.ss +++ /dev/null @@ -1,134 +0,0 @@ -;;; engine.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; Notes: -;;; The engine code defines three functions: make-engine, -;;; engine-block, and engine-return. - -;;; Keyboard interrupts are caught while an engine is running -;;; and the engine disabled while the handler is running. - -;;; All of the engine code is defined within local state -;;; containing the following variables: -;;; *active* true iff an engine is running -;;; *exit* the continuation to the engine invoker -;;; *keybd* the saved keyboard interrupt handler -;;; *timer* the saved timer interrupt handler - - -(let () - -(define-threaded *exit*) -(define-threaded *keybd*) -(define-threaded *timer*) -(define-threaded *active* #f) - -(define cleanup - (lambda (who) - (unless *active* ($oops who "no engine active")) - (set! *active* #f) - (keyboard-interrupt-handler *keybd*) - (timer-interrupt-handler *timer*) - (set! *keybd* (void)) - (set! *exit* (void)) - (set! *timer* (void)))) - -(define setup - (lambda (exit) - (set! *active* #t) - (set! *keybd* (keyboard-interrupt-handler)) - (keyboard-interrupt-handler (exception *keybd*)) - (set! *timer* (timer-interrupt-handler)) - (timer-interrupt-handler block) - (set! *exit* exit))) - -(define block - ; disable engine and return the continuation - (lambda () - (let ([exit *exit*]) - (cleanup 'engine-block) - (set-timer (call/cc (lambda (k) (exit (lambda () k)))))))) - -(define return - ; disable engine and return list (ticks value ...) - (lambda (args) - (let ([n (set-timer 0)]) - (let ([exit *exit*]) - (cleanup 'engine-return) - (exit (lambda () (cons n args))))))) - -(define exception - ; disable engine while calling the handler - (lambda (handler) - (lambda args - (let ([ticks (set-timer 0)]) - (let ([exit *exit*]) - (cleanup 'engine-exception) - (apply handler args) - (setup exit) - (if (= ticks 0) (block) (set-timer ticks))))))) - -(define run-engine - ; run a continuation as an engine - (lambda (k ticks) - ((call/cc - (lambda (exit) - (set-timer 0) - (when *active* ($oops 'engine "cannot nest engines")) - (setup exit) - (k ticks)))))) - -(define eng - ; create an engine from a procedure or continuation - (lambda (k) - (lambda (ticks complete expire) - (unless (and (fixnum? ticks) (not (negative? ticks))) - ($oops 'engine "invalid ticks ~s" ticks)) - (unless (procedure? complete) - ($oops 'engine "~s is not a procedure" complete)) - (unless (procedure? expire) - ($oops 'engine "~s is not a procedure" expire)) - (if (= ticks 0) - (expire (eng k)) - (let ([x (run-engine k ticks)]) - (if (procedure? x) - (expire (eng x)) - (apply complete x))))))) - -(set! engine-return (lambda args (return args))) - -(set! engine-block (lambda () (set-timer 0) (block))) - -(set! make-engine - (lambda (x) - (unless (procedure? x) ($oops 'make-engine "~s is not a procedure" x)) - (eng (lambda (ticks) - (with-exception-handler - (lambda (c) - (let ([ticks (set-timer 0)]) - (let ([exit *exit*]) - (cleanup 'raise) - (call/cc - (lambda (k) - (exit - (lambda () - (let-values ([vals (raise-continuable c)]) - (setup exit) - (if (= ticks 0) (block) (set-timer ticks)) - (apply k vals))))))))) - (lambda () - (set-timer ticks) - (call-with-values x (lambda args (return args))))))))) -) diff --git a/ta6ob/s/engine.ta6ob b/ta6ob/s/engine.ta6ob deleted file mode 100644 index 7169564..0000000 Binary files a/ta6ob/s/engine.ta6ob and /dev/null differ diff --git a/ta6ob/s/enum.ss b/ta6ob/s/enum.ss deleted file mode 100644 index b5384ad..0000000 --- a/ta6ob/s/enum.ss +++ /dev/null @@ -1,298 +0,0 @@ -;;; enum.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;; NOTES: -;; This implementation assume the universe is small -;; and the algorithms used by this implementation may be -;; up to linear in the universe -;; -;; This code is a good candidate for partial-static-structure optimization -;; Right now the define-enumeration macro is doing optimizations -;; that could be automatically performed by PSS if PSS worked on enums -;; -;; The R6RS standard is unclear whether the function returned by enum-set-indexer -;; should throw an error if its argument is not a symbol. We have chosen to -;; not include that check, but if the standard is updated, this may need to be changed. - -(let () - -;;;;;;;; -#| Low-level enum-set definition and operations - The structure is as follows: - -------------------------------------------------------------------------------- -The following records are created once: - -enum-base-rtd: -+-----------------+--------------------+--------------------------------+-----+ -| rtd:#!base-rtd | parent:#!base-rtd | fields:(index->sym sym->index) | ... | -+-----------------+--------------------+--------------------------------+-----+ - -enum-parent-rtd: -+-----------------+--------------------+--------------------------------+-----+ -| rtd:#!base-rtd | parent: #f | fields:(members) | ... | -+-----------------+--------------------+--------------------------------+-----+ - -------------------------------------------------------------------------------- -The following record is created per enum-type and it stored the mappings -between symbols and their corresponding bits in the bit mask: - -this-enum-rtd: -+-------------------+------------------------+-----------+----- -| rtd:enum-base-rtd | parent:enum-parent-rtd | fields:() | ... -+-------------------+------------------------+-----------+----- - ----+------------+------------+ - ...| index->sym | sym->index | - ----+------------+------------+ - -------------------------------------------------------------------------------- -The following record is created per enum-set: - -an-enum-set: -+-------------------+--------------------------------+ -| rtd:this-enum-rtd | members: 17 (integer bit mask) | -+-------------------+--------------------------------+ - -|# - - (define enum-base-rtd - (make-record-type ; not sealed, not opaque - #!base-rtd ; undocumented #!base-rtd - '#{enum b9s78zmm79qs7j22-a} ; make enum-base-rtd type nongenerative - '((immutable sym->index) ; static (per enumeration type) fields - (immutable index->sym)))) - (define enum-parent-rtd ; not sealed, not opaque, nongenerative - (make-record-type - '#{enum-parent dwwi4y1kribh7mif58yoxe-0} - '((immutable members)))) - - (define get-sym->index (csv7:record-field-accessor enum-base-rtd 'sym->index)) - (define get-index->sym (csv7:record-field-accessor enum-base-rtd 'index->sym)) - (define get-members (csv7:record-field-accessor enum-parent-rtd 'members)) - (define members-universe -1) ;; All bits set - -;;;;;;;; - - ;; Make a new enum-set using the rtd and the new set of members - (define (make-enum-set enum-set-rtd members) - #;((record-constructor enum-set-rtd) members) - ; breaking the abstraction to avoid significant efficiency hit - ($record enum-set-rtd members)) - - ;; Perform type check for enum-set and return its RTD - (define (enum-set-rtd who enum-set) - (or (and (record? enum-set) - (let ([rtd (record-rtd enum-set)]) - (and (eq? (record-rtd rtd) enum-base-rtd) - rtd))) - ($oops who "~s is not an enumeration" enum-set))) - - (define (assert-symbol-list who symbol-list) - (unless (and (list? symbol-list) - (for-all symbol? symbol-list)) - ($oops who "~s is not a list of symbols" symbol-list))) - (define (assert-symbol who symbol) - (unless (symbol? symbol) - ($oops who "~s is not a symbol" symbol))) - - (define rtd&list->enum-set - (lambda (who rtd symbol-list) - (let ([sym->index (get-sym->index rtd)]) - (let loop ([members 0] - [symbol-list symbol-list]) - (if (null? symbol-list) - (make-enum-set rtd members) - (let ([index (symbol-hashtable-ref sym->index (car symbol-list) #f)]) - (if (not index) - (if who - ($oops who "universe does not include specified symbol ~s" - (car symbol-list)) - (loop members (cdr symbol-list))) - (loop (logbit1 index members) (cdr symbol-list))))))))) - - (define $enum-set->list - (lambda (who enum-set) - (let ([rtd (enum-set-rtd who enum-set)]) - (let ([index->sym (get-index->sym rtd)] - [members (get-members enum-set)]) - (let loop ([i (fx1- (vector-length index->sym))] - [lst '()]) - (if (fx< i 0) - lst - (loop (fx1- i) - (if (logbit? i members) - (cons (vector-ref index->sym i) lst) - lst)))))))) - - (record-writer enum-parent-rtd (lambda (x p wr) (display "#" p))) - -;;;;;;;; -;; Constructor - - (let () - ;; Takes lst and assigns indexes to each element of lst - ;; lst :: symbol-list - ;; index :: fixnum - ;; symbol->index :: hashtable from symbols to fixnum - ;; rev-lst :: symbol-list (stored in reverse order) - ;; - ;; Result :: (values fixnum (vector of symbols)) - (define (make-symbol->index lst index symbol->index rev-lst) - (cond - [(null? lst) - (let ([index->symbol (make-vector index)]) - (let loop ([i (fx1- index)] - [rev-lst rev-lst]) - (unless (null? rev-lst) ;; or (< i 0) - (vector-set! index->symbol i (car rev-lst)) - (loop (fx1- i) (cdr rev-lst)))) - (values index index->symbol))] - [(symbol-hashtable-contains? symbol->index (car lst)) - (make-symbol->index (cdr lst) index symbol->index rev-lst)] - [else - (symbol-hashtable-set! symbol->index (car lst) index) - (make-symbol->index (cdr lst) (fx1+ index) symbol->index (cons (car lst) rev-lst))])) - - (set! make-enumeration - (lambda (symbol-list) - (assert-symbol-list 'make-enumeration symbol-list) - (let ([sym->index (make-hashtable symbol-hash eq?)]) - (let-values ([(index index->sym) (make-symbol->index symbol-list 0 sym->index '())]) - (let ([this-enum-rtd - ($make-record-type - enum-base-rtd enum-parent-rtd "enum-type" - '() ; no fields to add - #t ; sealed - #f ; not opaque - sym->index - index->sym)]) - (make-enum-set this-enum-rtd members-universe))))))) - -;;;;;;;;; -;; Misc functions - - (set! $enum-set-members get-members) - - (set! enum-set-universe - (lambda (enum-set) - (make-enum-set (enum-set-rtd 'enum-set-universe enum-set) -1))) - (set! enum-set-indexer - (lambda (enum-set) - (let ([sym->index (get-sym->index (enum-set-rtd 'enum-set-indexer enum-set))]) - (lambda (x) - (assert-symbol 'enum-set-indexer x) - (symbol-hashtable-ref sym->index x #f))))) - - (set! enum-set-constructor - (lambda (enum-set) - (let ([rtd (enum-set-rtd 'enum-set-constructor enum-set)]) - (lambda (symbol-list) - (assert-symbol-list 'enum-set-constructor symbol-list) - (rtd&list->enum-set 'enum-set-constructor rtd symbol-list))))) - - (set! enum-set->list - (lambda (enum-set) - ($enum-set->list 'enum-set->list enum-set))) - -;;;;;;;;; -;; Predicates - - (set! enum-set? - (lambda (enum-set) - (and (record? enum-set) - (let ([rtd (record-rtd enum-set)]) - (eq? (record-rtd rtd) enum-base-rtd))))) - - (let () - (define (enum-set-subset-aux? enum-set1 enum-set2 rtd1 rtd2) - (let ([index->sym1 (get-index->sym rtd1)] - [members1 (get-members enum-set1)] - [sym->index2 (get-sym->index rtd2)] - [members2 (get-members enum-set2)]) - (let loop ([index1 0]) - (or (fx= index1 (vector-length index->sym1)) - (let ([index2 (symbol-hashtable-ref - sym->index2 - (vector-ref index->sym1 index1) #f)]) - (and index2 - (or (not (logbit? index1 members1)) - (logbit? index2 members2)) - (loop (fx1+ index1)))))))) - - (set! enum-set-member? - (lambda (symbol enum-set) - (assert-symbol 'enum-set-member? symbol) - (let ([sym->index (get-sym->index - (enum-set-rtd 'enum-set-member? enum-set))]) - (let ([index (symbol-hashtable-ref sym->index symbol #f)]) - (and index - (logbit? index (get-members enum-set))))))) - - (set! enum-set-subset? - (lambda (enum-set1 enum-set2) - (let ([rtd1 (enum-set-rtd 'enum-set-subset? enum-set1)] - [rtd2 (enum-set-rtd 'enum-set-subset? enum-set2)]) - (if (eq? rtd1 rtd2) - (let ([members2 (get-members enum-set2)]) - (= members2 (logor (get-members enum-set1) members2))) - (enum-set-subset-aux? enum-set1 enum-set2 rtd1 rtd2))))) - - (set! enum-set=? - (lambda (enum-set1 enum-set2) - (let ([rtd1 (enum-set-rtd 'enum-set=? enum-set1)] - [rtd2 (enum-set-rtd 'enum-set=? enum-set2)]) - (if (eq? rtd1 rtd2) - (= (get-members enum-set1) (get-members enum-set2)) - (and (enum-set-subset-aux? enum-set1 enum-set2 rtd1 rtd2) - (enum-set-subset-aux? enum-set2 enum-set1 rtd2 rtd1)))))) - ) - -;;;;;;;; -;; Set-like functions - - (let () - (define-syntax enum-bin-op - (syntax-rules () - [(_ name (members1 members2) members-expr) - (set! name - (lambda (enum-set1 enum-set2) - (let ([rtd1 (enum-set-rtd 'name enum-set1)] - [rtd2 (enum-set-rtd 'name enum-set2)]) - (unless (eq? rtd1 rtd2) - ($oops 'name "~s and ~s have different enumeration types" - enum-set1 enum-set2)) - (make-enum-set rtd1 (let ([members1 (get-members enum-set1)] - [members2 (get-members enum-set2)]) - members-expr)))))])) - - (enum-bin-op enum-set-union (members1 members2) (logor members1 members2)) - (enum-bin-op enum-set-intersection (members1 members2) (logand members1 members2)) - (enum-bin-op enum-set-difference (members1 members2) (logand members1 (lognot members2))) - ) - -;;;;;;;; -;; Other functions - - (set! enum-set-complement - (lambda (enum-set) - (let ([rtd (enum-set-rtd 'enum-set-complement enum-set)]) - (make-enum-set rtd (lognot (get-members enum-set)))))) - - (set! enum-set-projection - (lambda (enum-set1 enum-set2) - (rtd&list->enum-set #f - (enum-set-rtd 'enum-set-projection enum-set2) - ($enum-set->list 'enum-set-projection enum-set1)))) - ) diff --git a/ta6ob/s/enum.ta6ob b/ta6ob/s/enum.ta6ob deleted file mode 100644 index feb8e0c..0000000 Binary files a/ta6ob/s/enum.ta6ob and /dev/null differ diff --git a/ta6ob/s/env.so b/ta6ob/s/env.so deleted file mode 100644 index 087e7d5..0000000 Binary files a/ta6ob/s/env.so and /dev/null differ diff --git a/ta6ob/s/env.ss b/ta6ob/s/env.ss deleted file mode 100644 index 3c653be..0000000 --- a/ta6ob/s/env.ss +++ /dev/null @@ -1,19 +0,0 @@ -;;; env.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(begin -($make-base-modules) -($make-rnrs-libraries) -) diff --git a/ta6ob/s/env.ta6ob b/ta6ob/s/env.ta6ob deleted file mode 100644 index 087e7d5..0000000 Binary files a/ta6ob/s/env.ta6ob and /dev/null differ diff --git a/ta6ob/s/event.ss b/ta6ob/s/event.ss deleted file mode 100644 index a1dd6e7..0000000 --- a/ta6ob/s/event.ss +++ /dev/null @@ -1,68 +0,0 @@ -;;; event.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(let () -(define stop-event-timer - (lambda () - ($set-timer (most-positive-fixnum)))) - -(define start-event-timer - (lambda () - ; set timer by way of $event, so recurrent calls to "set-timer" or - ; "{dis,en}able-interrupts" can't prevent interrupts - ($event))) - -(set! set-timer - (lambda (ticks) - (unless (and (fixnum? ticks) (fx>= ticks 0)) - ($oops 'set-timer "~s is not a nonnegative fixnum" ticks)) - (let ([ticks-left (stop-event-timer)]) - (let ([t ($tc-field 'timer-ticks ($tc))]) - (if (fx> ticks 0) - (begin - ($tc-field 'something-pending ($tc) #t) - ($tc-field 'timer-ticks ($tc) ticks)) - ($tc-field 'timer-ticks ($tc) #f)) - (if (fx= ($tc-field 'disable-count ($tc)) 0) - (let ([old (if t (fx+ t ticks-left) 0)]) - (start-event-timer) - old) - (or t 0)))))) - -(set! disable-interrupts - (lambda () - (let ([ticks (stop-event-timer)]) - (let ([disable-count ($tc-field 'disable-count ($tc))]) - (when (and (fx= disable-count 0) ($tc-field 'timer-ticks ($tc))) - ($tc-field 'timer-ticks ($tc) (fx+ ($tc-field 'timer-ticks ($tc)) ticks))) - (when (fx= disable-count (most-positive-fixnum)) - ($oops 'disable-interrupts - "too many consecutive calls to disable-interrupts")) - (let ([disable-count (fx+ disable-count 1)]) - ($tc-field 'disable-count ($tc) disable-count) - disable-count))))) - -(set! enable-interrupts - (lambda () - (let ([ticks (stop-event-timer)]) - (let ([disable-count (fx- ($tc-field 'disable-count ($tc)) 1)]) - (case disable-count - [(-1) ($set-timer ticks) 0] - [(0) ($tc-field 'disable-count ($tc) 0) - (start-event-timer) - 0] - [else ($tc-field 'disable-count ($tc) disable-count) - disable-count]))))) -) diff --git a/ta6ob/s/event.ta6ob b/ta6ob/s/event.ta6ob deleted file mode 100644 index 5de2e67..0000000 Binary files a/ta6ob/s/event.ta6ob and /dev/null differ diff --git a/ta6ob/s/exceptions.ss b/ta6ob/s/exceptions.ss deleted file mode 100644 index 5b249ba..0000000 --- a/ta6ob/s/exceptions.ss +++ /dev/null @@ -1,737 +0,0 @@ -;;; exceptions.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -#| -TODO: - - teach default handler to: - - squirrel away continuation for debug as &continuation simple condition - - say something about calling debug (if &continuation is included) - - teach reset to handle closing of ports, etc., in system error chain - - wire into existing error-handling mechanisms, or visa versa - - replace error calls as appropriate with violation calls, - syntax-violation calls, etc. - - fix: unbound variables show up as #{b *top*:b} - (~:s in message is supposed to take care of this but format isn't being called) - - mats for system violations and errors - - deal with error? and warning? mats -|# - -(begin -(let () - (define (warning-only? c) - (and (warning? c) (not (serious-condition? c)))) - - (let () - (define $display-condition - (lambda (c op prefix? use-cache?) - (module (print-source) - (include "types.ss") - (define (print-position op prefix src start?) - (call-with-values - (lambda () ((current-locate-source-object-source) src start? use-cache?)) - (case-lambda - [() - (let ([sfd (source-sfd src)] - [fp (if start? (source-bfp src) (source-efp src))]) - (fprintf op "~a~a char ~a of ~a" prefix - (if (eq? start? 'near) "near" "at") - fp (source-file-descriptor-name sfd)))] - [(path line char) - (fprintf op "~a~a line ~a, char ~a of ~a" prefix - (if (eq? start? 'near) "near" "at") - line char path)]))) - (define (print-source op prefix c) - (cond - [($src-condition? c) - (let ([src ($src-condition-src c)]) - (when (source? src) - (print-position op prefix src ($src-condition-start c))))] - [(source-condition? c) - (let ([form (source-condition-form c)]) - (parameterize ([print-level 3] [print-length 6]) - (fprintf op "~a~s" prefix (syntax->datum form))) - (let-values ([(src start?) ($syntax->src form)]) - (when src (print-position op " " src start?))))] - [(syntax-violation? c) - (let ([form (syntax-violation-form c)] - [subform (syntax-violation-subform c)]) - (parameterize ([print-level 3] [print-length 6]) - (if subform - (fprintf op "~a~s in ~s" prefix (syntax->datum subform) (syntax->datum form)) - (fprintf op "~a~s" prefix (syntax->datum form)))) - (let-values ([(src start?) ($syntax->src subform)]) - (if src - (print-position op " " src start?) - (let-values ([(src start?) ($syntax->src form)]) - (when src (print-position op " " src start?))))))]))) - (cond - [(and (format-condition? c) - (guard (ignore [#t #f]) - ($report-string #f - (and prefix? (if (warning-only? c) "warning" "exception")) - (and (who-condition? c) (condition-who c)) - (condition-message c) - (condition-irritants c)))) => - (lambda (s) - (display s op) - (print-source op " " c))] - [(message-condition? c) - (let ([irritants (if (irritants-condition? c) (condition-irritants c) '())]) - (case (and (list? irritants) (length irritants)) - [(0) - ($report-string op - (and prefix? (if (warning-only? c) "warning" "exception")) - (and (who-condition? c) (condition-who c)) - "~a" - (list (condition-message c)))] - [(1) - ($report-string op - (and prefix? (if (warning-only? c) "warning" "exception")) - (and (who-condition? c) (condition-who c)) - "~a with irritant ~s" - (list (condition-message c) (car irritants)))] - [else - ($report-string op - (and prefix? (if (warning-only? c) "warning" "exception")) - (and (who-condition? c) (condition-who c)) - "~a with irritants ~s" - (list (condition-message c) irritants))])) - (print-source op " " c)] - [else - (fprintf op "Exception occurred") - (cond - [(condition? c) - (print-source op " " c) - (let ([x* (simple-conditions c)]) - (cond - [(null? x*) - (fprintf op " with empty condition\n")] - [else - (fprintf op " with condition components:") - (for-each - (lambda (x i) - (let ([rtd (#3%record-rtd x)]) - (define (print-field i) - (if (csv7:record-field-accessible? rtd i) - (parameterize ([print-level 3] [print-length 6]) - (fprintf op ": ~s" ((csv7:record-field-accessor rtd i) x))) - (fprintf op ": (inaccessible)"))) - (fprintf op "\n~3d. ~a" i (csv7:record-type-name (#3%record-rtd x))) - (if (record-type-opaque? rtd) - (fprintf op " (opaque)") - (let ([name* (csv7:record-type-field-names rtd)]) - (if (fx= (length name*) 1) - (print-field 0) - (for-each - (lambda (name i) - (fprintf op "\n ~s" name) - (print-field i)) - name* (iota (length name*)))))))) - x* (iota (length x*)))]))] - [else (parameterize ([print-level 3] [print-length 6]) - (fprintf op " with non-condition value ~s" c))])]))) - - (set-who! display-condition - (case-lambda - [(c) ($display-condition c (current-output-port) #t #f)] - [(c op) - (unless (and (output-port? op) (textual-port? op)) - ($oops who "~s is not a textual output port" op)) - ($display-condition c op #t #f)])) - - (set! $make-source-oops - (lambda (who msg expr) - #`(assertion-violation '#,who - #,(call-with-string-output-port - (lambda (p) - ($display-condition (condition - (make-syntax-violation expr #f) - (make-message-condition msg)) - p #f #t))))))) - - (set! default-exception-handler - (lambda (c) - (let ([cep (console-error-port)]) - (with-exception-handler - (lambda (c) - (if (i/o-error? c) - (begin - (debug-condition c) - (if (debug-on-exception) (debug)) - (reset)) - (raise-continuable c))) - (lambda () - ; only I/O to cep in handler-protected code---not (debug), not (reset). - (fresh-line cep) - (display-condition c cep) - (newline cep) - (unless (or (warning-only? c) (debug-on-exception) (= ($cafe) 0) (not (interactive?))) - (display-string "Type (debug) to enter the debugger.\n" cep)) - (flush-output-port cep)))) - (unless (warning-only? c) - (debug-condition c) - (if (debug-on-exception) (debug)) - (reset))))) - -(define debug-on-exception - (make-parameter #f - (lambda (x) (and x #t)))) - -(define base-exception-handler - ($make-thread-parameter - default-exception-handler - (lambda (p) - (unless (procedure? p) ($oops 'default-exception-handler "~s is not a procedure" p)) - p))) - -(let () - (define create-exception-stack - (lambda (p) - (let ([ls (list p)]) - (set-cdr! ls ls) - ls))) - - (define default-handler - (lambda (x) - ((base-exception-handler) x))) - - (define-threaded handler-stack (create-exception-stack default-handler)) - - (let () - (define-record-type exception-state - (nongenerative) - (opaque #t) - (sealed #t) - (fields (immutable stack))) - - (set-who! create-exception-state - (case-lambda - [() (make-exception-state (create-exception-stack default-handler))] - [(p) - (unless (procedure? p) ($oops who "~s is not a procedure" p)) - (make-exception-state (create-exception-stack p))])) - - (set-who! current-exception-state - (case-lambda - [() (make-exception-state handler-stack)] - [(x) - (unless (exception-state? x) - ($oops who "~s is not an exception state" x)) - (set! handler-stack (exception-state-stack x))]))) - - (set-who! with-exception-handler - (lambda (handler thunk) - (unless (procedure? handler) ($oops who "~s is not a procedure" handler)) - (unless (procedure? thunk) ($oops who "~s is not a procedure" thunk)) - (fluid-let ([handler-stack (cons handler handler-stack)]) - (thunk)))) - - (set-who! raise - (lambda (obj) - (let ([handler (car handler-stack)]) - (fluid-let ([handler-stack (cdr handler-stack)]) - (handler obj) - (raise (make-non-continuable-violation)))))) - - (set-who! raise-continuable - (lambda (obj) - (let ([handler (car handler-stack)]) - (fluid-let ([handler-stack (cdr handler-stack)]) - (handler obj))))) - - (set-who! $guard - (lambda (supply-else? guards body) - (if supply-else? - ((call/cc - (lambda (kouter) - (let ([original-handler-stack handler-stack]) - (with-exception-handler - (lambda (arg) - ((call/cc - (lambda (kinner) - (kouter - (lambda () - (guards arg - (lambda () - (kinner - (lambda () - (fluid-let ([handler-stack original-handler-stack]) - (raise-continuable arg)))))))))))) - (lambda () - (call-with-values - body - (case-lambda - [(x) (lambda () x)] - [vals (lambda () (apply values vals))])))))))) - ((call/cc - (lambda (k) - (with-exception-handler - (lambda (arg) (k (lambda () (guards arg)))) - (lambda () - (call-with-values - body - (case-lambda - [(x) (lambda () x)] - [vals (lambda () (apply values vals))])))))))))) -) - -(define-syntax guard - (syntax-rules (else) - [(_ (var clause ... [else e1 e2 ...]) b1 b2 ...) - (identifier? #'var) - ($guard #f (lambda (var) (cond clause ... [else e1 e2 ...])) - (lambda () b1 b2 ...))] - [(_ (var clause1 clause2 ...) b1 b2 ...) - (identifier? #'var) - ($guard #t (lambda (var p) (cond clause1 clause2 ... [else (p)])) - (lambda () b1 b2 ...))])) - -(let () - ; redefine here to get local predicate - (define-record-type (&condition $make-simple-condition $simple-condition?) - (nongenerative #{&condition oyb459ue1fphfx4-a})) - - (define-record-type (compound-condition make-compound-condition compound-condition?) - (nongenerative) - (sealed #t) - (fields (immutable components))) - - (define (check-&condition-subtype! who rtd) - (unless (record-type-descriptor? rtd) - ($oops who "~s is not a record type descriptor" rtd)) - (unless (let f ([rtd rtd]) - (or (eq? rtd (type-descriptor &condition)) - (let ([rtd (record-type-parent rtd)]) - (and rtd (f rtd))))) - ($oops who "~s does not describe a subtype of &condition" rtd))) - - (record-writer (type-descriptor &condition) - (lambda (x p wr) - (fprintf p "#" (csv7:record-type-name (#3%record-rtd x))))) - - (record-writer (type-descriptor compound-condition) - (lambda (x p wr) - (fprintf p "#"))) - - (set-who! $compound-condition? compound-condition?) - (set-who! $compound-condition-components compound-condition-components) - - (set-who! condition - (case-lambda - [(x) - (unless (or ($simple-condition? x) (compound-condition? x)) - ($oops who "~s is not a condition" x)) - x] - [x* - (let ([ls (fold-right - (lambda (x ls) - (cond - [($simple-condition? x) (cons x ls)] - [(compound-condition? x) (append (compound-condition-components x) ls)] - [else ($oops who "~s is not a condition" x)])) - '() - x*)]) - (if (fx= (length ls) 1) - (car ls) - (make-compound-condition ls)))])) - - (set-who! simple-conditions - (lambda (x) - (cond - [($simple-condition? x) (list x)] - [(compound-condition? x) (compound-condition-components x)] - [else ($oops who "~s is not a condition" x)]))) - - (set! condition? - (lambda (x) - (or ($simple-condition? x) (compound-condition? x)))) - - (set-who! condition-predicate - (lambda (rtd) - (check-&condition-subtype! who rtd) - (let ([p? (lambda (x) (record? x rtd))]) - (lambda (x) - (or (p? x) - (and (compound-condition? x) - (ormap p? (compound-condition-components x)))))))) - - (set-who! condition-accessor - (lambda (rtd proc) - (define accessor-error - (lambda (x rtd) - ($oops 'generated-condition-accessor - "~s is not a condition of the type represented by ~s" - x rtd))) - (check-&condition-subtype! who rtd) - (rec generated-condition-accessor - (lambda (x) - (cond - [(record? x rtd) (proc x)] - [(compound-condition? x) - (let f ([ls (compound-condition-components x)]) - (if (null? ls) - (accessor-error x rtd) - (let ([x (car ls)]) - (if (record? x rtd) - (proc x) - (f (cdr ls))))))] - [else (accessor-error x rtd)])))))) - -(define-syntax define-condition-type - (lambda (x) - (syntax-case x () - [(_ type-name super-type constructor predicate? (field-name accessor) ...) - (with-syntax ([($accessor ...) (generate-temporaries #'(accessor ...))] - [msg (format "~~s is not a condition of type ~a" (datum type-name))]) - #'(begin - (define-record-type (type-name constructor $predicate?) - (nongenerative) - (parent super-type) - (fields (immutable field-name $accessor) ...)) - (define predicate? - (lambda (x) - (or ($predicate? x) - (and ($compound-condition? x) - (ormap $predicate? ($compound-condition-components x)))))) - (define accessor - (lambda (x) - (define accessor-error (lambda (x) ($oops 'accessor msg x))) - (cond - [($predicate? x) ($accessor x)] - [($compound-condition? x) - (let f ([ls ($compound-condition-components x)]) - (if (null? ls) - (accessor-error x) - (let ([x (car ls)]) - (if ($predicate? x) - ($accessor x) - (f (cdr ls))))))] - [else (accessor-error x)]))) - ...))]))) - -(eval-when (compile) -(define-syntax define-system-condition-type - (lambda (x) - (syntax-case x () - [(_ type-name super-type uid constructor predicate? (field-name accessor) ...) - (with-syntax ([($accessor ...) (generate-temporaries #'(accessor ...))] - [msg (format "~~s is not a condition of type ~a" (datum type-name))]) - #'(begin - (define-record-type (type-name constructor $predicate?) - (nongenerative uid) - (parent super-type) - (fields (immutable field-name $accessor) ...)) - (define predicate? - (lambda (x) - (or ($predicate? x) - (and ($compound-condition? x) - (ormap $predicate? ($compound-condition-components x)))))) - (define accessor - (lambda (x) - (define accessor-error (lambda (x) ($oops 'accessor msg x))) - (cond - [($predicate? x) ($accessor x)] - [($compound-condition? x) - (let f ([ls ($compound-condition-components x)]) - (if (null? ls) - (accessor-error x) - (let ([x (car ls)]) - (if ($predicate? x) - ($accessor x) - (f (cdr ls))))))] - [else (accessor-error x)]))) - ...))]))) -) - -;;; standard condition types - -;;; taking advantage of body-like semantics of begin to arrange for each -;;; condition type's compile-time information to be available for use in -;;; defining its child types, even though the system is compiled with -;;; (eval-syntax-expanders-when) not including compile. -(begin -(let-syntax ([a (syntax-rules () - [(_ &condition) ; leave only &condition visible - (define-record-type (&condition make-simple-condition simple-condition?) - (nongenerative #{&condition oyb459ue1fphfx4-a}))])]) - (a &condition)) - -(define-system-condition-type &message &condition #{&message bwptyckgidgnsihx-a} - make-message-condition message-condition? - (message condition-message)) - -(define-system-condition-type &warning &condition #{&warning bwtai41dgaww3fus-a} - make-warning warning?) - -(define-system-condition-type &serious &condition #{&serious bwvzuvr26s58u3l9-a} - make-serious-condition serious-condition?) - -(define-system-condition-type &error &serious #{&error bwyo6misxbfkmrdg-a} - make-error error?) - -(define-system-condition-type &violation &serious #{&violation bw1eic9intowee4m-a} - make-violation violation?) - -(define-system-condition-type &assertion &violation #{&assertion bw33t3z8ebx752vs-a} - make-assertion-violation assertion-violation?) - -(define-system-condition-type &irritants &condition #{&irritants bw6s5uqx4t7jxqmy-a} - make-irritants-condition irritants-condition? - (irritants condition-irritants)) - -(define-system-condition-type &who &condition #{&who bw9ihlhnvcgvped6-a} - make-who-condition who-condition? - (who condition-who)) - -(define-system-condition-type &non-continuable &violation #{&non-continuable bxb7tb8dlup7g15e-a} - make-non-continuable-violation - non-continuable-violation?) - -(define-system-condition-type &implementation-restriction &violation #{&implementation-restriction bxew42y3cczi8pwl-a} - make-implementation-restriction-violation - implementation-restriction-violation?) - -(define-system-condition-type &lexical &violation #{&lexical bxhmgtps2u8u0dns-a} - make-lexical-violation lexical-violation?) - -(define-system-condition-type &syntax &violation #{&syntax bxkbskgitdh6r1ey-a} - make-syntax-violation syntax-violation? - (form syntax-violation-form) - (subform syntax-violation-subform)) - -(define-system-condition-type &undefined &violation #{&undefined bxm04a68jvrijo54-a} - make-undefined-violation undefined-violation?) - -;;; io conditions - -(define-system-condition-type &i/o &error #{&i/o bxpqf1xyad0ubcxc-a} - make-i/o-error i/o-error?) - -(define-system-condition-type &i/o-read &i/o #{&i/o-read bxsfrson0v9520oj-a} - make-i/o-read-error i/o-read-error?) - -(define-system-condition-type &i/o-write &i/o #{&i/o-write bxu43jfdrejhuofp-a} - make-i/o-write-error i/o-write-error?) - -(define-system-condition-type &i/o-invalid-position &i/o #{&i/o-invalid-position bxxue953hwstmb6v-a} - make-i/o-invalid-position-error - i/o-invalid-position-error? - (position i/o-error-position)) - -(define-system-condition-type &i/o-filename &i/o #{&i/o-filename bx0jq0ws8e15dzx4-a} - make-i/o-filename-error i/o-filename-error? - (filename i/o-error-filename)) - -(define-system-condition-type &i/o-file-protection &i/o-filename #{&i/o-file-protection bx282rniyxbg5npc-a} - make-i/o-file-protection-error - i/o-file-protection-error?) - -(define-system-condition-type &i/o-file-is-read-only &i/o-file-protection #{&i/o-file-is-read-only bx5yeid8pfksxbgj-a} - make-i/o-file-is-read-only-error - i/o-file-is-read-only-error?) - -(define-system-condition-type &i/o-file-already-exists &i/o-filename #{&i/o-file-already-exists bx8np84yfxt4oy7q-a} - make-i/o-file-already-exists-error - i/o-file-already-exists-error?) - -(define-system-condition-type &i/o-file-does-not-exist &i/o-filename #{&i/o-file-does-not-exist bybc1zvn6f3ggmyw-a} - make-i/o-file-does-not-exist-error - i/o-file-does-not-exist-error?) - -(define-system-condition-type &i/o-port &i/o #{&i/o-port byd2dqmdwycr8ap5-a} - make-i/o-port-error i/o-port-error? - (pobj i/o-error-port)) - -(define-system-condition-type &i/o-decoding &i/o-port #{&i/o-decoding bygrphc3ngl3zyhc-a} - make-i/o-decoding-error i/o-decoding-error?) - -(define-system-condition-type &i/o-encoding &i/o-port #{&i/o-encoding byjg073tdyvfrl8i-a} - make-i/o-encoding-error i/o-encoding-error? - (cobj i/o-encoding-error-char)) - -;;; arithmetic conditions - -(define-system-condition-type &no-infinities &implementation-restriction #{&no-infinities byl6cyui4g4ri9zq-a} - make-no-infinities-violation - no-infinities-violation?) - -(define-system-condition-type &no-nans &implementation-restriction #{&no-nans byovopk8uzd3axqx-a} - make-no-nans-violation no-nans-violation?) - -;;; Chez Scheme conditions - -(define-system-condition-type &source &condition #{&source byrk0gbylhne2lh4-a} - make-source-condition source-condition? - (form source-condition-form)) - -(define-system-condition-type $&src &condition #{$&src byul0m8re6e47nnb-a} - $make-src-condition $src-condition? - (src $src-condition-src) - (start $src-condition-start)) - -(define-system-condition-type &format &condition #{&format byxbcdzg5oogzbei-a} - make-format-condition format-condition?) - -(define-system-condition-type &continuation &condition #{&continuation dxr8vukkubd1tr8-a} - make-continuation-condition continuation-condition? - (k condition-continuation)) - -(define-system-condition-type $&recompile &error #{&recompile eb5ipy47b8hscnlzoga59k-0} - $make-recompile-condition $recompile-condition? - (importer-path $recompile-importer-path)) -) - -(let () - (define avcond (make-assertion-violation)) - (define econd (make-error)) - (define wcond (make-warning)) - (define fcond (make-format-condition)) - (define favcond (condition avcond fcond)) - (define fecond (condition econd fcond)) - (define fwcond (condition wcond fcond)) - (define ircond (make-implementation-restriction-violation)) - (define fimpcond (condition ircond fcond)) - (define flexcond (condition (make-lexical-violation) (make-i/o-read-error) fcond)) - (define flexcond/ir (condition ircond (make-lexical-violation) (make-i/o-read-error) fcond)) - - (define (error-help warning? who whoarg message irritants basecond) - (unless (or (eq? whoarg #f) (string? whoarg) (symbol? whoarg)) - ($oops who "invalid who argument ~s (message = ~s, irritants = ~s)" whoarg message irritants)) - (unless (string? message) - ($oops who "invalid message argument ~s (who = ~s, irritants = ~s)" message whoarg irritants)) - (let ([c (if whoarg - (if irritants - (condition basecond - (make-who-condition whoarg) - (make-message-condition message) - (make-irritants-condition irritants)) - (condition basecond - (make-who-condition whoarg) - (make-message-condition message))) - (if irritants - (condition basecond - (make-message-condition message) - (make-irritants-condition irritants)) - (condition basecond - (make-message-condition message))))]) - (if warning? - (raise-continuable c) - (call/cc - (lambda (k) - (raise (condition c (make-continuation-condition k)))))))) - - (set-who! assertion-violation - (lambda (whoarg message . irritants) - (error-help #f who whoarg message irritants avcond))) - - (set-who! assertion-violationf - (lambda (whoarg message . irritants) - (error-help #f who whoarg message irritants favcond))) - - (set-who! $oops - (lambda (whoarg message . irritants) - (error-help #f who whoarg message irritants favcond))) - - (set-who! $oops/c - (lambda (whoarg basecond message . irritants) - (error-help #f who whoarg message irritants - (condition basecond fcond)))) - - (set-who! $impoops - (lambda (whoarg message . irritants) - (error-help #f who whoarg message irritants fimpcond))) - - (set-who! $record-oops - (lambda (whoarg nonrec rtd) - (unless (record-type-descriptor? rtd) - ($oops who "~s is not a record-type descriptor" rtd)) - (when (record? nonrec rtd) - ($oops who "~s actually is of type ~s" nonrec rtd)) - (error-help #f who whoarg "~s is not of type ~s" (list nonrec rtd) favcond))) - - (set-who! error - (lambda (whoarg message . irritants) - (error-help #f who whoarg message irritants econd))) - - (set-who! errorf - (lambda (whoarg message . irritants) - (error-help #f who whoarg message irritants fecond))) - - (set-who! warning - (lambda (whoarg message . irritants) - (error-help #t who whoarg message irritants wcond))) - - (set-who! warningf - (lambda (whoarg message . irritants) - (error-help #t who whoarg message irritants fwcond))) - - (let () - (define (infer-who form) - (syntax-case form () - [id (identifier? #'id) (datum id)] - [(id . stuff) (identifier? #'id) (datum id)] - [_ #f])) - (set-who! syntax-violation - (case-lambda - [(whoarg message form) - (error-help #f who (or whoarg (infer-who form)) message #f - (condition avcond (make-syntax-violation form #f)))] - [(whoarg message form subform) - (error-help #f who (or whoarg (infer-who form)) message #f - (make-syntax-violation form subform))]))) - - (set-who! syntax-error - (lambda (form . messages) - (for-each - (lambda (m) (unless (string? m) ($oops who "~s is not a string" m))) - messages) - (error-help #f who #f - (if (null? messages) "invalid syntax" (apply string-append messages)) - #f (make-syntax-violation form #f)))) - - (set-who! $undefined-violation - (lambda (id message) - (error-help #f who #f message #f - (condition (make-undefined-violation) (make-syntax-violation id #f))))) - - (set-who! $lexical-error - (case-lambda - [(whoarg msg args port ir?) - (error-help #f who whoarg msg args - (condition - (make-i/o-port-error port) - (if ir? flexcond/ir flexcond)))] - [(whoarg msg args port src start? ir?) - (error-help #f who whoarg msg args - (condition - (make-i/o-port-error port) - (if ir? flexcond/ir flexcond) - ($make-src-condition src start?)))])) - - (set-who! $source-violation - (lambda (whoarg src start? msg . args) - (error-help #f who whoarg msg args - (if src - (condition favcond ($make-src-condition src start?)) - favcond)))) - - (set-who! $source-warning - (lambda (whoarg src start? msg . args) - (error-help #t who whoarg msg args - (if src - (condition fwcond ($make-src-condition src start?)) - fwcond)))) -) -) diff --git a/ta6ob/s/exceptions.ta6ob b/ta6ob/s/exceptions.ta6ob deleted file mode 100644 index f53cccf..0000000 Binary files a/ta6ob/s/exceptions.ta6ob and /dev/null differ diff --git a/ta6ob/s/expand-lang.ss b/ta6ob/s/expand-lang.ss deleted file mode 100644 index 0505b6f..0000000 --- a/ta6ob/s/expand-lang.ss +++ /dev/null @@ -1,114 +0,0 @@ -;;; expand-lang.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(define-record-type libreq - (fields - (immutable path) - (immutable version) - (immutable uid)) - (nongenerative #{libreq fnuxvkuvs8x0xbc68h3hm6-0}) - (sealed #t)) - -(define-record-type recompile-info - (fields - (immutable import-req*) - (immutable include-req*)) - (nongenerative #{recompile-info fnuxvkuvs8x0xbc68h3hm6-1}) - (sealed #t)) - -(define-record-type library-info - (nongenerative #{library-info e10vy7tci6bqz6pmnxgvlq-3}) - (fields - (immutable path) - (immutable version) - (immutable uid) - (immutable visible?))) - -(define-record-type library/ct-info - (parent library-info) - (fields - (immutable import-req*) - (immutable visit-visit-req*) - (immutable visit-req*)) - (nongenerative #{library/ct-info fgf0koeh2zn6ajlujfyoyf-4}) - (sealed #t)) - -(define-record-type library/rt-info - (parent library-info) - (fields - (immutable invoke-req*)) - (nongenerative #{library/rt-info ff86rtm7efmvxcvrmh7t0b-3}) - (sealed #t)) - -(define-record-type program-info - (fields (immutable uid) (immutable invoke-req*)) - (nongenerative #{program-info fgc8ptwnu9i5gfqz3s85mr-0}) - (sealed #t)) - -(module (Lexpand Lexpand?) - (define library-path? - (lambda (x) - (and (list? x) (andmap symbol? x)))) - - (define library-version? - (lambda (x) - (and (list? x) - (andmap (lambda (x) (and (integer? x) (exact? x) (>= x 0))) x)))) - - (define maybe-optimization-loc? (lambda (x) (or (not x) (box? x)))) ; should be a record - - (define maybe-label? (lambda (x) (or (not x) (gensym? x)))) - - (define-language Lexpand - (nongenerative-id #{Lexpand fgy7v2wrvj0so4ro8kvhqo-3}) - (terminals - (maybe-label (dl)) - (gensym (uid export-id)) - (library-path (path)) - (library-version (version)) - (maybe-optimization-loc (db)) - (prelex (dv)) - (libreq (import-req visit-req visit-visit-req invoke-req)) - (string (include-req)) - (Lsrc (lsrc body init visit-code import-code de)) => unparse-Lsrc - (recompile-info (rcinfo)) - (library/ct-info (linfo/ct)) - (library/rt-info (linfo/rt)) - (program-info (pinfo))) - (Outer (outer) - (recompile-info rcinfo) - (group outer1 outer2) - (visit-only inner) - (revisit-only inner) - inner) - (Inner (inner) - (library/ct-info linfo/ct) - ctlib - (library/rt-info linfo/rt) - rtlib - (program-info pinfo) - prog - lsrc) - (ctLibrary (ctlib) - (library/ct uid (export-id* ...) import-code visit-code)) - (rtLibrary (rtlib) - (library/rt uid - (dl* ...) - (db* ...) - (dv* ...) - (de* ...) - body)) - (Program (prog) - (program uid body)))) diff --git a/ta6ob/s/expeditor.ss b/ta6ob/s/expeditor.ss deleted file mode 100644 index 1120420..0000000 --- a/ta6ob/s/expeditor.ss +++ /dev/null @@ -1,3054 +0,0 @@ -;;; expeditor.ss -;;; R. Kent Dybvig -;;; August 2007 - -;;; This code is based on David Boyer's command-line editor, which has the -;;; following copyright: -;;; -;;; Copyright (c) 1989, 1993, 1994 C. David Boyer -;;; -;;; Permission to copy this software, in whole or in part, to use this -;;; software for any lawful purpose, and to redistribute this software is -;;; granted subject to the restriction that all copies made of this software -;;; must include this copyright notice in full. -;;; -;;; The present implementation retains some of the basic design but little -;;; of the original code. - -;;; The expression editor module is organized into sections: -;;; -;;; 1. screen-management routines -;;; 2. exported parameters -;;; 3. eestate and pos record definitions -;;; 4. current entry management routines -;;; 5. the reader and prompt-and-reader -;;; 6. history management routines -;;; 7. key function definitions -;;; 8. key binding code -;;; -;;; Also contained within this file are a few system entry points: -;;; the $enable-expeditor and $expeditor-history-file parameters and -;;; the main entry point into the expression editor, $expeditor. - -(when-feature expeditor - -(define $enable-expeditor (make-parameter #f)) -(define $expeditor-history-file - (make-parameter #f - (lambda (s) - (cond - [(not s) s] - [(string? s) - (if (string=? s "") - (if-feature windows - (cond - [(getenv "APPDATA") => - (lambda (appdata) - (let ([dir (format "~a\\Chez Scheme" appdata)]) - (unless (file-exists? dir) - (guard (c [#t (void)]) (mkdir dir))) - (format "~a\\History" dir)))] - [(getenv "HOME") => - (lambda (home) - (format "~a\\.chezscheme_history" home))] - [else ".chezscheme_history"]) - "~/.chezscheme_history") - s)] - [else ($oops '$expeditor-history-file "~s is not #f or a string" s)])))) - -(define $expeditor) - -(module expression-editor - ( - ; parameters - ee-auto-indent ee-auto-paren-balance ee-common-identifiers - ee-default-repeat ee-flash-parens ee-noisy - ee-paren-flash-delay ee-history-limit ee-standard-indent - ; establishing key bindings - ee-bind-key ee-compose - ; built-in operators - ee-next-id-completion - ee-next-id-completion/indent - ee-id-completion ee-id-completion/indent - ee-insert-self ee-command-repeat - ee-history-bwd ee-history-fwd - ee-history-fwd-prefix ee-history-bwd-prefix - ee-history-fwd-contains ee-history-bwd-contains - ee-newline ee-accept ee-newline/accept ee-open-line - ee-indent ee-indent-all ee-backward-char - ee-forward-char ee-next-line ee-previous-line - ee-end-of-line ee-beginning-of-line - ee-beginning-of-entry ee-end-of-entry - ee-delete-to-eol ee-delete-line - ee-delete-between-point-and-mark ee-set-mark - ee-delete-entry ee-reset-entry ee-delete-sexp ee-backward-delete-sexp - ee-redisplay ee-yank-kill-buffer ee-yank-selection - ee-string-macro ee-eof ee-delete-char ee-eof/delete-char - ee-backward-delete-char ee-insert-paren - ee-flash-matching-delimiter ee-goto-matching-delimiter - ee-exchange-point-and-mark ee-forward-sexp - ee-backward-sexp ee-forward-word - ee-backward-word ee-forward-page - ee-backward-page ee-suspend-process - ) - -(define-syntax assert* - (syntax-rules () - [(_ expr ...) - (begin (assert expr) ...)])) - -(define-syntax on-error - (syntax-rules () - [(on-error e0 e1 e2 ...) - (guard (c [#t e0]) e1 e2 ...)])) - -(define-syntax defopt - (syntax-rules () - [(_ (p x ... [y e]) b1 b2 ...) - (define p - (case-lambda - [(x ...) (p x ... e)] - [(x ... y) b1 b2 ...]))])) - -; screen initialization and manipulation routines - -(module (init-screen raw-mode no-raw-mode - screen-resize! screen-rows screen-cols - ee-winch? ee-char-ready? ee-peek-char ee-read-char - ee-write-char ee-display-string ee-flush - move-cursor-up move-cursor-right move-cursor-left move-cursor-down - scroll-reverse clear-eol clear-eos clear-screen - carriage-return line-feed - bell pause get-clipboard wait) - ; screen state - (define cols) - (define rows) - (define cursor-col) - (define the-unread-char) - (define winch) - - ; we use terminfo routines directly, rather than going through curses, - ; because curses requires initscr(), which clears the screen, discarding - ; the current context. this is a shell, not a full-screen user interface. - - (define init-term (foreign-procedure "(cs)ee_init_term" () boolean)) - (define $ee-read-char (foreign-procedure "(cs)ee_read_char" (boolean) scheme-object)) - (define $ee-write-char (foreign-procedure "(cs)ee_write_char" (wchar_t) void)) - (define ee-flush (foreign-procedure "(cs)ee_flush" () void)) - (define get-screen-size (foreign-procedure "(cs)ee_get_screen_size" () scheme-object)) - (define raw-mode (foreign-procedure "(cs)ee_raw" () void)) - (define no-raw-mode (foreign-procedure "(cs)ee_noraw" () void)) - (define enter-am-mode (foreign-procedure "(cs)ee_enter_am_mode" () void)) - (define exit-am-mode (foreign-procedure "(cs)ee_exit_am_mode" () void)) - (define nanosleep (foreign-procedure "(cs)ee_nanosleep" (unsigned-32 unsigned-32) void)) - (define pause (foreign-procedure "(cs)ee_pause" () void)) - (define get-clipboard (foreign-procedure "(cs)ee_get_clipboard" () scheme-object)) - - (define move-cursor-up (foreign-procedure "(cs)ee_up" (integer-32) void)) - (define move-cursor-down (foreign-procedure "(cs)ee_down" (integer-32) void)) - (define $move-cursor-left (foreign-procedure "(cs)ee_left" (integer-32) void)) - (define $move-cursor-right (foreign-procedure "(cs)ee_right" (integer-32) void)) - (define clear-eol (foreign-procedure "(cs)ee_clr_eol" () void)) - (define clear-eos (foreign-procedure "(cs)ee_clr_eos" () void)) - (define $clear-screen (foreign-procedure "(cs)ee_clear_screen" () void)) - (define scroll-reverse (foreign-procedure "(cs)ee_scroll_reverse" (integer-32) void)) - (define bell (foreign-procedure "(cs)ee_bell" () void)) - (define $carriage-return (foreign-procedure "(cs)ee_carriage_return" () void)) - (define line-feed (foreign-procedure "(cs)ee_line_feed" () void)) - - (define (screen-resize!) - (let ([p (get-screen-size)]) - (set! rows (car p)) - (set! cols (cdr p)))) - - (define (screen-rows) rows) - (define (screen-cols) cols) - - (define (init-screen) - (and (init-term) - (begin - (set! cursor-col 0) - (set! the-unread-char #f) - (set! winch #f) - #t))) - - (define (clear-screen) - ($clear-screen) - (set! cursor-col 0)) - - (define (ee-winch?) - (and (not the-unread-char) - (if winch - (begin (set! winch #f) #t) - (begin - (ee-flush) - (let ([c ($ee-read-char #t)]) - (or (eq? c #t) - (begin (set! the-unread-char c) #f))))))) - - (define (ee-char-ready?) - (if the-unread-char - #t - (let f () - (ee-flush) - (let ([c ($ee-read-char #f)]) - (cond - [(eq? c #f) #f] - [(eq? c #t) (set! winch #t) (f)] - [else (set! the-unread-char c) #t]))))) - - (define (ee-read-char) - (if the-unread-char - (let ([c the-unread-char]) (set! the-unread-char #f) c) - (let f () - (ee-flush) - (let ([c ($ee-read-char #t)]) - (if (eq? c #t) - (begin (set! winch #t) (f)) - c))))) - - (define (ee-peek-char) - (or the-unread-char - (let ([c (ee-read-char)]) - (set! the-unread-char c) - c))) - - ; we assume that ee-write-char receives only characters that occupy one - ; screen cell. it should never be passed #\return, #\newline, or #\tab. - ; furthermore, ee-write-char should never be used to write past the end - ; of a screen line. - (define (ee-write-char c) - (set! cursor-col (fx+ cursor-col 1)) - (if (fx= cursor-col cols) - (begin - (exit-am-mode) - ($ee-write-char c) - (enter-am-mode)) - ($ee-write-char c))) - - ; comments regarding ee-write-char above apply also to ee-display-string - (define (ee-display-string s) - (let ([n (string-length s)]) - (do ([i 0 (fx+ i 1)]) - ((fx= i n)) - (ee-write-char (string-ref s i))))) - - (define (carriage-return) - (set! cursor-col 0) - ($carriage-return)) - - (define (move-cursor-right n) - (cond - [(fx< (fx+ cursor-col n) cols) - ($move-cursor-right n) - (set! cursor-col (fx+ cursor-col n))] - [else - (move-cursor-down (quotient (fx+ cursor-col n) cols)) - (let ([new-cursor-col (remainder (fx+ cursor-col n) cols)]) - (if (fx>= new-cursor-col cursor-col) - (move-cursor-right (fx- new-cursor-col cursor-col)) - (move-cursor-left (fx- cursor-col new-cursor-col))))])) - - (define (move-cursor-left n) - (when (and (fx= cursor-col cols) (fx> n 0)) - (set! n (fx- n 1)) - (set! cursor-col (fx- cursor-col 1))) - (cond - [(fx<= n cursor-col) - ($move-cursor-left n) - (set! cursor-col (fx- cursor-col n))] - [else - (move-cursor-up (fx1+ (quotient (fx- n cursor-col 1) cols))) - (let ([new-cursor-col (remainder - (fx- cols (remainder (fx- n cursor-col) cols)) - cols)]) - (if (fx>= new-cursor-col cursor-col) - (move-cursor-right (fx- new-cursor-col cursor-col)) - (move-cursor-left (fx- cursor-col new-cursor-col))))])) - - (define wait - (lambda (ms) - (unless (or (<= ms 0) (ee-char-ready?)) - (nanosleep 0 (* 10 1000 1000)) ; 10ms granularity is best we can assume - (wait (- ms 10))))) -) - -;;; parameters - -(define ee-common-identifiers - (make-parameter - ; general theory: exclude short ids and ids that will come up early - ; in an alphabetical search with short prefix. include common ids that - ; come up annoyingly late in such a search. - '(append apply call/cc call-with-values define display display-string - define-syntax define-record null? quote quotient reverse read-char - substring string-ref string-length string? string=? string-set! - syntax-case syntax-rules unless vector-ref vector-length vector? - vector-set! vector) - (lambda (x) - (unless (and (list? x) (andmap symbol? x)) - ($oops 'ee-common-identifiers "~s is not a list of symbols" x)) - x))) - -;;; default repeat value for ^U -(define ee-default-repeat - (make-parameter 4 - (lambda (x) - (unless (and (fixnum? x) (fxnonnegative? x)) - ($oops 'ee-default-repeat "~s is not an integer" x)) - x))) - -(define ee-auto-indent (make-parameter #t (lambda (x) (and x #t)))) - -(define ee-auto-paren-balance (make-parameter #t (lambda (x) (and x #t)))) - -(define ee-flash-parens (make-parameter #t (lambda (x) (and x #t)))) - -;;; paren balance delay factor in milliseconds -(define ee-paren-flash-delay - (make-parameter 100 - (lambda (x) - (unless (and (fixnum? x) (fxnonnegative? x)) - ($oops 'ee-paren-flash-delay "~s is not an integer" x)) - x))) - -;;; enable/disable bell -(define ee-noisy (make-parameter #f (lambda (x) (and x #t)))) - -;;; standard indent length -(define ee-standard-indent - (make-parameter 2 - (lambda (x) - (unless (and (fixnum? x) (fxnonnegative? x)) - ($oops 'ee-standard-indent "~s is not an integer" x)) - x))) - -(define ee-history-limit - (make-parameter 256 - (lambda (x) - (unless (and (fixnum? x) (fxnonnegative? x)) - ($oops 'ee-history-length "~s is not a nonnegative fixnum" x)) - x))) - -;;; eestate holds the state of the expression editor. - -(define-record-type eestate - (fields - (mutable last-op) - (mutable rt-last-op) - (mutable prompt) - (mutable repeat-count) - (mutable killbuf) - (mutable histnew) - (mutable histbwd) - (mutable histnow) - (mutable histfwd) - (mutable histkey) - (mutable last-suffix*) - (mutable cc?)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda () - (new #f ; last-op - '(0 . 0) ; rt-last-op - "" ; prompt - 1 ; repeat-count - '() ; killbuf - 0 ; histnew - '() ; histbwd - "" ; histnow - '() ; hisfwd - "" ; histkey - '() ; last-suffix* - #f))))) ; cc? - -(module () - (record-writer (type-descriptor eestate) - (lambda (x p wr) - (display "#" p)))) - -;;; pos is used for two different but related purposes: for row, col -;;; positions and for row, physical-line positions. see the comment -;;; about the entry top-line and bot-line fields below. - -(module (make-pos pos? pos-row pos-col pos=? pos? pos>=? index->pos) - (define-record-type pos - (fields (immutable row) (immutable col)) - (nongenerative) - (sealed #t)) - (define (pos=? p1 p2) - (and (fx= (pos-row p1) (pos-row p2)) - (fx= (pos-col p1) (pos-col p2)))) - (define (pos? p1 p2) - (or (fx> (pos-row p1) (pos-row p2)) - (and (fx= (pos-row p1) (pos-row p2)) - (fx> (pos-col p1) (pos-col p2))))) - (define (pos>=? p1 p2) - (or (fx> (pos-row p1) (pos-row p2)) - (and (fx= (pos-row p1) (pos-row p2)) - (fx>= (pos-col p1) (pos-col p2))))) - (define (index->pos s n r c) - ; convert index in single-string representation of entry - ; into pos. r and c are row and col at which string - ; starts in the entry - (let f ([i 0] [r r] [c c]) - (if (fx= i n) - (make-pos r c) - (if (char=? (string-ref s i) #\newline) - (f (fx+ i 1) (fx+ r 1) 0) - (f (fx+ i 1) r (fx+ c 1)))))) - (record-writer (type-descriptor pos) - (lambda (x p wr) - (fprintf p "#" (pos-row x) (pos-col x)))) -) - -(define lpchar #\() -(define rpchar #\)) -(define lbchar #\[) -(define rbchar #\]) - -(define beep - (lambda (str . arg*) - #;(with-output-to-file "/tmp/ee.log" - (lambda () (apply printf str arg*) (newline)) - 'append) - (when (ee-noisy) (bell)))) - -(module (string->entry - entry->string - string->lines - ; primtiive and derived record accessors and mutators: no ee argument - entry-col - entry-nsr - entry-row - entry-mark - entry-point - null-entry? - entry-mark-set! - entry-row-set! - entry-col-set! - ; normal entry procedures: first two arguments are ee and entry - add-char - beginning-of-line? - clear-entry - id-completions - correct&flash-matching-delimiter - yank-entry - delete-char - delete-forward - delete-to-eol - echo-entry - end-of-line? - find-matching-delimiter - find-next-sexp-backward - find-next-sexp-forward - find-next-word - find-previous-word - first-line? - flash - goto - handle-winch - indent - indent-all - insert-string-before - insert-strings-before - join-rows - last-line? - last-line-displayed? - move-bol - move-down - move-eoe - move-eol - move-left - move-right - move-up - only-whitespace-left? - page-down - page-up - redisplay - should-auto-indent?) - - ; NB. top-line and bot-line aren't really positions. - ; the row does identify the logical row, but the col identifies the - ; physical row of the logical row, i.e., 0 for the first physical - ; row, 1 for the second, etc. - - (define-record-type entry - (fields - (immutable lns) ; logical lines - (mutable row) ; point (logical cursor) row - (mutable col) ; point (logical cursor) column - (mutable screen-cols) ; cached screen columns - (mutable screen-rows) ; cached screen rows - (mutable top-line) ; first displayed line - (mutable bot-line) ; last displayed line - (mutable mark)) ; current mark pos - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (lns) - (new lns 0 0 (screen-cols) (screen-rows) - (make-pos 0 0) (make-pos 0 0) #f))))) - - (module () - (record-writer (type-descriptor entry) - (lambda (x p wr) - (display "#" p)))) - - (define (entry-point entry) - (make-pos (entry-row entry) (entry-col entry))) - - ;;; an lns is a nonempty list of logical lines, each of which may span - ;;; multiple screen lines. each line consists of an integer that records - ;;; the number of screen rows spanned along with a string containing - ;;; the text of the line. lines are implicitly separated by newlines; no - ;;; newlines appear in the strings themselves. - ;;; - ;;; lns := (ln ln ...) ;;; list of "ln"s - ;;; ln := [nsr, str] - ;;; nsr := integer ;;; number of screen rows occupied by the line - ;;; str := string ;;; contents of the line - - ; arrange for nsr to be updated whenever str is changed - (module (make-ln ln? ln-str ln-nsr ln-str-set! ln-nsr-set!) - (define-record-type (ln make-ln ln?) - (fields - (mutable str ln-str $ln-str-set!) - (mutable nsr ln-nsr ln-nsr-set!)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (ee str) - (new str (str->nsr ee str)))))) - (define (ln-str-set! ee ln str) - ($ln-str-set! ln str) - (ln-nsr-set! ln (str->nsr ee str)))) - - ; extract nsr or str from selected row of lns - (define (lns->nsr lns row) (ln-nsr (list-ref lns row))) - (define (lns->str lns row) (ln-str (list-ref lns row))) - - ; replace str in selected row of lns - (define (lns->str! ee lns row str) - (ln-str-set! ee (list-ref lns row) str)) - - (define (lns->char lns row col) - (let ([str (lns->str lns row)]) - (if (fx< col (string-length str)) - (string-ref str col) - #f))) - - (define (yank-entry ee entry) - (map ln-str (entry-lns entry))) - - (define (entry->string entry) - (let* ([lns (entry-lns entry)] [n (length lns)]) - (let ([sop (open-output-string)]) - (let loop ([i 0] [sep ""]) - (unless (fx= i n) - (fprintf sop "~a~a" sep (lns->str lns i)) - (loop (fx+ i 1) "\n"))) - (get-output-string sop)))) - - (define (echo-entry ee entry tp) - (display-string (eestate-prompt ee) tp) - (let ([lns (entry-lns entry)]) - (fprintf tp "~a\n" (ln-str (car lns))) - (for-each - (let ([pad (phantom-prompt ee)]) - (lambda (ln) (fprintf tp "~a~a\n" pad (ln-str ln)))) - (cdr lns))) - (flush-output-port tp)) - - (define (string->lines s) - ; break string into list of lines while expanding tabs - (let ([n (string-length s)] [op (open-output-string)]) - (let f ([i 0] [col 0]) - (if (fx= i n) - (list (get-output-string op)) - (let ([c (string-ref s i)]) - (case c - [(#\newline) - (let ([line (get-output-string op)]) - (cons line (f (fx+ i 1) 0)))] - [(#\tab) - (do ([i (fx- 8 (fxmodulo col 8)) (fx- i 1)]) - ((fx= i 0)) - (write-char #\space op)) - (f (fx+ i 1) 0)] - [(#\return) (f (fx+ i 1) col)] - [else (write-char c op) (f (fx+ i 1) (fx+ col 1))])))))) - - (define (string->entry ee s) - (let ([ln* (map (lambda (str) (make-ln ee str)) (string->lines s))]) - (make-entry (if (null? ln*) (list (make-ln ee "")) ln*)))) - - (define (null-entry? entry) - (let ([lns (entry-lns entry)]) - (and (fx= (length lns) 1) - (equal? (ln-str (car lns)) "")))) - - (define (entry-nsr entry) (apply fx+ (map ln-nsr (entry-lns entry)))) - - ;;; split a logical row into a list of strings each of which will fit - ;;; on a screen line, starting at logical column col. - (define split-string - (lambda (ee str col) - (let ([str-len (string-length str)]) - (let f ([col col] [width (fx- (screen-cols) (col->screen-col ee col))]) - (if (fx< (fx- str-len col) width) - (list (substring str col str-len)) - (cons (substring str col (fx+ col width)) - (f (fx+ col width) (screen-cols)))))))) - - (define (screen-lines-between ee entry toprow topoff nextrow nextoff) - ; returns distance in physical screen lines between physical line - ; topoff of toprow and nextoff of nextrow - (let ([lns (entry-lns entry)]) - (let f ([i toprow] [off topoff] [lns (list-tail lns toprow)]) - (if (fx= i nextrow) - (fx- nextoff off) - (fx+ (fx- (ln-nsr (car lns)) off) - (f (fx+ i 1) 0 (cdr lns))))))) - - (define (str->nsr ee str) - (fx+ (col->line-offset ee (string-length str)) 1)) - - ;;; return the line offset based on the column and screen size - ;;; ||-offset=2 (prompt) - ;;; example: if: col = 15 vv - ;;; offset = 2 ----------- - ;;; scrn-cols = 10 |> line-000| line-offset 0 - ;;; then: |line-11111| line-offset 1 - ;;; line-offset = 1 ^column = 15 - (define col->line-offset - (lambda (ee col) - (fxquotient (fx+ (string-length (eestate-prompt ee)) col) (screen-cols)))) - - ;;; return the actual screen column based on the logical row column - ;;; example: if: col = 15 vv-offset=2 (prompt) - ;;; offset = 2 ----------- - ;;; scrn-cols = 10 |> line-000| line-offset 0 - ;;; then: |line-11111| line-offset 1 - ;;; scrn-col = 7 ^column = 15 - (define col->screen-col - (lambda (ee col) - (fxremainder (fx+ col (string-length (eestate-prompt ee))) (screen-cols)))) - - (define (clear-entry ee entry) - ; like clear-screen, but clears only from top line of entry - (if (visible? ee entry 0 0) - (begin - (carriage-return) - (move-cursor-up - (let ([top-line (entry-top-line entry)]) - (screen-lines-between ee entry - (pos-row top-line) (pos-col top-line) - (entry-row entry) (col->line-offset ee (entry-col entry))))) - (clear-eos)) - (clear-screen))) - - ;;; given bottom line displayed, determines top line that will fill - ;;; the screen to the extent possible - (defopt (calc-top-line-displayed entry last-row-pos [nrows (screen-rows)]) - (let ([lns (entry-lns entry)]) - (let loop ([n nrows] - [r (pos-row last-row-pos)] - [off (pos-col last-row-pos)]) - (if (or (fx= n 1) (and (fx= r 0) (fx= off 0))) - (make-pos r off) - (if (fx= off 0) - (loop (fx- n 1) (fx- r 1) (fx- (lns->nsr lns (fx- r 1)) 1)) - (loop (fx- n 1) r (fx- off 1))))))) - - ;;; given first line displayed, determines bottom line that will fill - ;;; the screen to the extent possible - (defopt (calc-bot-line-displayed entry first-row-pos [nrows (screen-rows)]) - (let* ([lns (entry-lns entry)] - [last-row (fx- (length lns) 1)] - [last-off (fx- (lns->nsr lns last-row) 1)] - [first-row (pos-row first-row-pos)]) - (let loop ([n nrows] - [r first-row] - [off (pos-col first-row-pos)] - [off-max (fx- (lns->nsr lns first-row) 1)]) - (if (or (fx= n 1) (and (fx= r last-row) (fx= off last-off))) - (make-pos r off) - (if (fx= off off-max) - (loop (fx- n 1) (fx+ r 1) 0 (fx- (lns->nsr lns (fx+ r 1)) 1)) - (loop (fx- n 1) r (fx+ off 1) off-max)))))) - - ; NB. the macos x terminal app distinguishes between empty screen - ; positions (e.g., after clr_eos or clr_eol) and screen positions filled - ; with spaces. attempts to move past and clear after the former result - ; in strange behavior. (For example, the sequence clr_eos, cursor_right, - ; clr_eol, 'a', clr_eol, and 'b' doesn't print the b but does cause the - ; terminal to send back some characters. Using ' ' in place of the - ; cursor_right works as expected.) For this reason, we display spaces - ; and avoid using move-cursor-right to pad the front of each row after - ; the first, which gets the actual prompt. - - (define (phantom-prompt ee) - (make-string (string-length (eestate-prompt ee)) #\space)) - - (module (display-rest/goto) - (define (display-rest-of-line ee entry row col clear?) - ; display as much of the rest of row as will fit on the screen - (let ([lns (entry-lns entry)] [bot-line (entry-bot-line entry)]) - ; n = number of lines to display beyond the first - (let loop ([n (fx- (if (fx= row (pos-row bot-line)) - (pos-col bot-line) - (fx- (lns->nsr lns row) 1)) - (col->line-offset ee col))] - [str-lst (split-string ee (lns->str lns row) col)] - [new-col col]) - (when clear? (clear-eol)) - (let ([str (car str-lst)]) - (ee-display-string (car str-lst)) - (let ([new-col (fx+ new-col (string-length str))]) - (if (fx= n 0) - new-col - (begin - (carriage-return) - (line-feed) - (loop (fx- n 1) (cdr str-lst) new-col)))))))) - - (define (display-rest-of-entry ee entry) - (let ([row (entry-row entry)] - [col (entry-col entry)] - [bot-row (pos-row (entry-bot-line entry))]) - (let loop ([new-row row] [start-col col]) - (let ([new-col (display-rest-of-line ee entry new-row start-col #f)]) - (if (fx= new-row bot-row) - (values new-row new-col) - (begin - (carriage-return) - (line-feed) - (ee-display-string (phantom-prompt ee)) - (loop (fx+ new-row 1) 0))))))) - - (define (display-rest/goto ee entry just-row? clear? to-row to-col) - ; display rest of entry and go directly from there to (to-row, to-col) - ; just-row? => only remainder of current logical row needed by displayed - ; clear? => clear-eos or clear-eol needed - (let-values ([(cur-row cur-col) - (if just-row? - (values - (entry-row entry) - (display-rest-of-line ee entry - (entry-row entry) (entry-col entry) clear?)) - (begin - (entry-bot-line-set! entry - (calc-bot-line-displayed entry - (entry-top-line entry))) - (when clear? (clear-eos)) - (display-rest-of-entry ee entry)))]) - (unless (and (fx= cur-row (entry-row entry)) - (fx= cur-col (entry-col entry))) - (entry-row-set! entry cur-row) - ; if the last character written was in the last column of a screen - ; line, move back one so that the cursor is pointing at that character - ; to avoid returning a column value that would wrongly indicate that - ; the cursor is at the start of the next screen line - (if (and (fx> cur-col 0) (fx= (col->screen-col ee cur-col) 0)) - (begin - (move-cursor-left 1) - (entry-col-set! entry (fx- cur-col 1))) - (entry-col-set! entry cur-col))) - (goto ee entry (make-pos to-row to-col))))) - - (module (display-partial-entry) - (define (display-partial-row ee row str start end) - ; displays physical lines of str from start (inclusive) to end (inclusive) - ; assumes cursor is at column zero of start line; leaves cursor at - ; column zero of end line - (let ([ls (list-tail (split-string ee str 0) start)]) - (when (fx= start 0) - (ee-display-string - (if (fx= row 0) - (eestate-prompt ee) - (phantom-prompt ee)))) - (ee-display-string (car ls)) - (carriage-return) - (do ([i start (fx+ i 1)] [ls (cdr ls) (cdr ls)]) - ((fx= i end)) - (line-feed) - (ee-display-string (car ls)) - (carriage-return)))) - - (define (display-partial-entry ee entry toprow topoff botrow botoff) - ; displays physical screen lines between physical line topoff of - ; toprow (inclusive) and botoff of botrow (inclusive) - ; assumes cursor is at column zero of first physical line to be displayed; - ; leaves cursor at column zero of last line displayed - (let ([lns (entry-lns entry)]) - (let loop ([r toprow] [start topoff] [lns (list-tail lns toprow)]) - (display-partial-row ee r (ln-str (car lns)) start - (if (fx= r botrow) botoff (fx- (ln-nsr (car lns)) 1))) - (unless (fx= r botrow) - (line-feed) - (loop (fx+ r 1) 0 (cdr lns))))))) - - (define (goto-backward ee entry new-row new-col) - (assert* (fx>= new-row 0) - (fx>= new-col 0) - (fx<= new-col (string-length (lns->str (entry-lns entry) new-row)))) - (let* ([lns (entry-lns entry)] - [row (entry-row entry)] - [col (entry-col entry)] - [top-line (entry-top-line entry)] - [new-str (lns->str lns new-row)] - [new-len (string-length new-str)] - [new-row-offset (col->line-offset ee new-col)] - [new-row-pos (make-pos new-row new-row-offset)] - [new-bot-line (calc-bot-line-displayed entry new-row-pos)]) - (cond - ; case 1: destination on screen, no scrolling necessary - ; ------------------ - ; | (define fact | <--top-line - ; | (lambda (n) | <--new-row - ; | (if (zero? n)| <--point - ; | 1 | - ; | (* n (fac| - ; |t (sub1 n)))))) | <--bot-line - ; | | - ; ------------------ - [(pos>=? new-row-pos (entry-top-line entry)) - (move-cursor-up - (screen-lines-between ee entry - new-row new-row-offset - (entry-row entry) (col->line-offset ee (entry-col entry)))) - (let ([screen-col (col->screen-col ee col)] - [new-screen-col (col->screen-col ee new-col)]) - (cond - [(fx> new-screen-col screen-col) - (move-cursor-right (fx- new-screen-col screen-col))] - [(fx< new-screen-col screen-col) - (move-cursor-left (fx- screen-col new-screen-col))])) - (entry-row-set! entry new-row) - (entry-col-set! entry new-col)] - - ; case 2: a portion of the old screen overlaps the new screen. - ; we will scroll down and keep the overlap instead of - ; redrawing - ; + = new screen border - ; - = old-screen border - ; ++++++++++++++++++ - ; | (define f | <--new-row 0 }extra-top- - ; | (lambda (n) | }lines - ; ------------------ - ; | (if (zero? n)| <--top-line (2 . 0) - ; | 1 | <--point (row . col) - ; | (* n | <--new-bot-line (4 . 0) - ; ++++++++++++++++++ - ; | (f | <--bot-line (5 . 0) - ; | (1- | - ; ------------------ - ; n)))))) - [(pos>? new-bot-line (entry-top-line entry)) - ; move cursor to physical column 0 of top screen line - (move-cursor-up - (screen-lines-between ee entry - (pos-row top-line) (pos-col top-line) - row (col->line-offset ee col))) - (carriage-return) - (let ([extra-top-lines - (screen-lines-between ee entry - new-row new-row-offset - (pos-row top-line) (pos-col top-line))]) - ; reverse scroll to open up space at the top - ; if we're not actually at the top of the physical display, e.g., - ; if we only partially displayed the entry after an error or tab-tab, - ; we hope that this goes up a line and clears to end of line. if - ; this ever gives us problems, we'll have avoid getting into this - ; case when less than a screenful of lines has been displayed. - (scroll-reverse extra-top-lines) - ; display the extra lines - (let ([r (pos-row top-line)] [off (fx- (pos-col top-line) 1)]) - (if (fx>= off 0) - (display-partial-entry ee entry new-row new-row-offset r off) - (display-partial-entry ee entry new-row new-row-offset - (fx- r 1) (fx- (lns->nsr lns (fx- r 1)) 1)))) - ; move cursor back to top - (move-cursor-up (fx- extra-top-lines 1))) - (move-cursor-right (col->screen-col ee new-col)) - (entry-col-set! entry new-col) - (entry-row-set! entry new-row) - (entry-top-line-set! entry new-row-pos) - (when (posscreen-col ee new-col)) - (entry-col-set! entry new-col) - (entry-row-set! entry new-row) - (entry-top-line-set! entry new-row-pos) - (entry-bot-line-set! entry new-bot-line)]))) - - (define (goto-forward ee entry new-row new-col) - (assert* (fx< new-row (length (entry-lns entry))) - (fx>= new-col 0) - (fx<= new-col (string-length (lns->str (entry-lns entry) new-row)))) - (let* ([lns (entry-lns entry)] - [row (entry-row entry)] - [col (entry-col entry)] - [bot-line (entry-bot-line entry)] - [new-str (lns->str lns new-row)] - [new-len (string-length new-str)] - [new-row-offset (col->line-offset ee new-col)] - [new-row-pos (make-pos new-row new-row-offset)] - [new-top-line (calc-top-line-displayed entry new-row-pos)]) - (cond - ; case 1: destination on screen, no scrolling necessary - ; ------------------ - ; | (define fact | <--top-line - ; | (lambda (n) | <--point - ; | (if (zero? n)| <--new-row - ; | 1 | - ; | (* n (fac| - ; |t (sub1 n)))))) | <--bot-line - ; | | - ; ------------------ - [(pos<=? new-row-pos bot-line) - (move-cursor-down - (screen-lines-between ee entry - row (col->line-offset ee col) - new-row new-row-offset)) - (let ([screen-col (col->screen-col ee col)] - [new-screen-col (col->screen-col ee new-col)]) - (cond - [(fx> new-screen-col screen-col) - (move-cursor-right (fx- new-screen-col screen-col))] - [(fx< new-screen-col screen-col) - (move-cursor-left (fx- screen-col new-screen-col))])) - (entry-row-set! entry new-row) - (entry-col-set! entry new-col)] - - ; case 2: a portion of the old screen overlaps the new screen. - ; we will scroll up and keep the overlap - ; - ; + = new screen border - ; - = old-screen border - ; ------------------ - ; | (define f | <--top-line (0 . 0) - ; | (lambda (n) | - ; ++++++++++++++++++ - ; | (if (zero? n)| <--new-top-line } scrn- - ; | 1 | <--point (row . col) } draw- - ; | (* n | <--bot-line (4 . 0) } lines - ; ------------------ - ; | (f | - ; | (1- | <--new-row 6 - ; ++++++++++++++++++ - ; n)))))) - [(pos>=? bot-line new-top-line) - ; move cursor to physical col 0 of first line after old bot-line - (move-cursor-down - (screen-lines-between ee entry - row (col->line-offset ee col) - (pos-row bot-line) (pos-col bot-line))) - (carriage-return) - (line-feed) - (let ([r (pos-row bot-line)] [off (fx+ (pos-col bot-line) 1)]) - (if (fx< off (lns->nsr lns r)) - (display-partial-entry ee entry r off - new-row new-row-offset) - (display-partial-entry ee entry (fx+ r 1) 0 - new-row new-row-offset))) - (move-cursor-right (col->screen-col ee new-col)) - (entry-col-set! entry new-col) - (entry-row-set! entry new-row) - (when (pos>? new-top-line (entry-top-line entry)) - (entry-top-line-set! entry new-top-line)) - (entry-bot-line-set! entry new-row-pos)] - - ; case 3: no overlap between old screen area and new screen - ; area. we will redraw the entire screen - ; + = new screen border - ; - = old-screen border - ; ++++++++++++++++++ - ; | (define f | <--top-line (0 . 0) - ; | (lambda (n) | - ; | (if (zero? n)| <--bot-line (2 . 0) - ; ++++++++++++++++++ - ; ------------------ - ; | 1 | <--new-top-line - ; | (* n | - ; | (f | <--new-row, new-row-offset - ; ------------------ - ; (1- - ; n)))))) - [else - (clear-screen) - (display-partial-entry ee entry - (pos-row new-top-line) (pos-col new-top-line) - new-row new-row-offset) - (move-cursor-right (col->screen-col ee new-col)) - (entry-col-set! entry new-col) - (entry-row-set! entry new-row) - (entry-top-line-set! entry new-top-line) - (entry-bot-line-set! entry new-row-pos)]))) - - (define (goto ee entry p) - (let ([new-row (pos-row p)] [new-col (pos-col p)]) - (assert* (fx< new-row (length (entry-lns entry))) - (fx<= new-col (string-length (lns->str (entry-lns entry) new-row)))) - (if (or (fx< new-row (entry-row entry)) - (and (fx= new-row (entry-row entry)) - (fx< new-col (entry-col entry)))) - (goto-backward ee entry new-row new-col) - (goto-forward ee entry new-row new-col)))) - - (defopt (move-up ee entry [n 1]) - (assert* (fx>= (fx- (entry-row entry) n) 0)) - (let ([new-row (fx- (entry-row entry) n)]) - (goto-backward ee entry new-row - (fxmin (entry-col entry) - (string-length (lns->str (entry-lns entry) new-row)))))) - - (defopt (move-down ee entry [n 1]) - (assert* (fx< (fx+ (entry-row entry) n) (length (entry-lns entry)))) - (let ([new-row (fx+ (entry-row entry) n)]) - (goto-forward ee entry new-row - (fxmin (entry-col entry) - (string-length (lns->str (entry-lns entry) new-row)))))) - - (defopt (move-left ee entry [n 1]) - (let ([new-col (fx- (entry-col entry) n)]) - (assert* (fx>= new-col 0)) - (goto-backward ee entry (entry-row entry) new-col))) - - (defopt (move-right ee entry [n 1]) - (let ([new-col (fx+ (entry-col entry) n)]) - (assert* (fx<= new-col (string-length (lns->str (entry-lns entry) (entry-row entry))))) - (goto-forward ee entry (entry-row entry) new-col))) - - (define (page-down ee entry) - (let* ([last-row (fx- (length (entry-lns entry)) 1)] - [row (entry-row entry)] - [col (entry-col entry)] - [point-line-offset (col->line-offset ee col)] - [top-line (entry-top-line entry)] - [bot-line (entry-bot-line entry)] - [n (screen-lines-between ee entry - (pos-row top-line) (pos-col top-line) - (pos-row bot-line) (pos-col bot-line))]) - (let f ([r (fxmin (fx+ row n) last-row)]) - (if (fx= r row) - (unless (fx= r last-row) - (goto-forward ee entry (fx+ r 1) - (fxmin col (string-length (lns->str (entry-lns entry) (fx+ r 1)))))) - (let ([c (fxmin col (string-length (lns->str (entry-lns entry) r)))]) - (if (<= (screen-lines-between ee entry - row point-line-offset - r (col->line-offset ee c)) - n) - (goto-forward ee entry r c) - (f (fx- r 1)))))))) - - (define (page-up ee entry) - (let* ([row (entry-row entry)] - [col (entry-col entry)] - [point-line-offset (col->line-offset ee col)] - [top-line (entry-top-line entry)] - [bot-line (entry-bot-line entry)] - [n (screen-lines-between ee entry - (pos-row top-line) (pos-col top-line) - (pos-row bot-line) (pos-col bot-line))]) - (let f ([r (max (fx- row n) 0)]) - (if (fx= r row) - (unless (fx= r 0) - (goto-backward ee entry (fx- r 1) - (fxmin col (string-length (lns->str (entry-lns entry) (fx- r 1)))))) - (let ([c (fxmin col (string-length (lns->str (entry-lns entry) r)))]) - (if (<= (screen-lines-between ee entry - r (col->line-offset ee c) - row point-line-offset) - n) - (goto-backward ee entry r c) - (f (fx+ r 1)))))))) - - (define (move-eol ee entry) - (move-right ee entry - (fx- (string-length (lns->str (entry-lns entry) (entry-row entry))) - (entry-col entry)))) - - (define (move-bol ee entry) - (move-left ee entry (entry-col entry))) - - (define (move-eoe ee entry) - (let ([lns (entry-lns entry)]) - (let ([r (fx- (length lns) 1)]) - (goto-forward ee entry r (string-length (lns->str lns r)))))) - - (define (move-to-col-pos ee entry new-col) - (let ([col (entry-col entry)]) - (if (fx< new-col col) - (move-left ee entry (fx- col new-col)) - (move-right ee entry (fx- new-col col))))) - - (define (adjust-mark/delete ee entry r1 c1 r2 c2) - (let ([mark (entry-mark entry)]) - (when mark - (let ([mrow (pos-row mark)] [mcol (pos-col mark)]) - (unless (or (fx< mrow r1) (and (fx= mrow r1) (fx< mcol c1))) - (entry-mark-set! entry - (and (not (or (fx< mrow r2) (and (fx= mrow r2) (fx< mcol c2)))) - (make-pos - (fx- mrow (fx- r2 r1)) - (if (fx= mrow r2) (fx+ c1 (fx- mcol c2)) mcol))))))))) - - (define (adjust-mark/insert ee entry r1 c1 r2 c2) - (let ([mark (entry-mark entry)]) - (when mark - (let ([mrow (pos-row mark)] [mcol (pos-col mark)]) - (unless (or (fx< mrow r1) (and (fx= mrow r1) (fx< mcol c1))) - (entry-mark-set! entry - (make-pos - (fx+ mrow (fx- r2 r1)) - (if (fx= mrow r1) (fx+ c2 (fx- mcol c1)) mcol)))))))) - - (define (delete-forward ee entry r2 c2) - ; deletes from point, aka r1, c1 (inclusive) to r2, c2 (exclusive) - ; and returns the deleted content as a list of strings - (let ([r1 (entry-row entry)] [c1 (entry-col entry)]) - (assert* (or (fx< r1 r2) (and (fx= r1 r2) (fx<= c1 c2)))) - (adjust-mark/delete ee entry r1 c1 r2 c2) - (if (fx= r1 r2) - (let* ([ln (list-ref (entry-lns entry) r1)] - [s (ln-str ln)] - [old-nsr (ln-nsr ln)]) - (ln-str-set! ee ln - (string-append - (substring s 0 c1) - (substring s c2 (string-length s)))) - (display-rest/goto ee entry (fx= (ln-nsr ln) old-nsr) #t r1 c1) - (list (substring s c1 c2))) - (let* ([lns (entry-lns entry)] - [ls1 (list-tail lns r1)] - [ls2 (list-tail ls1 (fx- r2 r1))] - [s1 (ln-str (car ls1))] - [s2 (ln-str (car ls2))]) - (ln-str-set! ee (car ls1) - (string-append - (substring s1 0 c1) - (substring s2 c2 (string-length s2)))) - (let ([deleted - (cons (substring s1 c1 (string-length s1)) - (let f ([ls (cdr ls1)]) - (if (eq? ls ls2) - (list (substring s2 0 c2)) - (cons (ln-str (car ls)) (f (cdr ls))))))]) - (set-cdr! ls1 (cdr ls2)) - (display-rest/goto ee entry #f #t r1 c1) - deleted))))) - - (define (delete-char ee entry) - (assert* (not (end-of-line? ee entry))) - (let ([row (entry-row entry)] [col (entry-col entry)]) - (delete-forward ee entry row (fx+ col 1)))) - - (define (delete-to-eol ee entry) - (let ([row (entry-row entry)]) - (delete-forward ee entry row - (string-length (lns->str (entry-lns entry) row))))) - - (define (join-rows ee entry) - (assert* (end-of-line? ee entry) (not (last-line? ee entry))) - (delete-forward ee entry (fx+ (entry-row entry) 1) 0)) - - (define (insert-string-before ee entry new-str) - (let* ([row (entry-row entry)] - [col (entry-col entry)] - [lns (entry-lns entry)] - [ln (list-ref lns row)] - [str (ln-str ln)] - [str-len (string-length str)] - [new-col (fx+ col (string-length new-str))] - [nsr (ln-nsr ln)] - [eoe? (end-of-entry? ee entry)]) - (ln-str-set! ee ln - (string-append - (substring str 0 col) - new-str - (substring str col (string-length str)))) - (let ([just-row? (fx= (ln-nsr ln) nsr)]) - (display-rest/goto ee entry just-row? - ; avoid clear-eol/eos if insertion takes place at end of entry or - ; if rewriting just the current row - (and (not eoe?) (not just-row?)) - row new-col)) - (adjust-mark/insert ee entry row col row new-col))) - - (define (add-char ee entry c) - ; add character after point, then move point forward one character - (assert* (char? c)) - (insert-string-before ee entry (string c))) - - (define (insert-strings-before ee entry strs) - (unless (null? strs) - (if (fx= (length strs) 1) - (insert-string-before ee entry (car strs)) - (let* ([row (entry-row entry)] - [col (entry-col entry)] - [lns (entry-lns entry)] - [ls (list-tail lns row)] - [ln (car ls)] - [point-str (ln-str ln)] - [eoe? (end-of-entry? ee entry)]) - (ln-str-set! ee ln - (string-append (substring point-str 0 col) (car strs))) - (set-cdr! ls - (let f ([str (cadr strs)] [strs (cddr strs)]) - (if (null? strs) - (cons (make-ln ee - (string-append str - (substring point-str col - (string-length point-str)))) - (cdr ls)) - (cons (make-ln ee str) - (f (car strs) (cdr strs)))))) - (let* ([n (fx- (length strs) 1)] - [new-row (fx+ row n)] - [new-col (string-length (list-ref strs n))]) - (display-rest/goto ee entry #f (not eoe?) new-row new-col) - (adjust-mark/insert ee entry row col new-row new-col)))))) - - (define (first-line? ee entry) (fxzero? (entry-row entry))) - - (define (last-line? ee entry) - (fx= (entry-row entry) (fx1- (length (entry-lns entry))))) - - (define (last-line-displayed? ee entry) - (pos=? (make-pos (entry-row entry) (col->line-offset ee (entry-col entry))) - (entry-bot-line entry))) - - (define (visible? ee entry row col) - (let ([line (make-pos row (col->line-offset ee col))]) - (and (pos<=? (entry-top-line entry) line) - (pos<=? line (entry-bot-line entry))))) - - (define (end-of-line? ee entry) - (fx= (entry-col entry) - (string-length (lns->str (entry-lns entry) (entry-row entry))))) - - (define (end-of-entry? ee entry) - (and (fx= (entry-row entry) (fx- (length (entry-lns entry)) 1)) - (end-of-line? ee entry))) - - (define (beginning-of-line? ee entry) (fx= (entry-col entry) 0)) - - ; returns #t iff only spaces and newlines are left after point - (define (only-whitespace-left? ee entry) - (let f ([ls (list-tail (entry-lns entry) (entry-row entry))] - [col (entry-col entry)]) - (or (null? ls) - (let* ([s (ln-str (car ls))] [n (string-length s)]) - (let g ([col col]) - (if (fx= col n) - (f (cdr ls) 0) - (and (char=? (string-ref s col) #\space) - (g (fx+ col 1))))))))) - - (define (handle-winch ee entry) - (screen-resize!) - (unless (and (fx= (screen-rows) (entry-screen-rows entry)) - (fx= (screen-cols) (entry-screen-cols entry))) - (clear-entry ee entry) - (redisplay ee entry))) - - (module (redisplay) - (define (set-screen-size! ee entry) - (screen-resize!) - (unless (and (fx= (entry-screen-cols entry) (screen-cols)) - (fx= (entry-screen-rows entry) (screen-rows))) - (for-each - (lambda (ln) (ln-nsr-set! ln (str->nsr ee (ln-str ln)))) - (entry-lns entry)) - (entry-screen-cols-set! entry (screen-cols)) - (entry-screen-rows-set! entry (screen-rows)))) - - (defopt (redisplay ee entry [nrows #f]) - (set-screen-size! ee entry) - (let* ([nrows (or nrows (screen-rows))] ; want new screen-rows - [row (entry-row entry)] - [col (entry-col entry)] - [point-line (make-pos row (col->line-offset ee col))]) - (entry-bot-line-set! entry - (calc-bot-line-displayed entry (entry-top-line entry) nrows)) - (when (pos>? point-line (entry-bot-line entry)) - (entry-bot-line-set! entry point-line)) - (entry-top-line-set! entry - (calc-top-line-displayed entry (entry-bot-line entry) nrows)) - (when (posscreen-col ee col)))))) - - (define (flash ee entry mpos) - (let ([point-pos (entry-point entry)]) - (cond - [(visible? ee entry (pos-row mpos) (pos-col mpos)) - (goto ee entry mpos) - (ee-flush) - (wait (ee-paren-flash-delay)) - (goto ee entry point-pos)] - [(posline-offset ee (pos-col point-pos)))] - [ncols (col->screen-col ee (pos-col point-pos))]) - (move-cursor-left ncols) - (move-cursor-up nlines) - (ee-flush) - (wait (ee-paren-flash-delay)) - (move-cursor-down nlines) - (move-cursor-right ncols))] - [else - (let ([nlines - (screen-lines-between ee entry - (pos-row point-pos) - (col->line-offset ee (pos-col point-pos)) - (pos-row (entry-bot-line entry)) - (pos-col (entry-top-line entry)))] - [ncols (col->screen-col ee (pos-col point-pos))]) - (move-cursor-left ncols) - (move-cursor-down nlines) - (ee-flush) - (wait (ee-paren-flash-delay)) - (move-cursor-up nlines) - (move-cursor-right ncols))]))) - - (define (correct&flash-matching-delimiter ee entry) - (define (expected left) (if (eqv? left lbchar) rbchar rpchar)) - (move-left ee entry 1) ; move over delim - (let ([lns (entry-lns entry)]) - (let* ([row (entry-row entry)] - [col (entry-col entry)] - [str (lns->str lns row)] - [c (string-ref str col)]) - (if (or (char=? c lpchar) (char=? c lbchar)) - ; don't correct close delimiter when inserting open delimiter - ; since doing so often leads to surprising results - (when (ee-flash-parens) - (cond - [(find-matching-delim-forward ee entry row col #f) => - (lambda (mpos) (flash ee entry mpos))])) - (cond - [(find-matching-delim-backward ee entry row col - (ee-auto-paren-balance)) => - (lambda (mpos) - (let ([cexp (expected - (string-ref - (lns->str lns (pos-row mpos)) - (pos-col mpos)))]) - (unless (eqv? c cexp) - (string-set! str col cexp) - (ee-write-char cexp) - (move-cursor-left 1))) - (when (ee-flash-parens) (flash ee entry mpos)))])))) - (move-right ee entry 1)) - - (define (find-matching-delimiter ee entry) - (let ([row (entry-row entry)] - [col (entry-col entry)] - [str (lns->str (entry-lns entry) (entry-row entry))]) - (and (fx< col (string-length str)) - (let ([c (string-ref str col)]) - (if (or (char=? c lpchar) (char=? c lbchar)) - (find-matching-delim-forward ee entry row col #f) - (and (or (char=? c rpchar) (char=? c rbchar)) - (find-matching-delim-backward ee entry row col #f))))))) - - (define (find-matching-delim-backward ee entry row col lax?) - (let ([lns (entry-lns entry)]) - ; 1. create string representing current entry through row, col - ; 2. search forward, stacking left/right delimiters and their indices - ; 3. if matching delimiter found, convert string index to pos - (let* ([s (let ([op (open-output-string)]) - (let loop ([i 0] [sep ""]) - (let ([str (lns->str lns i)]) - (if (= i row) - (fprintf op "~a~a" sep (substring str 0 (fx+ col 1))) - (begin - (fprintf op "~a~a" sep str) - (loop (fx+ i 1) "\n"))))) - (get-output-string op))] - [ip (open-input-string s)]) - (let loop ([stack '()]) - (on-error (loop '()) - (let-values ([(type value start end) (read-token ip)]) - (case type - [(atomic box dot insert mark quote) (loop stack)] - [(lbrack record-brack) - (loop (cons (cons 'rbrack end) stack))] - [(lparen vfxnparen vfxparen vnparen vparen vu8nparen vu8paren) - (loop (cons (cons 'rparen end) stack))] - [(rbrack rparen) - (if (= end (string-length s)) - (and (not (null? stack)) - (or lax? (eq? (caar stack) type)) - (index->pos s (fx- (cdar stack) 1) 0 0)) - (if (and (not (null? stack)) (eq? (caar stack) type)) - (loop (cdr stack)) - (loop '())))] - [(eof fasl) #f] - [else - (warningf 'expeditor "unexpected token type ~s from read-token" type) - #f]))))))) - - (define (find-matching-delim-forward ee entry row col lax?) - (let ([lns (entry-lns entry)]) - ; should be sitting on left paren or bracket - (assert* (or (char=? (lns->char lns row col) lpchar) - (char=? (lns->char lns row col) lbchar))) - ; 1. create string representing current entry starting at col, row - ; 2. search forward until matching delimiter, eof, or error - ; 3. if matching delimiter found, convert string index to pos - (let* ([s (let ([op (open-output-string)] [l-lns (length lns)]) - (let ([s (lns->str lns row)]) - (display (substring s col (string-length s)) op)) - (let loop ([i (fx+ row 1)]) - (unless (fx= i l-lns) - (fprintf op "\n~a" (lns->str lns i)) - (loop (fx+ i 1)))) - (get-output-string op))] - [ip (open-input-string s)]) - (on-error #f - (let loop ([stack '()]) - (let-values ([(type value start end) (read-token ip)]) - (case type - [(atomic box dot insert mark quote) (loop stack)] - [(lbrack record-brack) - (loop (cons 'rbrack stack))] - [(lparen vfxnparen vfxparen vnparen vparen vu8nparen vu8paren) - (loop (cons 'rparen stack))] - [(rbrack rparen) - (if (fx= (length stack) 1) - (and (or lax? (eq? (car stack) type)) - (index->pos s start row col)) - (and (eq? (car stack) type) (loop (cdr stack))))] - [(eof fasl) #f] - [else - (warningf 'expeditor "unexpected token type ~s from read-token" type) - #f]))))))) - - (define (find-next-sexp-backward ee entry row col) - (let* ([lns (entry-lns entry)] - [s (let ([op (open-output-string)]) - (let loop ([i 0] [sep ""]) - (let ([str (lns->str lns i)]) - (if (= i row) - (fprintf op "~a~a" sep (substring str 0 col)) - (begin - (fprintf op "~a~a" sep str) - (loop (fx+ i 1) "\n"))))) - (get-output-string op))] - [ip (open-input-string s)]) - (on-error #f - (let loop ([stack '()] [last-start 0]) - (let-values ([(type value start end) (read-token ip)]) - (case type - [(atomic dot insert mark) - (if (and (not (null? stack)) (eq? (caar stack) 'qubx)) - (loop (cdr stack) (cdar stack)) - (loop stack start))] - [(box quote) - (if (and (not (null? stack)) (eq? (caar stack) 'qubx)) - (loop stack #f) - (loop (cons (cons 'qubx start) stack) #f))] - [(eof) (and last-start (index->pos s last-start 0 0))] - [(lbrack record-brack) - (if (and (not (null? stack)) (eq? (caar stack) 'qubx)) - (loop (cons (cons 'rbrack (cdar stack)) (cdr stack)) #f) - (loop (cons (cons 'rbrack start) stack) #f))] - [(lparen vfxnparen vfxparen vnparen vparen vu8nparen vu8paren) - (if (and (not (null? stack)) (eq? (caar stack) 'qubx)) - (loop (cons (cons 'rparen (cdar stack)) (cdr stack)) #f) - (loop (cons (cons 'rparen start) stack) #f))] - [(rbrack rparen) - (if (and (not (null? stack)) (eq? (caar stack) type)) - (loop (cdr stack) (cdar stack)) - (loop '() #f))] - [else - (warningf 'expeditor "unexpected token type ~s from read-token" type) - #f])))))) - - (define (find-next-sexp-forward ee entry row col ignore-whitespace?) - ; ordinarily stops at first s-expression if it follows whitespace (or - ; comments), but always moves to second if ignore-whitespace? is true - (let* ([lns (entry-lns entry)] - [s (let ([op (open-output-string)] [l-lns (length lns)]) - (let ([s (lns->str lns row)]) - (display (substring s col (string-length s)) op)) - (let loop ([i (fx+ row 1)]) - (unless (fx= i l-lns) - (fprintf op "\n~a" (lns->str lns i)) - (loop (fx+ i 1)))) - (get-output-string op))] - [ip (open-input-string s)]) - (define (skip start) - (index->pos s - (on-error start - (let-values ([(type value start end) (read-token ip)]) - start)) - row col)) - (on-error #f - (let loop ([stack '()] [first? #t] [ignore? #f]) - (let-values ([(type value start end) (read-token ip)]) - (if (and first? (not ignore-whitespace?) (fx> start 0)) - (and (not ignore?) (index->pos s start row col)) - (case type - [(atomic dot insert mark) - (if (null? stack) - (and (not ignore?) (skip start)) - (loop stack #f ignore?))] - [(box) (loop stack #f ignore?)] - [(quote) - (when (and ignore-whitespace? - (eq? value 'datum-comment) - (null? stack)) - (loop '() #f #t)) - (loop stack #f ignore?)] - [(eof fasl) #f] - [(lbrack record-brack) (loop (cons 'rbrack stack) #f ignore?)] - [(lparen vfxnparen vfxparen vnparen vparen vu8nparen vu8paren) - (loop (cons 'rparen stack) #f ignore?)] - [(rbrack rparen) - (and (not (null? stack)) - (eq? (car stack) type) - (let ([stack (cdr stack)]) - (if (null? stack) - (and (not ignore?) (skip start)) - (loop stack #f ignore?))))] - [else - (warningf 'expeditor "unexpected token type ~s from read-token" type) - #f]))))))) - - (module (find-next-word find-previous-word) - (define separator? - (lambda (c) - (memq c '(#\space #\; #\( #\) #\[ #\] #\" #\' #\`)))) - - (define (find-next-word ee entry row col) - ; always returns a position - (let ([lns (entry-lns entry)]) - ; skip past separators - (let loop ([row row] [col col]) - (cond - [(fx= col (string-length (lns->str lns row))) - (if (fx= row (fx1- (length lns))) - (make-pos row col) - (loop (fx1+ row) 0))] - [(separator? (lns->char lns row col)) - (loop row (fx1+ col))] - ; now we are past initial separators, find next separator - [else - (let loop ([col col]) - (cond - [(or (fx= col (string-length (lns->str lns row))) - (separator? (lns->char lns row col))) - (make-pos row col)] - [else (loop (fx1+ col))]))])))) - - (define (find-previous-word ee entry row col) - ; always returns a position - (let ([lns (entry-lns entry)]) - ; skip past separators space (starts at char left of current) - (let loop ([row row] [col col]) - (cond - [(fx= col 0) - (if (fx= row 0) - (make-pos row col) - (loop - (fx1- row) - (string-length (lns->str lns (fx1- row)))))] - [(separator? (lns->char lns row (fx1- col))) - (loop row (fx1- col))] - ; now we are past initial separators, find next separator - [else - (let loop ([col col]) - (cond - [(or (fx= col 0) - (separator? (lns->char lns row (fx1- col)))) - (make-pos row col)] - [else (loop (fx1- col))]))]))))) - - (module (indent indent-all) - (define (calc-indent ee entry row) - (define (find-unmatched-left-delim row) - (let* ([ln (list-ref (entry-lns entry) row)] - [s (ln-str ln)]) - (ln-str-set! ee ln (string rpchar)) - (let ([pos (find-matching-delim-backward ee entry row 0 #t)]) - (ln-str-set! ee ln s) - pos))) - (let ([lns (entry-lns entry)]) - (cond - [(find-unmatched-left-delim row) => - (lambda (mpos) - (let ([mrow (pos-row mpos)] [mcol (pos-col mpos)]) - (or - ; if some intervening line has same unmatched left - ; delimiter, use its indentation - (let f ([xrow (fx- row 1)]) - (and (not (fx= xrow mrow)) - (cond - [(find-unmatched-left-delim xrow) => - (lambda (xmpos) - (if (pos=? xmpos mpos) - (current-indent lns xrow) - (f (fx- xrow 1))))] - [else (f (fx- xrow 1))]))) - ; otherwise, if left paren is followed by a symbol, - ; indent under second item or use standard indent if - ; second item is too far out or not present - (let ([ip (open-input-string - (let ([s (lns->str lns mrow)]) - (substring s mcol (string-length s))))]) - (on-error #f - (and (char=? (read-char ip) lpchar) - (let-values ([(t1 v1 s1 e1) (read-token ip)]) - (and (and (eq? t1 'atomic) (symbol? v1)) - (let-values ([(t2 v2 s2 e2) (read-token ip)]) - (if (and (not (eq? t2 'eof)) - (fx< s2 6) - ; use standard indent for let and rec - (not (memq v1 '(let rec)))) - (fx+ mcol s2) - (fx+ mcol (ee-standard-indent))))))))) - ; otherwise, indent one space in. this handles, among - ; other things, bracketed let bindings and cond clauses. - (fx+ mcol 1))))] - [else 0]))) - - (define current-indent - (lambda (lns row) - (let* ([s (lns->str lns row)] - [n (string-length s)]) - (let f ([i 0]) - (if (and (fx< i n) (char=? (string-ref s i) #\space)) - (f (fx+ i 1)) - i))))) - - (define (indent-row! ee entry row n) - (cond - [(fx< n 0) - (adjust-mark/delete ee entry row 0 row (fx- n)) - (let ([lns (entry-lns entry)]) - (lns->str! ee lns row - (let ([s (lns->str lns row)]) - (substring s (fx- n) (string-length s)))))] - [(fx> n 0) - (adjust-mark/insert ee entry row 0 row n) - (let ([lns (entry-lns entry)]) - (lns->str! ee lns row - (string-append - (make-string n #\space) - (lns->str lns row))))])) - - (define (indent ee entry) - (let* ([row (entry-row entry)] - [lns (entry-lns entry)] - [n (fx- (calc-indent ee entry row) (current-indent lns row))]) - (unless (fx= n 0) - (let* ([ln (list-ref lns row)] - [nsr (ln-nsr ln)] - [eoe? (end-of-entry? ee entry)]) - (indent-row! ee entry row n) - (move-bol ee entry) - (let ([just-row? (fx= (ln-nsr ln) nsr)]) - (display-rest/goto ee entry just-row? - ; avoid clear-eol/eos if inserting and either at end of entry or - ; rewriting just the current row - (or (fx< n 0) (and (not eoe?) (not just-row?))) - row (fxmax (fx+ (entry-col entry) n) 0))))))) - - (define (indent-all ee entry) - (let* ([lns (entry-lns entry)] - [row (entry-row entry)] - [col (entry-col entry)] - [top-line (entry-top-line entry)] - [point-ln (list-ref lns row)] - [point-strlen (string-length (ln-str point-ln))] - [lines-to-top ; compute before we muck with indentation - (screen-lines-between ee entry - (pos-row top-line) (pos-col top-line) - row (col->line-offset ee col))]) - (let loop ([ls lns] [i 0] [firstmod (length lns)] [lastmod -1]) - (if (null? ls) - (unless (and (fx< lastmod (pos-row top-line)) - (fx> firstmod (pos-row (entry-bot-line entry)))) - ; move to first physical column of first displayed line - (move-cursor-up lines-to-top) - (carriage-return) - (clear-eos) - (entry-col-set! entry - (fxmax 0 - (fx+ col - (fx- (string-length (ln-str point-ln)) - point-strlen)))) - (redisplay ee entry)) - (let ([n (fx- (calc-indent ee entry i) (current-indent lns i))]) - (if (fx= n 0) - (loop (cdr ls) (fx+ i 1) firstmod lastmod) - (begin - (indent-row! ee entry i n) - (loop (cdr ls) (fx+ i 1) - (fxmin i firstmod) - (fxmax i lastmod))))))))) - ) - - (define (id-completions ee entry) - (define (idstringsymbol (string-append prefix s1))] - [x2 (string->symbol (string-append prefix s2))]) - ; prefer common - (let ([m1 (memq x1 common)] [m2 (memq x2 common)]) - (if m1 - (or (not m2) (< (length m2) (length m1))) - (and (not m2) - ; prefer user-defined - (let ([u1 (not (memq x1 scheme-syms))] - [u2 (not (memq x2 scheme-syms))]) - (if u1 - (or (not u2) (string= n2 n1) - (string=? (substring str2 0 n1) str1) - (substring str2 n1 n2)))) - (define (fn-completions prefix) - (values prefix - (sort string - (lambda (suffix) - (cons (if (file-directory? (string-append prefix suffix)) - (string-append suffix (string (directory-separator))) - suffix) - suffix*))] - [else suffix*]))) - '() - (on-error '() - (directory-list - (let ([dir (path-parent prefix)]) - (if (string=? dir "") "." dir)))))))) - (let loop ([c 0]) - (if (fx>= c (entry-col entry)) - (values #f '()) - (let ([s (let ([s (lns->str (entry-lns entry) (entry-row entry))]) - (substring s c (string-length s)))]) - ((on-error - (lambda () - (if (and (fx> (string-length s) 0) (char=? (string-ref s 0) #\")) - (fn-completions (substring s 1 (string-length s))) - (loop (fx+ c 1)))) - (let-values ([(type value start end) (read-token (open-input-string s))]) - (lambda () - (cond - [(and (fx= (fx+ c end) (entry-col entry)) - (eq? type 'atomic) - (symbol? value)) - (let ([prefix (symbol->string value)]) - (values prefix - (sort (idstringstring x)) => - (lambda (suffix) (cons suffix suffix*))] - [else suffix*])) - '() (environment-symbols (interaction-environment))))))] - [(and (fx= (fx+ c end -1) (entry-col entry)) - (eq? type 'atomic) - (string? value)) - (fn-completions value)] - [else (loop (fx+ c end))]))))))))) - - (define (should-auto-indent? ee) - (and (ee-auto-indent) - ; don't autoindent if the characters are coming so fast that we're - ; probably dealing with paste input - (> (- (real-time) (car (eestate-rt-last-op ee))) 50))) -) - -(module (ee-read) - (define (accept ee entry kf) - (let* ([str (entry->string entry)] - [sip (open-input-string str)]) - (define (fail c) - (define (report sop) - (cond - [(and (message-condition? c) - (irritants-condition? c) - (equal? (condition-message c) "~? at char ~a of ~s") - (let ([irritants (condition-irritants c)]) - (and (list? irritants) - (fx= (length irritants) 4) - irritants))) => - (lambda (irritants) - (apply - (lambda (?msg ?args fp ip) - (fprintf sop "read: ~?" ?msg ?args) - (let ([pos (index->pos str fp 0 0)]) - (entry-row-set! entry (pos-row pos)) - (entry-col-set! entry (pos-col pos)))) - irritants))] - [else (display-condition c sop)])) - ; clear entry before report has a chance to muck with point position - (clear-entry ee entry) - (ee-display-string (make-string (screen-cols) #\-)) - (carriage-return) - (line-feed) - (let* ([s (let ([sop (open-output-string)]) - (report sop) - (get-output-string sop))] - [n (string-length s)]) - (let loop ([i 0] [msg-lines 0]) - (if (= i n) - (begin - (unless (fx< (screen-rows) 3) - (ee-display-string (make-string (screen-cols) #\-)) - (carriage-return) - (line-feed)) - (redisplay ee entry (max (fx- (screen-rows) msg-lines 2) 1))) - (let ([m (min (fx+ i (screen-cols)) n)]) - (ee-display-string (substring s i m)) - (when (fx< (screen-rows) 2) (wait 2000)) - (carriage-return) - (line-feed) - (loop m (fx+ msg-lines 1)))))) - (kf)) - (define (succeed result) - (move-eoe ee entry) - (no-raw-mode) - (ee-write-char #\newline) - (ee-flush) - (update-history! ee entry) - ; skip close delimiters, whitespace, and comments, then - ; save remainder of entry, if any, as histnow - (eestate-histnow-set! ee - (substring str - (let skip ([fp (file-position sip)]) - (on-error fp - (let-values ([(type value start end) (read-token sip)]) - (case type - [(rparen rbrack) (skip end)] - [else start])))) - (string-length str))) - (eestate-last-op-set! ee #f) - ; inform encapsulated transcript port(s) if any - (let loop ([op (console-output-port)]) - (when ($xscript-port? op) - (let-values ([(ip op xp) ($constituent-ports op)]) - (unless (port-closed? xp) (echo-entry ee entry xp)) - (loop op)))) - result) - ((guard (c [#t (lambda () (fail c))]) - (let ([x (read sip)]) - (lambda () (succeed x))))))) - - (define (dispatch ee entry table) - (if (ee-winch?) - (begin - (handle-winch ee entry) - (dispatch ee entry table)) - (let ([c (ee-read-char)]) - (let ([x (if (eof-object? c) - (lambda (ee entry c) #f) - (hashtable-ref table c ee-insert-self))]) - (cond - [(procedure? x) - (let ([n (eestate-repeat-count ee)]) - (eestate-repeat-count-set! ee 1) - (if (= n 0) - (dispatch ee entry base-dispatch-table) - (let loop ([n n] [entry entry]) - (cond - [(x ee entry c) => - (lambda (entry) - (if (> n 1) - (loop (- n 1) entry) - (begin - (eestate-rt-last-op-set! ee - (cons (cdr (eestate-rt-last-op ee)) - (real-time))) - (eestate-last-op-set! ee x) - (dispatch ee entry base-dispatch-table))))] - [else - (accept ee entry - (lambda () - (dispatch ee entry base-dispatch-table)))]))))] - [(dispatch-table? x) (dispatch ee entry x)] - [else - (eestate-repeat-count-set! ee 1) - (eestate-last-op-set! ee #f) - (beep "unbound key") - (dispatch ee entry base-dispatch-table)]))))) - - (define (ee-read ee) - (screen-resize!) - (let ([entry (let ([s (eestate-histnow ee)]) - ; set to "" so that entry will appear modified if nonempty, - ; i.e., if a partial entry is left over from last read - (eestate-histnow-set! ee "") - (string->entry ee s))]) - (raw-mode) - (carriage-return) - (redisplay ee entry) - (move-eol ee entry) - (guard (c [#t (carriage-return) - (line-feed) - (clear-eos) - (ee-flush) - (no-raw-mode) - (ee-display-string - (call-with-string-output-port - (lambda (p) - (display-condition c p)))) - (ee-write-char #\newline) - (update-history! ee entry) - (void)]) - (dispatch ee entry base-dispatch-table))))) - -(define (ee-prompt-and-read ee n) - (unless (and (integer? n) (>= n 0)) - ($oops 'ee-prompt-and-read - "nesting level ~s is not a positive integer" - n)) - (if (and (let f ([ip (console-input-port)]) - (or (eq? ip #%$console-input-port) - (and ($xscript-port? ip) - (let-values ([(ip op xp) ($constituent-ports ip)]) - (f ip))))) - (let f ([op (console-output-port)]) - (or (eq? op #%$console-output-port) - (and ($xscript-port? op) - (let-values ([(ip op xp) ($constituent-ports op)]) - (f op)))))) - (begin - ; fresh-line doesn't take into account output written to the console - ; through some other port or external means, so this might not emit a - ; fresh line when one is needed, but the user can always redisplay - (fresh-line (console-output-port)) - (flush-output-port (console-output-port)) - (eestate-prompt-set! ee - (let ([wps (waiter-prompt-string)]) - (if (string=? wps "") - "" - (string-append - (apply string-append (make-list n wps)) - " ")))) - (ee-read ee)) - (default-prompt-and-read n))) - -;;; history functions - -(module (history-search-bwd history-search-fwd - update-history! history-fast-forward! entry-modified? - ee-save-history ee-load-history) - (define search - (lambda (ee pred? get-bwd set-bwd! get-fwd set-fwd!) - (let loop ([bwd (get-bwd ee)] - [now (eestate-histnow ee)] - [fwd (get-fwd ee)]) - (and (not (null? bwd)) - (let ([s (car bwd)]) - (if (pred? s) - (begin - (set-bwd! ee (cdr bwd)) - (eestate-histnow-set! ee s) - (set-fwd! ee (cons now fwd)) - s) - (loop (cdr bwd) s (cons now fwd)))))))) - - (define history-search-bwd - (lambda (ee pred?) - (search ee pred? eestate-histbwd eestate-histbwd-set! - eestate-histfwd eestate-histfwd-set!))) - - (define history-search-fwd - (lambda (ee pred?) - (search ee pred? eestate-histfwd eestate-histfwd-set! - eestate-histbwd eestate-histbwd-set!))) - - (define history->list - (lambda (ee) - (cdr `(,@(reverse (eestate-histfwd ee)) - ,(eestate-histnow ee) - ,@(eestate-histbwd ee))))) - - (define trim-history - (lambda (ls) - (let ([n (ee-history-limit)]) - (if (> (length ls) n) - (list-head ls n) - ls)))) - - (define update-history! - (lambda (ee entry) - (define (all-whitespace? s) - (let ([n (string-length s)]) - (let f ([i 0]) - (or (fx= i n) - (and (memv (string-ref s i) '(#\space #\newline)) - (f (fx+ i 1))))))) - (let ([s (entry->string entry)] [ls (history->list ee)]) - (eestate-histbwd-set! ee - (if (or (all-whitespace? s) - (and (not (null? ls)) - (equal? s (car ls)))) - ls - (begin - (eestate-histnew-set! ee (fx+ (eestate-histnew ee) 1)) - (trim-history (cons s ls)))))) - (eestate-histnow-set! ee "") - (eestate-histfwd-set! ee '()))) - - (define history-fast-forward! - (lambda (ee) - (eestate-histbwd-set! ee (history->list ee)) - (eestate-histnow-set! ee "") - (eestate-histfwd-set! ee '()))) - - (define (entry-modified? ee entry) - (not (string=? (entry->string entry) (eestate-histnow ee)))) - - (module (ee-save-history ee-load-history) - (define read-history - (lambda (ip) - (on-error #f - (let loop ([ls '()]) - (let ([x (read ip)]) - (if (eof-object? x) - ls - (begin - (unless (string? x) ($oops #f "oops")) - (loop (cons x ls))))))))) - - (define ee-save-history - (lambda (ee filename) - (unless (string? filename) - ($oops 'ee-save "~s is not a string" filename)) - (let* ([iop ($open-file-input/output-port 'expeditor filename - (file-options exclusive no-fail no-truncate) - (buffer-mode block) - (make-transcoder (utf-8-codec)))] - [ls (let ([curls (history->list ee)]) - (cond - [(read-history iop) => - (lambda (savls) - (trim-history - (append - (list-head curls (eestate-histnew ee)) - savls)))] - [else curls]))]) - (truncate-file iop) - (fprintf iop "~ - ;;; This file contains a saved history for the (Petite) Chez Scheme~@ - ;;; expression editor. The history is represented as a sequence of~@ - ;;; strings, each representing a history entry, with the most recent~@ - ;;; entries listed last.~@ - ~@ - ;;; Exit each Scheme session running the expression editor before~@ - ;;; saving changes so they aren't wiped out when the session ends.\n\n") - (for-each (lambda (s) (fprintf iop "~s\n" s)) (reverse ls)) - (close-port iop)))) - - (define ee-load-history - (lambda (ee filename) - (unless (string? filename) - ($oops 'ee-load-history "~s is not a string" filename)) - (let* ([iop ($open-file-input/output-port 'expeditor filename - (file-options exclusive no-fail no-truncate) - (buffer-mode block) - (make-transcoder (utf-8-codec)))] - [ls (read-history iop)]) - (close-port iop) - (unless ls - ($oops 'ee-load-history "missing or malformed history file ~s" - filename)) - (eestate-histnew-set! ee 0) - (eestate-histbwd-set! ee ls) - (eestate-histnow-set! ee "") - (eestate-histfwd-set! ee '()))))) -) - -;;; editing functions - -(module (ee-next-id-completion ee-next-id-completion/indent) - (define complete - (lambda (ee entry suffix*) - (eestate-last-suffix*-set! ee suffix*) - (if (null? suffix*) - (beep "id-completion: no completion found") - (insert-string-before ee entry (car suffix*))))) - - (define next-completion - (lambda (ee entry) - (if (fx<= (length (eestate-last-suffix* ee)) 1) - (beep "id-completion: no completion found") - (let ([suffix (car (eestate-last-suffix* ee))]) - (let ([n (string-length suffix)]) - (move-left ee entry n) - (delete-forward ee entry (entry-row entry) (fx+ (entry-col entry) n))) - (complete ee entry - (append (cdr (eestate-last-suffix* ee)) (list suffix))))))) - - (define ee-next-id-completion - (lambda (ee entry c) - (if (eq? (eestate-last-op ee) ee-next-id-completion) - (next-completion ee entry) - (let-values ([(prefix suffix*) (id-completions ee entry)]) - (if prefix - (complete ee entry suffix*) - (begin - (eestate-last-suffix*-set! ee '()) - (beep "id-completion: no identifier to complete"))))) - entry)) - - (define ee-next-id-completion/indent - (lambda (ee entry c) - (cond - [(and (eq? (eestate-last-op ee) ee-next-id-completion/indent) - (eestate-cc? ee)) - (next-completion ee entry) - entry] - [(and (or (eq? (eestate-last-op ee) ee-insert-self) - (eq? (eestate-last-op ee) ee-next-id-completion/indent)) - (let-values ([(prefix suffix*) (id-completions ee entry)]) - (and prefix suffix*))) => - (lambda (suffix*) - (eestate-cc?-set! ee #t) - (complete ee entry suffix*) - entry)] - [else - (eestate-cc?-set! ee #f) - (eestate-last-suffix*-set! ee '()) - (ee-indent ee entry c)]))) -) - -(module (ee-id-completion ee-id-completion/indent) - (define (display-completions prefix suffix*) - (let* ([s* (map (lambda (suffix) (string-append prefix suffix)) suffix*)] - [width (fx+ (apply fxmax (map string-length s*)) 2)] - [tcols (fxmax 1 (fxquotient (screen-cols) width))] - [trows (fxquotient (length s*) tcols)] - [nlong (fxremainder (length s*) tcols)]) - (define (display-row v last) - (let loop ([j 0]) - (let ([s (vector-ref v j)]) - (if (fx= j last) - (ee-display-string s) - (begin - (ee-display-string (format "~va" width s)) - (loop (fx+ j 1)))))) - (carriage-return) - (line-feed)) - (let ([v (make-vector (if (fx= nlong 0) trows (fx+ trows 1)))]) - (do ([i 0 (fx+ i 1)]) - ((fx= i (vector-length v))) - (vector-set! v i (make-vector tcols #f))) - (let f ([s* s*] [i 0] [j 0] [nlong nlong]) - (unless (null? s*) - (if (fx= i (if (fx> nlong 0) (fx+ trows 1) trows)) - (f s* 0 (fx+ j 1) (fx- nlong 1)) - (begin - (vector-set! (vector-ref v i) j (car s*)) - (f (cdr s*) (fx+ i 1) j nlong))))) - (do ([i 0 (fx+ i 1)]) - ((fx= i trows)) - (display-row (vector-ref v i) (fx- tcols 1))) - (unless (fx= nlong 0) - (display-row (vector-ref v trows) (fx- nlong 1))) - (if (fx= nlong 0) trows (fx+ trows 1))))) - - (define (common-prefix s*) - (let outer ([s1 (car s*)] [s* (cdr s*)]) - (if (null? s*) - s1 - (let ([s2 (car s*)]) - (let ([n1 (string-length s1)] [n2 (string-length s2)]) - (let inner ([i 0]) - (if (or (fx= i n1) - (fx= i n2) - (not (char=? (string-ref s1 i) (string-ref s2 i)))) - (outer (substring s1 0 i) (cdr s*)) - (inner (fx+ i 1))))))))) - - (define ee-id-completion - (lambda (ee entry c) - (let-values ([(prefix suffix*) (id-completions ee entry)]) - (if prefix - (if (not (null? suffix*)) - (if (eq? (eestate-last-op ee) ee-id-completion) - (begin - (clear-entry ee entry) - (ee-display-string (make-string (screen-cols) #\-)) - (carriage-return) - (line-feed) - (let ([nrows (display-completions prefix suffix*)]) - (ee-display-string (make-string (screen-cols) #\-)) - (carriage-return) - (line-feed) - (redisplay ee entry (max (fx- (screen-rows) nrows 1) 1)))) - (insert-string-before ee entry (common-prefix suffix*))) - (beep "id-completion: no completions found")) - (beep "id-completion: no identifier to complete"))) - entry)) - - (define ee-id-completion/indent - (lambda (ee entry c) - (cond - [(and (eq? (eestate-last-op ee) ee-id-completion/indent) - (eestate-cc? ee)) - (let-values ([(prefix suffix*) (id-completions ee entry)]) - (if (not (null? suffix*)) - (begin - (clear-entry ee entry) - (ee-display-string (make-string (screen-cols) #\-)) - (carriage-return) - (line-feed) - (let ([nrows (display-completions prefix suffix*)]) - (ee-display-string (make-string (screen-cols) #\-)) - (carriage-return) - (line-feed) - (redisplay ee entry (max (fx- (screen-rows) nrows 1) 1)))) - (beep "id-completion: no completions found"))) - entry] - [(and (or (eq? (eestate-last-op ee) ee-insert-self) - (eq? (eestate-last-op ee) ee-id-completion/indent)) - (let-values ([(prefix suffix*) (id-completions ee entry)]) - (and prefix suffix*))) => - (lambda (suffix*) - (eestate-cc?-set! ee #t) - (if (not (null? suffix*)) - (insert-string-before ee entry (common-prefix suffix*)) - (beep "id-completion: no completions found")) - entry)] - [else - (eestate-cc?-set! ee #f) - (ee-indent ee entry c)]))) -) - -(define ee-insert-self - (lambda (ee entry c) - (add-char ee entry c) - entry)) - -(define ee-command-repeat - (lambda (ee entry c) - (define (digit-value c) (char- c #\0)) - (eestate-repeat-count-set! ee - (let ([c (ee-peek-char)]) - (if (and (not (eof-object? c)) (char-numeric? c)) - (let loop ([n (digit-value (ee-read-char))]) - (let ([c (ee-peek-char)]) - (if (and (not (eof-object? c)) (char-numeric? c)) - (loop (+ (* n 10) (digit-value (ee-read-char)))) - n))) - (ee-default-repeat)))) - entry)) - -(module (ee-history-bwd ee-history-fwd - ee-history-bwd-prefix ee-history-fwd-prefix - ee-history-bwd-contains ee-history-fwd-contains) - (define contains? - (lambda (key str) - (let ([key-len (string-length key)] - [str-len (string-length str)]) - (let loop ([idx 0]) - (cond - [(fx> key-len (fx- str-len idx)) #f] - [(string=? key (substring str idx (fx+ idx key-len))) #t] - [else (loop (add1 idx))]))))) - - (define prefix? - (lambda (key str) - (let ([nkey (string-length key)] [nstr (string-length str)]) - ; if key doesn't start with space, skip leading spaces in str - (let ([i (if (or (fx= nkey 0) (char=? (string-ref key 0) #\space)) - 0 - (let f ([i 0]) - (if (or (fx= i nstr) (not (char=? (string-ref str i) #\space))) - i - (f (fx+ i 1)))))]) - (let ([n (fx+ nkey i)]) - (and (fx<= n nstr) - (string=? key (substring str i n)))))))) - - (define new-entry - (lambda (ee entry s) - (clear-entry ee entry) - (let ([entry (string->entry ee s)]) - (redisplay ee entry 1) - (move-eol ee entry) - entry))) - - (define ee-history-bwd - (lambda (ee entry c) - (cond - [(and (not (null-entry? entry)) (entry-modified? ee entry)) - (beep "cannot leave nonempty modified entry") - entry] - [(history-search-bwd ee (lambda (s) #t)) => - (lambda (s) - ; clear histkey when null as favor to search commands - (when (null-entry? entry) (eestate-histkey-set! ee "")) - (new-entry ee entry s))] - [else - (beep "invalid history movement") - entry]))) - - (define ee-history-fwd - (lambda (ee entry c) - (cond - [(and (not (null-entry? entry)) (entry-modified? ee entry)) - (beep "cannot leave nonempty modified entry") - entry] - [(history-search-fwd ee (lambda (s) #t)) => - (lambda (s) - ; clear histkey when null as favor to search commands - (when (null-entry? entry) (eestate-histkey-set! ee "")) - (new-entry ee entry s))] - [else - (beep "invalid history movement") - entry]))) - - (define history-search-bwd-key - (lambda (ee entry match?) - (if (or (entry-modified? ee entry) (null-entry? entry)) - (begin - (history-fast-forward! ee) - (eestate-histkey-set! ee (entry->string entry)) - (cond - [(history-search-bwd ee - (lambda (s) (match? (eestate-histkey ee) s))) => - (lambda (s) (new-entry ee entry s))] - [else - (beep "invalid history movement") - entry])) - ; if nonempty and unmodified, we must already have moved via one - ; of the history commands, so eestate-histkey should be valid - (cond - [(history-search-bwd ee - (lambda (s) (match? (eestate-histkey ee) s))) => - (lambda (s) (new-entry ee entry s))] - [else - (beep "invalid history movement") - entry])))) - - (define history-search-fwd-key - ; similar to history-search-bwd-key but "finds" key at forward extreme - (lambda (ee entry match?) - (if (or (entry-modified? ee entry) (null-entry? entry)) - (begin - (history-fast-forward! ee) - (eestate-histkey-set! ee (entry->string entry)) - (cond - [(history-search-fwd ee - (lambda (s) (prefix? (eestate-histkey ee) s))) => - (lambda (s) (new-entry ee entry s))] - [else - (beep "invalid history movement") - entry])) - ; if nonempty and unmodified, we must already have moved via one - ; of the history commands, so eestate-histkey should be valid - (cond - [(history-search-fwd ee - (lambda (s) (match? (eestate-histkey ee) s))) => - (lambda (s) (new-entry ee entry s))] - [else - (let ([entry (new-entry ee entry (eestate-histkey ee))]) - (history-fast-forward! ee) - entry)])))) - - (define ee-history-fwd-prefix - (lambda (ee entry c) - (history-search-fwd-key ee entry prefix?))) - - (define ee-history-bwd-prefix - (lambda (ee entry c) - (history-search-bwd-key ee entry prefix?))) - - (define ee-history-fwd-contains - (lambda (ee entry c) - (history-search-fwd-key ee entry contains?))) - - (define ee-history-bwd-contains - (lambda (ee entry c) - (history-search-bwd-key ee entry contains?))) -) - -(define ee-newline/accept - (lambda (ee entry c) - (cond - [(null-entry? entry) entry] - ; #f tells ee-read to return expr - [(and (find-next-sexp-forward ee entry 0 0 #t) - (only-whitespace-left? ee entry)) - (let loop () - (delete-to-eol ee entry) - (unless (last-line? ee entry) - (join-rows ee entry) - (loop))) - #f] - [else - (insert-strings-before ee entry '("" "")) - (when (should-auto-indent? ee) (indent ee entry)) - entry]))) - -(define ee-newline - (lambda (ee entry c) - (cond - [(null-entry? entry) entry] - [else - (insert-strings-before ee entry '("" "")) - (when (should-auto-indent? ee) (indent ee entry)) - entry]))) - -(define ee-accept - (lambda (ee entry c) - ; force ee-read to attempt read even if not at end of expr and not balanced - (on-error #f - (let ([sip (open-input-string (entry->string entry))]) - (let loop () - (let-values ([(type value start end) (read-token sip)]) - (cond - [(eq? type 'eof) - ; entry contains only whitespace and comments. pretend to accept - ; but don't really, or ee-read will return eof, causing cafe to exit - (update-history! ee entry) - (move-eoe ee entry) - (no-raw-mode) - (ee-write-char #\newline) - (ee-flush) - (raw-mode) - (let ([entry (string->entry ee "")]) - (redisplay ee entry) - entry)] - [(and (eq? type 'quote) (eq? value 'datum-comment)) - (read sip) - (loop)] - [else #f]))))))) - -(define ee-open-line - (lambda (ee entry c) - (let ([point (entry-point entry)]) - (insert-strings-before ee entry '("" "")) - (when (should-auto-indent? ee) (indent ee entry)) - (goto ee entry point) - entry))) - -(define ee-indent - (lambda (ee entry c) - (indent ee entry) - entry)) - -(define ee-indent-all - (lambda (ee entry c) - (indent-all ee entry) - entry)) - -(define ee-backward-char - (lambda (ee entry c) - (if (beginning-of-line? ee entry) - (unless (first-line? ee entry) - (move-up ee entry) - (move-eol ee entry)) - (move-left ee entry)) - entry)) - -(define ee-forward-char - (lambda (ee entry c) - (if (end-of-line? ee entry) - (unless (last-line? ee entry) - (move-down ee entry) - (move-bol ee entry)) - (move-right ee entry)) - entry)) - -(define ee-next-line - (lambda (ee entry c) - (if (last-line? ee entry) - (ee-history-fwd ee entry c) - (begin - (move-down ee entry) - entry)))) - -(define ee-previous-line - (lambda (ee entry c) - (if (first-line? ee entry) - (ee-history-bwd ee entry c) - (begin - (move-up ee entry) - entry)))) - -(define ee-end-of-line - (lambda (ee entry c) - (move-eol ee entry) - entry)) - -(define ee-beginning-of-line - (lambda (ee entry c) - (move-bol ee entry) - entry)) - -(define ee-beginning-of-entry - (lambda (ee entry c) - (goto ee entry (make-pos 0 0)) - entry)) - -(define ee-end-of-entry - (lambda (ee entry c) - (move-eoe ee entry) - entry)) - -(define ee-delete-to-eol - (lambda (ee entry c) - (if (end-of-line? ee entry) - (unless (last-line? ee entry) - (join-rows ee entry) - (eestate-killbuf-set! ee - (if (eq? (eestate-last-op ee) ee-delete-to-eol) - (append (eestate-killbuf ee) '("")) - '("")))) - (eestate-killbuf-set! ee - (let ([killbuf (delete-to-eol ee entry)]) - (if (eq? (eestate-last-op ee) ee-delete-to-eol) - ; last addition must have been ("") representing newline - (append (reverse (cdr (reverse (eestate-killbuf ee)))) - killbuf) - killbuf)))) - entry)) - -(define ee-delete-line - (lambda (ee entry c) - (if (and (first-line? ee entry) - (not (last-line? ee entry)) - (last-line-displayed? ee entry)) - (ee-delete-entry ee entry c) - (begin - (move-bol ee entry) - (let ([killbuf (delete-to-eol ee entry)]) - (unless (equal? killbuf '("")) - (eestate-killbuf-set! ee killbuf))) - entry)))) - -(define ee-delete-between-point-and-mark - (lambda (ee entry c) - (let ([point (entry-point entry)] [mark (entry-mark entry)]) - (if mark - (unless (pos=? mark point) - (eestate-killbuf-set! ee - (if (posentry ee "")]) - (redisplay ee entry) - entry))) - -(define ee-reset-entry - (lambda (ee entry c) - (history-fast-forward! ee) - (ee-delete-entry ee entry c))) - -(define ee-delete-sexp - (lambda (ee entry c) - (let ([pos (find-next-sexp-forward ee entry - (entry-row entry) (entry-col entry) #f)]) - (if pos - (eestate-killbuf-set! ee - (delete-forward ee entry (pos-row pos) (pos-col pos))) - (beep "end of s-expression not found"))) - entry)) - -(define ee-backward-delete-sexp - (lambda (ee entry c) - (let ([row (entry-row entry)] [col (entry-col entry)]) - (let ([pos (find-next-sexp-backward ee entry row col)]) - (if pos - (begin - (goto ee entry pos) - (eestate-killbuf-set! ee (delete-forward ee entry row col))) - (beep "start of s-expression not found")))) - entry)) - -(define ee-redisplay - (lambda (ee entry c) - (if (eq? (eestate-last-op ee) ee-redisplay) - (clear-screen) - (clear-entry ee entry)) - (redisplay ee entry) - entry)) - -(define ee-yank-kill-buffer - (lambda (ee entry c) - (insert-strings-before ee entry (eestate-killbuf ee)) - entry)) - -(define ee-yank-selection - (lambda (ee entry c) - (insert-strings-before ee entry - (string->lines - (let* ([s (get-clipboard)] - [n (fx- (string-length s) 1)]) - (if (and (fx>= n 0) (char=? (string-ref s n) #\newline)) - (substring s 0 n) - s)))) - entry)) - -(define ee-string-macro - (lambda (str) - (lambda (ee entry c) - (insert-string-before ee entry str) - entry))) - -(define ee-eof - (lambda (ee entry c) - (cond - [(null-entry? entry) #f] - [else (beep "eof ignored except in null entry")]))) - -(define ee-delete-char - (lambda (ee entry c) - (cond - [(end-of-line? ee entry) - (unless (last-line? ee entry) (join-rows ee entry)) - entry] - [else (delete-char ee entry) entry]))) - -(define ee-eof/delete-char - (lambda (ee entry c) - (cond - [(null-entry? entry) - (if (eq? (eestate-last-op ee) ee-eof/delete-char) - entry ; assume attempt to continue deleting chars - #f)] - [(end-of-line? ee entry) - (unless (last-line? ee entry) (join-rows ee entry)) - entry] - [else (delete-char ee entry) entry]))) - -(define ee-backward-delete-char - (lambda (ee entry c) - (if (beginning-of-line? ee entry) - (unless (first-line? ee entry) - (move-up ee entry) - (move-eol ee entry) - (join-rows ee entry)) - (begin - (move-left ee entry) - (delete-char ee entry))) - entry)) - -(define ee-insert-paren - (lambda (ee entry c) - (add-char ee entry c) - (when (or (ee-flash-parens) (ee-auto-paren-balance)) - (correct&flash-matching-delimiter ee entry)) - entry)) - -(define ee-goto-matching-delimiter - (lambda (ee entry c) - (let ([pos (find-matching-delimiter ee entry)]) - (if pos - (goto ee entry pos) - (beep "matching delimiter not found"))) - entry)) - -(define ee-flash-matching-delimiter - (lambda (ee entry c) - (let ([pos (find-matching-delimiter ee entry)]) - (if pos - (flash ee entry pos) - (beep "matching delimiter not found"))) - entry)) - -(define ee-exchange-point-and-mark - (lambda (ee entry c) - (let ([mark (entry-mark entry)]) - (if mark - (begin - (entry-mark-set! entry (entry-point entry)) - (goto ee entry mark)) - (beep "mark not set"))) - entry)) - -(define ee-forward-sexp - (lambda (ee entry c) - (let ([pos (find-next-sexp-forward ee entry - (entry-row entry) (entry-col entry) #f)]) - (if pos - (goto ee entry pos) - (beep "end of s-expression not found"))) - entry)) - -(define ee-backward-sexp - (lambda (ee entry c) - (let ([pos (find-next-sexp-backward ee entry - (entry-row entry) (entry-col entry))]) - (if pos - (goto ee entry pos) - (beep "start of s-expression not found"))) - entry)) - -(define ee-forward-word - (lambda (ee entry c) - (goto ee entry - (find-next-word ee entry - (entry-row entry) - (entry-col entry))) - entry)) - -(define ee-backward-word - (lambda (ee entry c) - (goto ee entry - (find-previous-word ee entry - (entry-row entry) - (entry-col entry))) - entry)) - -(define ee-forward-page - (lambda (ee entry c) - (page-down ee entry) - entry)) - -(define ee-backward-page - (lambda (ee entry c) - (page-up ee entry) - entry)) - -(define ee-suspend-process - (lambda (ee entry c) - (carriage-return) - (line-feed) - (clear-eos) - (ee-flush) - (no-raw-mode) - (pause) - (raw-mode) - (carriage-return) - (clear-eos) - (redisplay ee entry) - entry)) - -(define (ee-compose . p*) - (rec ee-composition - (lambda (ee entry c) - (let f ([p* p*] [entry entry]) - (if (null? p*) - entry - (let ([entry ((car p*) ee entry c)]) - (and entry (f (cdr p*) entry)))))))) - -;;; key bindings - -;;; (ee-bind-key key ee-xxx) - -;;; key must evaluate to a , where: -;;; -;;; = | -;;; -;;; -> "+" -;;; -> -;;; \e escape character -;;; ^x control is applied to character x -;;; \\ backslash -;;; \^ caret -;;; any character other than \ or ^ -;;; -;;; examples: -;;; -;;; input key description byte sequence -;;; --------- ----------- ------------- -;;; #\a letter 'a' 97 -;;; #\^ caret 94 -;;; -;;; examples: -;;; -;;; input key contents description byte sequence -;;; --------- -------- ----------- ------------- -;;; "\\ex" \ex Esc-x 27 120 -;;; "^a" ^a Ctrl-A 1 -;;; "\\\\" \\ backslash 92 -;;; "\\^" \^ caret 94 -;;; "a" a letter 'a' 97 - -(module (dispatch-table? base-dispatch-table ee-bind-key) - (define make-dispatch-table - (lambda () - (make-eqv-hashtable 256))) - - (define dispatch-table? hashtable?) - - (define ee-bind-key - (lambda (key proc) - (unless (or (char? key) - (and (string? key) (fx> (string-length key) 0))) - ($oops 'ee-bind-key "~s is not a valid key (character or nonempty string)" key)) - (unless (procedure? proc) - ($oops 'ee-bind-key "~s is not a procedure" proc)) - - (if (string? key) - (let* ([n (string-length key)]) - (define (s0 table i) - (let ([c (string-ref key i)]) - (case c - [(#\\) (s-backslash table (fx+ i 1))] - [(#\^) (s-caret table (fx+ i 1))] - [else (s-lookup table (fx+ i 1) c)]))) - (define (s-backslash table i) - (when (fx= i n) - ($oops 'ee-bind-key - "malformed key ~s (nothing following \\)" - key)) - (let ([c (string-ref key i)]) - (case c - [(#\e) (s-lookup table (fx+ i 1) #\esc)] - [(#\\ #\^) (s-lookup table (fx+ i 1) c)] - [else ($oops 'ee-bind-key - "malformed key ~s (unexpected character following \\)" - key)]))) - (define (s-caret table i) - (define (^char c) - (integer->char (fxlogand (char->integer c) #b11111))) - (when (fx= i n) - ($oops 'ee-bind-key - "malformed key ~s (nothing following ^)" - key)) - (s-lookup table (fx+ i 1) (^char (string-ref key i)))) - (define (s-lookup table i key) - (let ([x (hashtable-ref table key #f)]) - (cond - [(fx= i n) - (when (dispatch-table? x) - (warningf 'ee-bind-key - "definition for key ~s disables its use as a prefix" - key)) - (hashtable-set! table key proc)] - [(dispatch-table? x) (s0 x i)] - [else - (when (procedure? x) - (warningf 'ee-bind-key - "definition for key ~s disables its use as a prefix" - key)) - (let ([x (make-dispatch-table)]) - (hashtable-set! table key x) - (s0 x i))]))) - (s0 base-dispatch-table 0)) - (begin - (when (dispatch-table? (hashtable-ref base-dispatch-table key #f)) - (warningf 'ee-bind-key - "definition for key ~s disables its use as a prefix" - key)) - (hashtable-set! base-dispatch-table key proc))))) - - (define base-dispatch-table (make-dispatch-table)) - - ; set up self-insertion for space and all printing characters - (for-each - (lambda (c) (ee-bind-key c ee-insert-self)) - (string->list " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")) -) - -(let ([ebk ee-bind-key]) - ; newline operations - (ebk #\return ee-newline/accept) ; Enter, ^M - (ebk "^J" ee-accept) ; ^J - (ebk "^O" ee-open-line) ; ^O - - ; indenting operations - (ebk "\\e\t" ee-indent) ; Esc-Tab - (ebk "\\eq" ee-indent-all) ; Esc-q - (ebk "\\eQ" ee-indent-all) ; Esc-Q - (ebk "\\e^Q" ee-indent-all) ; Esc-^Q - - ; command completion - (ebk "\t" ee-id-completion/indent) ; Tab - (ebk "^R" ee-next-id-completion) ; ^R - - ; cursor movement keys - (ebk "^B" ee-backward-char) ; ^B - (ebk "\\e[D" ee-backward-char) ; Left ; ] - (ebk "^F" ee-forward-char) ; ^F - (ebk "\\e[C" ee-forward-char) ; Right ; ] - (ebk "^N" ee-next-line) ; ^N - (ebk "\\e[B" ee-next-line) ; Down - (ebk "^P" ee-previous-line) ; ^P - (ebk "\\e[A" ee-previous-line) ; Up - - (ebk "\\ef" ee-forward-word) ; Esc-f - (ebk "\\eF" ee-forward-word) ; Esc-F - (ebk "\\e^F" ee-forward-sexp) ; Esc-^F - (ebk "\\eb" ee-backward-word) ; Esc-b - (ebk "\\eB" ee-backward-word) ; Esc-B - (ebk "\\e^B" ee-backward-sexp) ; Esc-^B - - (ebk "^X^X" ee-exchange-point-and-mark) ; ^X^X - (ebk "^X[" ee-backward-page) ; ^X[ - (ebk "^X]" ee-forward-page) ; ^X] - (ebk "\\e[5~" ee-backward-page) ; Page-Up - (ebk "\\e[6~" ee-forward-page) ; Page-Down - - (ebk "^E" ee-end-of-line) ; ^E - (ebk "\\e[F" ee-end-of-line) ; End key - ; terminals are supposed to default to "normal" (aka "cursor") rather than - ; "application" mode and in normal mode send ANSI \\e[F and \\e[H for End - ; and Home. although gnome terminal apparently starts in normal mode, it - ; sends the application-mode sequences for this. we capitulate reluctantly, - ; since by defining Esc-OF and Esc-OH to do End and Home we prevent people - ; from binding Esc-O by itself to a command. - (ebk "\\eOF" ee-end-of-line) ; End key (gnome terminal) - (ebk "\\e[4~" ee-end-of-line) ; End key (cygwin) - (ebk "^A" ee-beginning-of-line) ; ^A - (ebk "\\e[H" ee-beginning-of-line) ; Home key - (ebk "\\eOH" ee-beginning-of-line) ; Home key (gnome terminal) - (ebk "\\e[1~" ee-beginning-of-line) ; Home key (cygwin) - (ebk "\\e<" ee-beginning-of-entry) ; Esc-< - (ebk "\\e>" ee-end-of-entry) ; Esc-> ; [[ - (ebk "\\e]" ee-goto-matching-delimiter) ; Esc-] - (ebk #\( ee-insert-paren) ; ( - (ebk #\) ee-insert-paren) ; ) - (ebk #\[ ee-insert-paren) ; [ - (ebk #\] ee-insert-paren) ; ] - (ebk "^]" ee-flash-matching-delimiter) ; ^] - - ; destructive functions - (ebk "^U" ee-delete-line) ; ^U - (ebk "^K" ee-delete-to-eol) ; ^K - (ebk "\\ek" ee-delete-to-eol) ; Esc-k - (ebk "^W" ee-delete-between-point-and-mark) ; ^W - (ebk "^G" ee-delete-entry) ; ^G - (ebk "^C" ee-reset-entry) ; ^C - (ebk "\\e^K" ee-delete-sexp) ; Esc-^K - (ebk "\\e\\e[3~" ee-delete-sexp) ; Esc-Delete - (ebk "\\e\177" ee-backward-delete-sexp) ; Esc-Backspace - (ebk "\\e^H" ee-backward-delete-sexp) ; Esc-^H - (ebk "^V" ee-yank-selection) ; ^V - (ebk "^Y" ee-yank-kill-buffer) ; ^Y - (ebk "^D" ee-eof/delete-char) ; ^D - (ebk #\rubout ee-backward-delete-char) ; Backspace (<--) - (ebk "\\e[3~" ee-delete-char) ; Delete - (ebk "^H" ee-backward-delete-char) ; ^H - (ebk "^@" ee-set-mark) ; ^@ (or ^Space) - (ebk "^^" ee-set-mark) ; ^^ - - ; display functions - (ebk "^L" ee-redisplay) ; ^L - - ; string macros - (ebk "\\ed" (ee-string-macro "(define ")) ; Esc-d ; ) - (ebk "\\el" (ee-string-macro "(lambda ")) ; Esc-l ; ) - - ; history keys - (ebk "\\e^P" ee-history-bwd) ; Esc-^P - (ebk "\\e\\e[A" ee-history-bwd) ; Esc-Up - (ebk "\\e^N" ee-history-fwd) ; Esc-^N - (ebk "\\e\\e[B" ee-history-fwd) ; Esc-Down - (ebk "\\ep" ee-history-bwd-prefix) ; Esc-p - (ebk "\\eP" ee-history-bwd-contains) ; Esc-P - (ebk "\\en" ee-history-fwd-prefix) ; Esc-n - (ebk "\\eN" ee-history-fwd-contains) ; Esc-N - - ; misc - (ebk "\\e^U" ee-command-repeat) ; Esc-^U - (ebk "^Z" ee-suspend-process) ; ^Z -) - -(set! $expeditor - (lambda (thunk) - (let ([ee #f]) - (define (expeditor-prompt-and-read n) - (if (cond - [(eestate? ee) #t] - [(eq? ee 'failed) #f] - [(init-screen) - (set! ee (make-eestate)) - (let ([histfile ($expeditor-history-file)]) - (when histfile - (on-error (void) (ee-load-history ee histfile)))) - #t] - [else (set! ee 'failed) #f]) - (ee-prompt-and-read ee n) - (default-prompt-and-read n))) - (let-values ([val* (parameterize ([waiter-prompt-and-read expeditor-prompt-and-read]) - (thunk))]) - (when (eestate? ee) - (let ([histfile ($expeditor-history-file)]) - (when histfile - (on-error (void) (ee-save-history ee histfile))))) - (apply values val*))))) -) - -) ; when-feature expeditor diff --git a/ta6ob/s/expeditor.ta6ob b/ta6ob/s/expeditor.ta6ob deleted file mode 100644 index 0353669..0000000 Binary files a/ta6ob/s/expeditor.ta6ob and /dev/null differ diff --git a/ta6ob/s/fasl-helpers.ss b/ta6ob/s/fasl-helpers.ss deleted file mode 100644 index a673c1d..0000000 --- a/ta6ob/s/fasl-helpers.ss +++ /dev/null @@ -1,157 +0,0 @@ -;;; fasl-helpers.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(module (put8 put16 put32 put64 put-iptr put-uptr) - (define (bit-mask k) (- (ash 1 k) 1)) - (define put8 - (lambda (p n) - (put-u8 p (fxlogand n (bit-mask 8))))) - (define put16-le - (cond - [(>= (most-positive-fixnum) (bit-mask 16)) - (lambda (p n) - (put-u8 p (fxlogand n (bit-mask 8))) - (put-u8 p (fxlogand (fxsrl n 8) (bit-mask 8))))] - [else ($oops 'put16-le "unsupported fixnum size")])) - (define put16-be - (cond - [(>= (most-positive-fixnum) (bit-mask 16)) - (lambda (p n) - (put-u8 p (fxlogand (fxsrl n 8) (bit-mask 8))) - (put-u8 p (fxlogand n (bit-mask 8))))] - [else ($oops 'put16-be "unsupported fixnum size")])) - (define put16 - (lambda (p n) - (constant-case native-endianness - [(little) (put16-le p n)] - [(big) (put16-be p n)]))) - (define put32-le - (cond - [(>= (most-positive-fixnum) (bit-mask 32)) - (lambda (p n) - (put-u8 p (fxlogand n (bit-mask 8))) - (put-u8 p (fxlogand (fxsrl n 8) (bit-mask 8))) - (put-u8 p (fxlogand (fxsrl n 16) (bit-mask 8))) - (put-u8 p (fxlogand (fxsrl n 24) (bit-mask 8))))] - [(>= (most-positive-fixnum) (bit-mask 24)) - (lambda (p n) - (cond - [(fixnum? n) - (put-u8 p (fxlogand n (bit-mask 8))) - (put-u8 p (fxlogand (fxsrl n 8) (bit-mask 8))) - (put-u8 p (fxlogand (fxsrl n 16) (bit-mask 8))) - (put-u8 p (fxlogand (fxsra n 24) (bit-mask 8)))] - [else - (let ([n (logand n (bit-mask 16))]) - (put-u8 p (fxlogand n (bit-mask 8))) - (put-u8 p (fxsrl n 8))) - (let ([n (ash n -16)]) - (put-u8 p (fxlogand n (bit-mask 8))) - (put-u8 p (fxlogand (fxsra n 8) (bit-mask 8))))]))] - [else ($oops 'put32-le "unsupported fixnum size")])) - (define put32-be - (cond - [(>= (most-positive-fixnum) (bit-mask 32)) - (lambda (p n) - (put-u8 p (fxlogand (fxsrl n 24) (bit-mask 8))) - (put-u8 p (fxlogand (fxsrl n 16) (bit-mask 8))) - (put-u8 p (fxlogand (fxsrl n 8) (bit-mask 8))) - (put-u8 p (fxlogand n (bit-mask 8))))] - [(>= (most-positive-fixnum) (bit-mask 24)) - (lambda (p n) - (cond - [(fixnum? n) - (put-u8 p (fxlogand (fxsra n 24) (bit-mask 8))) - (put-u8 p (fxlogand (fxsrl n 16) (bit-mask 8))) - (put-u8 p (fxlogand (fxsrl n 8) (bit-mask 8))) - (put-u8 p (fxlogand n (bit-mask 8)))] - [else - (let ([n (ash n -16)]) - (put-u8 p (fxlogand (fxsra n 8) (bit-mask 8))) - (put-u8 p (fxlogand n (bit-mask 8)))) - (let ([n (logand n (bit-mask 16))]) - (put-u8 p (fxsrl n 8)) - (put-u8 p (fxlogand n (bit-mask 8))))]))] - [else ($oops 'put32-be "unsupported fixnum size")])) - (define put32 - (lambda (p n) - (constant-case native-endianness - [(little) (put32-le p n)] - [(big) (put32-be p n)]))) - (define put64-le - (lambda (p n) - (cond - [(and (>= (most-positive-fixnum) (bit-mask 32)) (fixnum? n)) - (put32-le p (fxlogand n (bit-mask 32))) - (put32-le p (ash n -32))] - [else - (put32-le p (logand n (bit-mask 32))) - (put32-le p (ash n -32))]))) - (define put64-be - (lambda (p n) - (cond - [(and (>= (most-positive-fixnum) (bit-mask 32)) (fixnum? n)) - (put32-be p (ash n -32)) - (put32-be p (fxlogand n (bit-mask 32)))] - [else - (put32-be p (ash n -32)) - (put32-be p (logand n (bit-mask 32)))]))) - (define put64 - (lambda (p n) - (constant-case native-endianness - [(little) (put64-le p n)] - [(big) (put64-be p n)]))) - (define put-iptr - (lambda (p n0) - (let f ([n (if (< n0 0) (- n0) n0)] [cbit 0]) - (if (and (fixnum? n) (fx<= n 63)) - (put8 p (fxlogor (if (< n0 0) #x80 0) (fxsll n 1) cbit)) - (begin - (f (ash n -7) 1) - (put-u8 p (fxlogor (fxsll (logand n #x7f) 1) cbit))))))) - (define put-uptr - (lambda (p n) - (unless (>= n 0) - ($oops 'compiler-internal "put-uptr received negative input ~s" n)) - (let f ([n n] [cbit 0]) - (if (and (fixnum? n) (fx<= n 127)) - (put-u8 p (fxlogor (fxsll n 1) cbit)) - (begin - (f (ash n -7) 1) - (put-u8 p (fxlogor (fxsll (logand n #x7f) 1) cbit))))))) -) - -(define emit-header - (case-lambda - [(p version mtype) (emit-header p version mtype '())] - [(p version mtype bootfiles) - (define (put-str p s) - (let ([n (string-length s)]) - (do ([i 0 (fx+ i 1)]) - ((fx= i n)) - (let* ([c (string-ref s i)] [k (char->integer c)]) - (unless (fx<= k 255) - ($oops #f "cannot handle bootfile name character ~s whose integer code exceeds 255" c)) - (put-u8 p k))))) - (put-bytevector p (constant fasl-header)) - (put-uptr p version) - (put-uptr p mtype) - (put-u8 p (char->integer #\()) ; ) - (let f ([bootfiles bootfiles] [sep? #f]) - (unless (null? bootfiles) - (when sep? (put-u8 p (char->integer #\space))) - (put-str p (car bootfiles)) - (f (cdr bootfiles) #t))) ; ( - (put-u8 p (char->integer #\)))])) diff --git a/ta6ob/s/fasl.ss b/ta6ob/s/fasl.ss deleted file mode 100644 index 13941ac..0000000 --- a/ta6ob/s/fasl.ss +++ /dev/null @@ -1,712 +0,0 @@ -;;; fasl.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(let () -(define-record-type target - (nongenerative #{target dchg2hp5v3cck8ge283luo-1}) - (sealed #t) - (fields - fasl-bld-graph - fasl-enter - fasl-out - fasl-start - fasl-table - fasl-wrf-graph - fasl-base-rtd - fasl-write - fasl-file)) - -(let () -(include "types.ss") - -; don't use rtd-* as defined in record.ss in case we're building a patch -; file for cross compilation, because the offsets may be incorrect -(define rtd-size (csv7:record-field-accessor #!base-rtd 'size)) -(define rtd-flds (csv7:record-field-accessor #!base-rtd 'flds)) -(define rtd-parent (csv7:record-field-accessor #!base-rtd 'parent)) -(define rtd-name (csv7:record-field-accessor #!base-rtd 'name)) -(define rtd-uid (csv7:record-field-accessor #!base-rtd 'uid)) -(define rtd-flags (csv7:record-field-accessor #!base-rtd 'flags)) - -(define-record-type table - (fields (mutable count) (immutable hash)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda () - (new 0 (make-eq-hashtable)))))) - -(include "fasl-helpers.ss") - -(define bld-pair - (lambda (x t a?) - (bld (car x) t a?) - (bld (cdr x) t a?))) - -(define bld-vector - (lambda (x t a?) - (let ([len (vector-length x)]) - (let bldvec ([i 0]) - (unless (fx= i len) - (bld (vector-ref x i) t a?) - (bldvec (fx+ i 1))))))) - -(define bld-record - (lambda (x t a?) - (unless (eq? x #!base-rtd) - (when (record-type-descriptor? x) - ; fasl representation for record-type-descriptor includes uid separately and as part of the record - (bld (record-type-uid x) t a?)) - (really-bld-record x t a?)))) - -(define really-bld-record - (lambda (x t a?) - (let ([rtd ($record-type-descriptor x)]) - (bld rtd t a?) - (do ([flds (rtd-flds rtd) (cdr flds)] [i 0 (+ i 1)]) - ((null? flds)) - (when (memq (fld-type (car flds)) '(scheme-object ptr)) - (bld ((csv7:record-field-accessor rtd i) x) t a?)))))) - -(define bld-ht - (lambda (x t a?) - (let-values ([(keyvec valvec) (hashtable-entries x)]) - (vector-for-each - (lambda (key val) - (bld key t a?) - (bld val t a?)) - keyvec valvec)))) - -(define bld-box - (lambda (x t a?) - (bld (unbox x) t a?))) - -(define bld-simple - (lambda (x t a?) - (void))) - -(module (bld-graph dump-graph reset-dump-graph) - (define enable-dump-graph? #f) - (define vcat (if enable-dump-graph? - `#((code . ,(lambda (x) (and (pair? x) (eq? (car x) 'code)))) - (pair . ,pair?) - (string . ,string?) - (symbol . ,symbol?) - (vector . ,vector?) - (record . ,record?) - (other . ,(lambda (x) #t))))) - (define ventry) - (define vdup) - (define record! - (lambda (v x) - (when enable-dump-graph? - (let f ([i 0]) - (let ([cat (vector-ref vcat i)]) - (if ((cdr cat) x) - (vector-set! v i (fx+ (vector-ref v i) 1)) - (f (fx+ i 1)))))))) - (define reset-dump-graph - (lambda () - (when enable-dump-graph? - (set! ventry (make-vector (vector-length vcat) 0)) - (set! vdup (make-vector (vector-length vcat) 0))))) - (define dump-graph - (lambda () - (when enable-dump-graph? - (vector-for-each - (lambda (cat entry dup) - (printf "~10s ~10s ~s\n" entry dup (car cat))) - vcat ventry vdup)))) - (define bld-graph - (lambda (x t a? handler) - (let ([a (eq-hashtable-cell (table-hash t) x 'first)]) - (let ([p (cdr a)]) - (cond - [(eq? p 'first) - #;(let ([n (hashtable-size (table-hash t))]) - (when (fx= (modulo n 10000) 0) - (printf "entries = ~s, ba = ~s, count = ~s\n" n (bytes-allocated) (table-count t)))) - (record! ventry x) - (set-cdr! a #f) - (handler x t a?)] - [(not p) - (record! vdup x) - (let ([n (table-count t)]) - (set-cdr! a (cons n #t)) - (table-count-set! t (fx+ n 1)))]))))) - (reset-dump-graph)) - -(define bld - (lambda (x t a?) - (cond - [(pair? x) (bld-graph x t a? bld-pair)] - [(vector? x) (bld-graph x t a? bld-vector)] - [(or (symbol? x) (string? x)) (bld-graph x t a? bld-simple)] - ; this check must go before $record? check - [(and (annotation? x) (not a?)) - (bld (annotation-stripped x) t a?)] - ; this check must go before $record? check - [(eq-hashtable? x) (bld-graph x t a? bld-ht)] - ; this check must go before $record? check - [(symbol-hashtable? x) (bld-graph x t a? bld-ht)] - [($record? x) (bld-graph x t a? bld-record)] - [(box? x) (bld-graph x t a? bld-box)] - [(or (large-integer? x) (ratnum? x) ($inexactnum? x) ($exactnum? x) - (fxvector? x) (bytevector? x)) - (bld-graph x t a? bld-simple)]))) - -(module (small-integer? large-integer?) - (define least-small-integer (- (expt 2 31))) - (define greatest-small-integer (- (expt 2 31) 1)) - (define small-integer? - (lambda (x) - (if (fixnum? greatest-small-integer) - (and (fixnum? x) (fx<= least-small-integer x greatest-small-integer)) - (or (fixnum? x) (and (bignum? x) (<= least-small-integer x greatest-small-integer)))))) - (define large-integer? - (lambda (x) - (if (fixnum? greatest-small-integer) - (if (fixnum? x) (not (fx<= least-small-integer x greatest-small-integer)) (bignum? x)) - (and (bignum? x) (not (<= least-small-integer x greatest-small-integer))))))) - -(define wrf-small-integer - (lambda (x p t a?) - (put-u8 p (constant fasl-type-small-integer)) - (put-iptr p x))) - -(define wrf-large-integer - (lambda (x p t a?) - (put-u8 p (constant fasl-type-large-integer)) - (put-u8 p (if (positive? x) 0 1)) - (let* ([x (abs x)] [il (integer-length x)]) - (let* ([n (bitwise-arithmetic-shift-right il - (log2 (constant bigit-bits)))] - [m (bitwise-arithmetic-shift-left n - (log2 (constant bigit-bits)))]) - (if (fx= m il) - (put-uptr p n) - (begin - (put-uptr p (+ n 1)) - (put-uptr p (bitwise-arithmetic-shift-right x m)))) - (let f ([end m]) - (unless (= end 0) - (let ([start (- end (constant bigit-bits))]) - (put-uptr p (bitwise-bit-field x start end)) - (f start)))))))) - -(define wrf-pair - (lambda (x p t a?) - (cond - [(weak-pair? x) - (put-u8 p (constant fasl-type-weak-pair)) - (wrf (car x) p t a?) - (wrf (cdr x) p t a?)] - [(ephemeron-pair? x) - (put-u8 p (constant fasl-type-ephemeron)) - (wrf (car x) p t a?) - (wrf (cdr x) p t a?)] - [else - ; more like list* - (put-u8 p (constant fasl-type-pair)) - (let ([n (let wrf-pair-loop0 ([n 1] [x (cdr x)]) - ; cut off at end or at shared structure - (if (and (pair? x) - (not (weak-pair? x)) - (not (ephemeron-pair? x)) - (not (eq-hashtable-ref (table-hash t) x #f))) - (wrf-pair-loop0 (fx+ n 1) (cdr x)) - n))]) - (put-uptr p n) - (let wrf-pair-loop1 ([x x] [n n]) - (wrf (car x) p t a?) - (if (fx= n 1) - (wrf (cdr x) p t a?) - (wrf-pair-loop1 (cdr x) (fx- n 1)))))]))) - -(define wrf-symbol - (lambda (x p t a?) - (cond - [(gensym? x) - (let ((uname (gensym->unique-string x))) - (put-u8 p (constant fasl-type-gensym)) - (wrf-string-help (symbol->string x) p) - (wrf-string-help uname p))] - [else - (put-u8 p (constant fasl-type-symbol)) - (wrf-string-help (symbol->string x) p)]))) - -(define wrf-string-help - (lambda (x p) - (put-uptr p (string-length x)) - (let ([n (string-length x)]) - (do ([i 0 (fx+ i 1)]) - ((fx= i n)) - (put-uptr p (char->integer (string-ref x i))))))) - -(define wrf-string - (lambda (x p t a?) - (put-u8 p (if (immutable-string? x) - (constant fasl-type-immutable-string) - (constant fasl-type-string))) - (wrf-string-help x p))) - -(define wrf-vector - (lambda (x p t a?) - (put-u8 p (if (immutable-vector? x) - (constant fasl-type-immutable-vector) - (constant fasl-type-vector))) - (let ([n (vector-length x)]) - (put-uptr p n) - (let wrf-vector-loop ([i 0]) - (unless (fx= i n) - (wrf (vector-ref x i) p t a?) - (wrf-vector-loop (fx+ i 1))))))) - -(define wrf-fxvector - (lambda (x p t a?) - (put-u8 p (if (immutable-fxvector? x) - (constant fasl-type-immutable-fxvector) - (constant fasl-type-fxvector))) - (let ([n (fxvector-length x)]) - (put-uptr p n) - (let wrf-fxvector-loop ([i 0]) - (unless (fx= i n) - (put-iptr p (fxvector-ref x i)) - (wrf-fxvector-loop (fx+ i 1))))))) - -(define wrf-bytevector - (lambda (x p t a?) - (put-u8 p (if (immutable-bytevector? x) - (constant fasl-type-immutable-bytevector) - (constant fasl-type-bytevector))) - (let ([n (bytevector-length x)]) - (put-uptr p n) - (let wrf-bytevector-loop ([i 0]) - (unless (fx= i n) - (let ([x (bytevector-u8-ref x i)]) - (put-u8 p x) - (wrf-bytevector-loop (fx+ i 1)))))))) - -; Written as: fasl-tag rtd field ... -(module (wrf-record really-wrf-record wrf-annotation) - (define maybe-remake-rtd - (lambda (rtd) - (if (eq? (machine-type) ($target-machine)) - rtd - ($remake-rtd rtd (let () (include "layout.ss") compute-field-offsets))))) - - (define wrf-fields - (lambda (x p t a?) - ; extract field values using host field information (byte offset and filtered - ; type); write using target field information. to save i/o & space, using iptr - ; as common rep'n for multibyte integer fields since any small unsigned quantity - ; is a small signed but a small negative signed quantity is a large unsigned - ; quantity. we check 16- and 32-bit integer values and fixnums before writing - ; them in case the host field is larger than the target field. - (define get-field - (lambda (host-fld) - (let ([type (fld-type host-fld)] [addr (fld-byte host-fld)]) - ; using $filter-foreign-type to get host filtering - (case ($filter-foreign-type type) - [(scheme-object) ($object-ref 'ptr x addr)] - [(integer-8 unsigned-8 char) ($object-ref 'unsigned-8 x addr)] - [(integer-16 unsigned-16) ($object-ref 'integer-16 x addr)] - [(integer-24 unsigned-24) ($object-ref 'integer-24 x addr)] - [(integer-32 unsigned-32) ($object-ref 'integer-32 x addr)] - [(integer-40 unsigned-40) ($object-ref 'integer-40 x addr)] - [(integer-48 unsigned-48) ($object-ref 'integer-48 x addr)] - [(integer-56 unsigned-56) ($object-ref 'integer-56 x addr)] - [(integer-64 unsigned-64) ($object-ref 'integer-64 x addr)] - [(single-float) ($object-ref 'unsigned-32 x addr)] - [(double-float) ($object-ref 'unsigned-64 x addr)] - [(wchar) - (constant-case wchar-bits - [(16) ($object-ref 'integer-16 x addr)] - [(32) ($object-ref 'integer-32 x addr)])] - [(fixnum) ($object-ref 'fixnum x addr)] - [else ($oops 'fasl-write "cannot fasl record field of type ~s" type)])))) - (define check-field - (lambda (target-fld val) - (unless (eq? (constant machine-type-name) (machine-type)) - (let* ([type (fld-type target-fld)] [filtered-type (filter-foreign-type type)]) - (unless (case filtered-type - [(scheme-object) #t] - [(integer-16 unsigned-16) ($integer-16? val)] - [(integer-32 unsigned-32) ($integer-32? val)] - [(wchar) - (constant-case wchar-bits - [(16) ($integer-16? val)] - [(32) ($integer-32? val)])] - [(fixnum) (<= (- (ash 1 (- (constant fixnum-bits) 1))) val (- (ash 1 (- (constant fixnum-bits) 1)) 1))] - [(char single-float double-float) #t] - [(integer-8 integer-64 integer-24 integer-40 integer-48 integer-56) #t] - [(unsigned-8 unsigned-64 unsigned-24 unsigned-40 unsigned-48 unsigned-56) #t] - [else ($oops 'fasl-write "unexpected difference in filtered foreign type ~s for unfiltered type ~s" filtered-type type)]) - ($oops 'fasl-write "host value ~s for type ~s is too big for target" val type)))))) - (define put-field - (lambda (target-fld pad val) - (define put-i64 - (lambda (p val) - (constant-case ptr-bits - [(32) (put-iptr p (bitwise-arithmetic-shift-right val 32)) (put-uptr p (logand val #xffffffff))] - [(64) (put-iptr p val)]))) - (define-syntax put-padty - (syntax-rules () - [(_ fasl-fld-type) - (put-u8 p (fxlogor (fxsll pad 4) (constant fasl-fld-type)))])) - (let ([type (fld-type target-fld)] [addr (fld-byte target-fld)]) - ; using filter-foreign-type to get target filtering - (case (filter-foreign-type type) - [(scheme-object) (put-padty fasl-fld-ptr) (wrf val p t a?) (constant ptr-bytes)] - [(integer-8 unsigned-8 char) (put-padty fasl-fld-u8) (put-u8 p val) 1] - [(integer-16 unsigned-16) (put-padty fasl-fld-i16) (put-iptr p val) 2] - [(integer-24 unsigned-24) (put-padty fasl-fld-i24) (put-iptr p val) 3] - [(integer-32 unsigned-32) (put-padty fasl-fld-i32) (put-iptr p val) 4] - [(integer-40 unsigned-40) (put-padty fasl-fld-i40) (put-i64 p val) 5] - [(integer-48 unsigned-48) (put-padty fasl-fld-i48) (put-i64 p val) 6] - [(integer-56 unsigned-56) (put-padty fasl-fld-i56) (put-i64 p val) 7] - [(integer-64 unsigned-64) (put-padty fasl-fld-i64) (put-i64 p val) 8] - [(single-float) - (put-padty fasl-fld-single) - (put-uptr p val) - 4] - [(double-float) - (put-padty fasl-fld-double) - (let ([n val]) - (put-uptr p (ash n -32)) - (put-uptr p (logand n #xFFFFFFFF))) - 8] - [(wchar) - (constant-case wchar-bits - [(16) (put-padty fasl-fld-i16) (put-iptr p val)] - [(32) (put-padty fasl-fld-i32) (put-iptr p val)]) - (/ (constant wchar-bits) 8)] - [(fixnum) - (constant-case ptr-bits - [(32) (put-padty fasl-fld-i32)] - [(64) (put-padty fasl-fld-i64)]) - (put-iptr p val) - (constant ptr-bytes)] - [else ($oops 'fasl-write "cannot fasl record field of type ~s" type)])))) - (let* ([host-rtd ($record-type-descriptor x)] - [target-rtd (maybe-remake-rtd host-rtd)] - [target-fld* (rtd-flds target-rtd)]) - (put-uptr p (rtd-size target-rtd)) - (put-uptr p (length target-fld*)) - (wrf host-rtd p t a?) - (fold-left - (lambda (last-target-addr host-fld target-fld) - (let ([val (get-field host-fld)]) - (check-field target-fld val) - (let ([target-addr (fld-byte target-fld)]) - (fx+ target-addr (put-field host-fld (fx- target-addr last-target-addr) val))))) - (constant record-data-disp) - (rtd-flds host-rtd) - target-fld*)))) - - (define wrf-record - (lambda (x p t a?) - (if (eq? x #!base-rtd) - (put-u8 p (constant fasl-type-base-rtd)) - (really-wrf-record x p t a?)))) - - (define really-wrf-record - (lambda (x p t a?) - (cond - [(record-type-descriptor? x) - (put-u8 p (constant fasl-type-rtd)) - (wrf (record-type-uid x) p t a?) - (wrf-fields (maybe-remake-rtd x) p t a?)] - [else - (put-u8 p (constant fasl-type-record)) - (wrf-fields x p t a?)]))) - - (define wrf-annotation - (lambda (x p t a?) - (define maybe-remake-annotation - (lambda (x a?) - (if (fx= (annotation-flags x) a?) - x - (make-annotation (annotation-expression x) (annotation-source x) (annotation-stripped x) a?)))) - (put-u8 p (constant fasl-type-record)) - (wrf-fields (maybe-remake-annotation x a?) p t a?))) -) - -(define wrf-eqht - (lambda (x p t a?) - (put-u8 p (constant fasl-type-eq-hashtable)) - (put-u8 p (if (hashtable-mutable? x) 1 0)) - (put-u8 p (cond - [(eq-hashtable-weak? x) (constant eq-hashtable-subtype-weak)] - [(eq-hashtable-ephemeron? x) (constant eq-hashtable-subtype-ephemeron)] - [else (constant eq-hashtable-subtype-normal)])) - (put-uptr p ($ht-minlen x)) - (put-uptr p ($ht-veclen x)) - (let-values ([(keyvec valvec) (hashtable-entries x)]) - (put-uptr p (vector-length keyvec)) - (vector-for-each - (lambda (key val) - (wrf key p t a?) - (unless (<= (constant most-positive-fixnum) (most-positive-fixnum)) - (when (fixnum? key) - (unless (fx<= (constant most-negative-fixnum) key (constant most-positive-fixnum)) - ($oops 'fasl-write "eq-hashtable fixnum key ~s is out-of-range for target machine" key)))) - (wrf val p t a?)) - keyvec valvec)))) - -(define wrf-symht - (lambda (x p t a?) - (put-u8 p (constant fasl-type-symbol-hashtable)) - (put-u8 p (if (hashtable-mutable? x) 1 0)) - (put-uptr p ($ht-minlen x)) - (put-u8 p - (let ([equiv? (hashtable-equivalence-function x)]) - (cond - [(eq? equiv? eq?) 0] - [(eq? equiv? eqv?) 1] - [(eq? equiv? equal?) 2] - [(eq? equiv? symbol=?) 3] - [else ($oops 'fasl-write "unexpected equivalence function ~s for symbol hashtable ~s" equiv? x)]))) - (put-uptr p ($ht-veclen x)) - (let-values ([(keyvec valvec) (hashtable-entries x)]) - (put-uptr p (vector-length keyvec)) - (vector-for-each - (lambda (key val) - (wrf key p t a?) - (wrf val p t a?)) - keyvec valvec)))) - -(define wrf-box - (lambda (x p t a?) - (put-u8 p (if (immutable-box? x) - (constant fasl-type-immutable-box) - (constant fasl-type-box))) - (wrf (unbox x) p t a?))) - -(define wrf-ratnum - (lambda (x p t a?) - (put-u8 p (constant fasl-type-ratnum)) - (wrf ($ratio-numerator x) p t a?) - (wrf ($ratio-denominator x) p t a?))) - -(define wrf-inexactnum - (lambda (x p t a?) - (put-u8 p (constant fasl-type-inexactnum)) - (wrf ($inexactnum-real-part x) p t a?) - (wrf ($inexactnum-imag-part x) p t a?))) - -(define wrf-exactnum - (lambda (x p t a?) - (put-u8 p (constant fasl-type-exactnum)) - (wrf ($exactnum-real-part x) p t a?) - (wrf ($exactnum-imag-part x) p t a?))) - -(define wrf-char - (lambda (x p) - (wrf-immediate - (fxlogor (fxsll (char->integer x) (constant char-data-offset)) - (constant type-char)) - p))) - -(define wrf-immediate - (lambda (x p) - (put-u8 p (constant fasl-type-immediate)) - (put-uptr p x))) - -(define wrf-flonum - (lambda (x p) - (put-u8 p (constant fasl-type-flonum)) - (let ([n ($object-ref 'unsigned-64 x (constant flonum-data-disp))]) - (put-uptr p (ash n -32)) - (put-uptr p (logand n #xFFFFFFFF))))) - -(define wrf-graph - (lambda (x p t a? handler) - (let ([a (eq-hashtable-ref (table-hash t) x #f)]) - (cond - [(not a) - (handler x p t a?)] - [(cdr a) - (put-u8 p (constant fasl-type-graph-def)) - (put-uptr p (car a)) - (set-cdr! a #f) - (handler x p t a?)] - [else - (put-u8 p (constant fasl-type-graph-ref)) - (put-uptr p (car a))])))) - -(define wrf - (lambda (x p t a?) - (cond - [(symbol? x) (wrf-graph x p t a? wrf-symbol)] - [(pair? x) (wrf-graph x p t a? wrf-pair)] - [(small-integer? x) (wrf-small-integer x p t a?)] - [(null? x) (wrf-immediate (constant snil) p)] - [(not x) (wrf-immediate (constant sfalse) p)] - [(eq? x #t) (wrf-immediate (constant strue) p)] - [(string? x) (wrf-graph x p t a? wrf-string)] - [(fxvector? x) (wrf-graph x p t a? wrf-fxvector)] - [(bytevector? x) (wrf-graph x p t a? wrf-bytevector)] - ; this check must go before $record? check - [(annotation? x) - (if a? - (wrf-graph x p t a? wrf-annotation) - (wrf (annotation-stripped x) p t a?))] - ; this check must go before $record? check - [(eq-hashtable? x) (wrf-graph x p t a? wrf-eqht)] - ; this check must go before $record? check - [(symbol-hashtable? x) (wrf-graph x p t a? wrf-symht)] - ; this check must go before $record? check - [(hashtable? x) ($oops 'fasl-write "invalid fasl object ~s" x)] - [($record? x) (wrf-graph x p t a? wrf-record)] - [(vector? x) (wrf-graph x p t a? wrf-vector)] - [(char? x) (wrf-char x p)] - [(box? x) (wrf-graph x p t a? wrf-box)] - [(large-integer? x) (wrf-graph x p t a? wrf-large-integer)] - [(ratnum? x) (wrf-graph x p t a? wrf-ratnum)] - [(flonum? x) (wrf-flonum x p)] - [($inexactnum? x) (wrf-graph x p t a? wrf-inexactnum)] - [($exactnum? x) (wrf-graph x p t a? wrf-exactnum)] - [(eof-object? x) (wrf-immediate (constant seof) p)] - [(bwp-object? x) (wrf-immediate (constant sbwp) p)] - [($unbound-object? x) (wrf-immediate (constant sunbound) p)] - [(eq? x (void)) (wrf-immediate (constant svoid) p)] - [(eq? x '#0=#0#) (wrf-immediate (constant black-hole) p)] - [($rtd-counts? x) (wrf-immediate (constant sfalse) p)] - [else ($oops 'fasl-write "invalid fasl object ~s" x)]))) - -(define start - (lambda (p t situation proc) - (define (append-bvs bv*) - (let f ([bv* bv*] [n 0]) - (if (null? bv*) - (if (fixnum? n) - (make-bytevector n) - ($oops 'fasl-write "fasl output is too large to compress")) - (let ([bv1 (car bv*)]) - (let ([m (bytevector-length bv1)]) - (let ([bv2 (f (cdr bv*) (+ n m))]) - (bytevector-copy! bv1 0 bv2 n m) - bv2)))))) - (dump-graph) - (let-values ([(bv* size) - (let-values ([(p extractor) ($open-bytevector-list-output-port)]) - (let ([n (table-count t)]) - (unless (fx= n 0) - (put-u8 p (constant fasl-type-graph)) - (put-uptr p n))) - (proc p) - (extractor))]) - (put-u8 p situation) - (if (and (>= size 100) (fasl-compressed)) - (let* ([fmt ($tc-field 'compress-format ($tc))] - [bv (append-bvs bv*)] - [uncompressed-size-bv (call-with-bytevector-output-port (lambda (bvp) (put-uptr bvp (bytevector-length bv))))] - [bv ($bytevector-compress bv fmt)]) - (put-uptr p (+ 1 (bytevector-length uncompressed-size-bv) (bytevector-length bv))) - (put-u8 p - (cond - [(eqv? fmt (constant COMPRESS-GZIP)) (constant fasl-type-gzip)] - [(eqv? fmt (constant COMPRESS-LZ4)) (constant fasl-type-lz4)] - [else ($oops 'fasl-write "unexpected $compress-format value ~s" fmt)])) - (put-bytevector p uncompressed-size-bv) - (put-bytevector p bv)) - (begin - (put-uptr p (+ size 1)) - (put-u8 p (constant fasl-type-uncompressed)) - (for-each (lambda (bv) (put-bytevector p bv)) bv*)))))) - -(module (fasl-write fasl-file) - ; when called from fasl-write or fasl-file, always preserve annotations; - ; otherwise use value passed in by the compiler - (define fasl-one - (lambda (x p) - (let ([t (make-table)]) - (bld x t (constant annotation-all)) - (start p t (constant fasl-type-visit-revisit) (lambda (p) (wrf x p t (constant annotation-all))))))) - - (define-who fasl-write - (lambda (x p) - (unless (and (output-port? p) (binary-port? p)) - ($oops who "~s is not a binary output port" p)) - (when ($port-flags-set? p (constant port-flag-compressed)) ($compressed-warning who p)) - (emit-header p (constant scheme-version) (constant machine-type-any)) - (fasl-one x p))) - - (define-who fasl-file - (lambda (in out) - (unless (string? in) ($oops who "~s is not a string" in)) - (unless (string? out) ($oops who "~s is not a string" out)) - (let ([ip ($open-file-input-port who in (file-options) - (buffer-mode block) (current-transcoder))] - [op ($open-file-output-port who out (file-options replace))]) - (on-reset - (begin - (close-input-port ip) - (delete-file out #f)) - (on-reset - (close-port op) - (emit-header op (constant scheme-version) (constant machine-type-any)) - (let fasl-loop () - (let ([x (read ip)]) - (unless (eof-object? x) - (fasl-one x op) - (fasl-loop))))) - (close-port op)) - (close-port ip))))) - -(define fasl-base-rtd - (lambda (x p) - (emit-header p (constant scheme-version) (constant machine-type-any)) - (let ([t (make-table)]) - (bld-graph x t #f really-bld-record) - (start p t (constant fasl-type-visit-revisit) (lambda (p) (wrf-graph x p t #f really-wrf-record)))))) - -($fasl-target (make-target bld-graph bld wrf start make-table wrf-graph fasl-base-rtd fasl-write fasl-file)) -) - -(let () - (define fasl-target - (lambda () - (let ([target ($fasl-target)]) - (assert target) - target))) - (set! $fasl-bld-graph (lambda (x t a? handler) ((target-fasl-bld-graph (fasl-target)) x t a? handler))) - (set! $fasl-enter (lambda (x t a?) ((target-fasl-enter (fasl-target)) x t a?))) - (set! $fasl-out (lambda (x p t a?) ((target-fasl-out (fasl-target)) x p t a?))) - (set! $fasl-start (lambda (p t situation proc) ((target-fasl-start (fasl-target)) p t situation proc))) - (set! $fasl-table (lambda () ((target-fasl-table (fasl-target))))) - (set! $fasl-wrf-graph (lambda (x p t a? handler) ((target-fasl-wrf-graph (fasl-target)) x p t a? handler))) - (set! $fasl-base-rtd (lambda (x p) ((target-fasl-base-rtd (fasl-target)) x p))) - (set! fasl-write (lambda (x p) ((target-fasl-write (fasl-target)) x p))) - (set! fasl-file (lambda (in out) ((target-fasl-file (fasl-target)) in out)))) - -(when ($unbound-object? (#%$top-level-value '$capture-fasl-target)) - (let ([ht (make-hashtable values =)]) - (set! $capture-fasl-target - (lambda (mt) - (hashtable-set! ht mt ($fasl-target)))) - (set-who! $with-fasl-target - (lambda (mt th) - (cond - [(hashtable-ref ht mt #f) => - (lambda (target) - (parameterize ([$fasl-target target]) - (th)))] - [else ($oops who "unrecognized machine type ~s" mt)]))))) - -($capture-fasl-target (constant machine-type)) -) diff --git a/ta6ob/s/fasl.ta6ob b/ta6ob/s/fasl.ta6ob deleted file mode 100644 index 4c318cc..0000000 Binary files a/ta6ob/s/fasl.ta6ob and /dev/null differ diff --git a/ta6ob/s/foreign.ss b/ta6ob/s/foreign.ss deleted file mode 100644 index d68c32e..0000000 --- a/ta6ob/s/foreign.ss +++ /dev/null @@ -1,73 +0,0 @@ -;;; foreign.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(let () - (define $foreign-address-name - (foreign-procedure "(cs)foreign_address_name" (void*) - string)) - - (define $remove-foreign-entry - (foreign-procedure "(cs)remove_foreign_entry" - (string) scheme-object)) - - (set! $foreign-entries - (foreign-procedure "(cs)foreign_entries" () - scheme-object)) - - (set! remove-foreign-entry - (lambda (entry) - (unless (string? entry) - ($oops 'remove-foreign-entry "~s is not a string" entry)) - (unless ($remove-foreign-entry entry) - ($oops 'remove-foreign-entry "no entry for ~s" entry)))) - - (let () - (define lookup - (foreign-procedure "(cs)lookup_foreign_entry" (string) - void*)) - (set-who! foreign-entry? - (lambda (str) - (unless (string? str) ($oops who "~s is not a string" str)) - (if (eqv? (lookup str) 0) #f #t))) - (set-who! foreign-entry - (lambda (str) - (unless (string? str) ($oops who "~s is not a string" str)) - (let ([x (lookup str)]) - (when (eqv? x 0) ($oops who "no entry for ~s" str)) - x)))) - - (set-who! foreign-address-name - (lambda (n) - (define void*? - (constant-case ptr-bits - [(32) $integer-32?] - [(64) $integer-64?])) - (unless (void*? n) ($oops who "~s is not a valid address" n)) - ($foreign-address-name n))) - - (set! load-shared-object - (if (foreign-entry? "(cs)load_shared_object") - (let () - (define lso - (foreign-procedure "(cs)load_shared_object" - (string) - void)) - (lambda (x) - (unless (or (string? x) (eq? x #f)) - ($oops 'load-shared-object "invalid path ~s" x)) - (lso x))) - (lambda args - ($oops 'load-shared-object "not supported")))) -) ;let diff --git a/ta6ob/s/foreign.ta6ob b/ta6ob/s/foreign.ta6ob deleted file mode 100644 index 2cb6d3e..0000000 Binary files a/ta6ob/s/foreign.ta6ob and /dev/null differ diff --git a/ta6ob/s/format.ss b/ta6ob/s/format.ss deleted file mode 100644 index be09796..0000000 --- a/ta6ob/s/format.ss +++ /dev/null @@ -1,1784 +0,0 @@ -;;; format.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -#| TODO: - * more tests - - tests of format with #f, #t, or port as first argument; test of printf - and fprintf, tests that exercise all paths of cp1in format handler - - verify complete coverage of code paths - - extract all tests from cltl2 - - more # and v parameter tests - - ~^ tests: - - need tests for outside abort, abort in indirect, nested {super-,}abort - in conditionals, nested {super-,}abort in case-conversion, etc. - - need tests with one parameter and two parameters - - ~* and ~:p tests for moving around loop args - - test float printing with Bob's set of floats - * use something better than string-append for constructing ~f and ~e output - * use more efficient dispatch, e.g., have case use binary search for fixnum - keys; or modify compiler to use jump tables for well-behaved case's - * look into not hardcoding float-base = 10 - * vparams adds substantial allocation overhead, probably because of the - compiler's handling of mvlet producers containing if expressions; fix - the compiler - * abstract out Chez Scheme specifics, like display-string, $list-length, - string ports, use of generic port -|# - -;;; missing directives -;;; pretty-printer controls (^_, ~:>, ~i, ~:t ~/name/) - -;;; known incompatibilities with Common Lisp -;;; : [print nil as ()] modifier ignored for ~a -;;; : [print nil as ()] modifier treated as "print-gensym #f" for ~s -;;; common lisp doesn't complain when there are unused arguments, -;;; may not complain when there are too few arguments. we always -;;; complain when there are too few and complain when we can determine -;;; statically that there are too many -;;; we insist on real argument for ~f, ~e, and ~g; common lisp is -;;; lax and sends off anything else to ~D. - -;;; other notes -;;; we always assume that format starts at the beginning of a line -;;; in support of ~&, ~t, and ~<...> - -(let () - ;;; configuration - - ;; check for too many args at parse time - (define static-too-many-args-check #t) - ;; check for too many args at parse time for indirects and loop bodies - (define indirect-too-many-args-check #f) - ;; check for too many args at run time. the check is always suppressed - ;; when we terminate a format or indirect format as the result of ~^ - (define dynamic-too-many-args-check #f) - - ;;; predicates used to check format parameters - (define nnfixnum? (lambda (x) (and (fixnum? x) (fx>= x 0)))) - (define true? (lambda (x) #t)) - (define pfixnum? (lambda (x) (and (fixnum? x) (fx> x 0)))) - (define radix? (lambda (x) (and (fixnum? x) (fx<= 2 x 36)))) - - ; we require nongenerative records because the compiler embeds parsed - ; format strings in object files. force cp1in-parse-format to return #f - ; to bootstrap after making changes to any of these records - (define-datatype (#{fmt cgos0c9ufi1rq-fd} (immutable directive)) - (#{newline cgos0c9ufi1rq-ez} n) - (#{fresh-line cgos0c9ufi1rq-fc} n) - (#{dup-char cgos0c9ufi1rq-fh} n c) - (#{display cgos0c9ufi1rq-fi} mincol colinc minpad pad-char left?) - (#{simple-display cgos0c9ufi1rq-et}) - (#{simple-write cgos0c9ufi1rq-es}) - (#{write cgos0c9ufi1rq-ei} mincol colinc minpad pad-char nogensym? left?) - (#{cwrite cgos0c9ufi1rq-fk} colon? at?) - (#{fwrite cgos0c9ufi1rq-fb} w d k oc pc sign?) - (#{ewrite cgos0c9ufi1rq-ff} w d ew k oc pc ec sign?) - (#{gwrite cgos0c9ufi1rq-e9} w d ew k oc pc ec sign?) - (#{$write cgos0c9ufi1rq-eg} d n w pc sign-before-pad? sign?) - (#{write-radix cgos0c9ufi1rq-eh} base w pc cc ci sign? commas?) - (#{plural cgos0c9ufi1rq-ey} back-up? y/ies?) - (#{fancy-radix cgos0c9ufi1rq-fe} colon? at?) - (#{indirect cgos0c9ufi1rq-e6} splice?) - (#{goto cgos0c9ufi1rq-fa} n reverse? absolute?) - (#{tabulate cgos0c9ufi1rq-ek} colnum colinc relative?) - (#{convert-case cgos0c9ufi1rq-fl} nested-cmd* colon? at?) - (#{conditional cgos0c9ufi1rq-fo} n cases default) - (#{conditional/at cgos0c9ufi1rq-fn} consequent) - (#{conditional/colon cgos0c9ufi1rq-fm} alternative consequent) - (#{justify cgos0c9ufi1rq-e1} mincol colinc minpad pad-char before? after? initial margin columns segments) - (#{abort cgos0c9ufi1rq-ft} n m super?) - (#{iteration cgos0c9ufi1rq-e2} body n sublists? use-remaining? at-least-once?) - (#{columntrack cgos0c9ufi1rq-fq} body) - ) - - ;;; parse string to list of strings, chars, and fmt records - (define parse - (lambda (who cntl) - (define column? #f) - (define-syntactic-monad state nargs cmd* stack) - (define-record-type frame - (fields (immutable directive) (immutable cmd*)) - (nongenerative)) - (define-record-type cvtcase-frame - (parent frame) - (fields (immutable colon?) (immutable at?)) - (nongenerative) - (sealed #t)) - (define-record-type conditional/at-frame - (parent frame) - (nongenerative) - (sealed #t)) - (define-record-type conditional/colon-frame - (parent frame) - (fields (mutable altern)) - (nongenerative) - (sealed #t) - (protocol - (lambda (make-new) - (lambda (directive cmd*) - ((make-new directive cmd*) #f))))) - (define-record-type conditional-frame - (parent frame) - (fields (immutable n) (mutable cases) (mutable default?)) - (nongenerative) - (sealed #t) - (protocol - (lambda (make-new) - (lambda (directive cmd* n) - ((make-new directive cmd*) n '() #f))))) - (define-record-type justify-frame - (parent frame) - (fields - (immutable mincol) - (immutable colinc) - (immutable minpad) - (immutable pc) - (immutable before?) - (immutable after?) - (mutable segments) - (mutable initial) - (mutable margin) - (mutable columns)) - (nongenerative) - (sealed #t) - (protocol - (lambda (make-new) - (lambda (directive cmd* mincol colinc minpad pc before? after?) - ((make-new directive cmd*) mincol colinc minpad pc before? after? '() #f #f #f))))) - (define-record-type iteration-frame - (parent frame) - (fields (immutable n) (immutable sublists?) (immutable use-remaining?)) - (nongenerative) - (sealed #t)) - (define incomplete-format-directive - (lambda (b i) - ($oops who "incomplete format directive ~s" - (substring cntl b i)))) - (define (bump x n) (and x n (fx+ x n))) - (unless (string? cntl) - ($oops who "~s is not a string" cntl)) - (let ([nmax (fx- (string-length cntl) 1)]) - (define char - (lambda (i) - (if (fx> i nmax) - #!eof - (string-ref cntl i)))) - (define sfinal - (state lambda () - (unless (null? stack) - ($oops who "unclosed directive ~a" (frame-directive (car stack)))) - (let ([cmd* (reverse cmd*)]) - (values (if column? (list (fmt-columntrack "" cmd*)) cmd*) nargs)))) - (define s0 - (state lambda (i) - (let ([c (char i)]) - (state-case c - [eof (state sfinal ())] - [(#\~) (state s3 () (fx+ i 1) i)] - [else (state s1 () (fx+ i 1) i c)])))) - (define s1 - (state lambda (i b c0) - (let ([c (char i)]) - (state-case c - [eof (state sfinal ([cmd* (cons c0 cmd*)]))] - [(#\~) (state s3 ([cmd* (cons c0 cmd*)]) (fx+ i 1) i)] - [else (state s2 () (fx+ i 1) b)])))) - (define s2 - (state lambda (i b) - (let ([c (char i)]) - (state-case c - [eof (state sfinal ([cmd* (cons (substring cntl b i) cmd*)]))] - [(#\~) (state s3 ([cmd* (cons (substring cntl b i) cmd*)]) (fx+ i 1) i)] - [else (state s2 () (fx+ i 1) b)])))) - (define s3 - (state lambda (i b) - (let ([c (char i)]) - (state-case c - [eof (incomplete-format-directive b i)] - [(#\~) (state s1 () (fx+ i 1) i #\~)] - [(#\- #\+) (state s4-sign () (fx+ i 1) b '() i)] - [((#\0 - #\9)) (state s4-digit () (fx+ i 1) b '() i)] - [(#\,) (state s4-comma () (fx+ i 1) b '(#f))] - [(#\') (state s4-quote () (fx+ i 1) b '())] - [(#\#) (state s4-after-param () (fx+ i 1) b '(hash))] - [(#\v) (state s4-after-param ([nargs (bump nargs 1)]) (fx+ i 1) b '(v))] - [else (state s5 () i b '())])))) - (define s4-sign - (state lambda (i b p* bp) - (let ([c (char i)]) - (state-case c - [eof (incomplete-format-directive b i)] - [((#\0 - #\9)) (state s4-digit () (fx+ i 1) b p* bp)] - [else (incomplete-format-directive b i)])))) - (define s4-quote - (state lambda (i b p*) - (let ([c (char i)]) - (state-case c - [eof (incomplete-format-directive b i)] - [else (state s4-after-param () (fx+ i 1) b (cons c p*))])))) - (define s4-after-param - (state lambda (i b p*) - (let ([c (char i)]) - (state-case c - [eof (incomplete-format-directive b i)] - [(#\,) (state s4-comma () (fx+ i 1) b p*)] - [else (state s5 () i b (reverse p*))])))) - (define s4-digit - (state lambda (i b p* bp) - (let ([c (char i)]) - (state-case c - [eof (incomplete-format-directive b i)] - [((#\0 - #\9)) (state s4-digit () (fx+ i 1) b p* bp)] - [(#\,) (state s4-comma () (fx+ i 1) b (cons (string->number (substring cntl bp i)) p*))] - [else (state s5 () i b (reverse (cons (string->number (substring cntl bp i)) p*)))])))) - (define s4-comma - (state lambda (i b p*) - (let ([c (char i)]) - (state-case c - [eof (incomplete-format-directive b i)] - [(#\- #\+) (state s4-sign () (fx+ i 1) b p* i)] - [((#\0 - #\9)) (state s4-digit () (fx+ i 1) b p* i)] - [(#\,) (state s4-comma () (fx+ i 1) b (cons #f p*))] - [(#\') (state s4-quote () (fx+ i 1) b p*)] - [(#\#) (state s4-after-param () (fx+ i 1) b (cons 'hash p*))] - [(#\v) (state s4-after-param ([nargs (bump nargs 1)]) (fx+ i 1) b (cons 'v p*))] - [else (state s5 () i b (reverse (cons #f p*)))])))) - (define s5 - (state lambda (i b p*) - (let ([c (char i)]) - (state-case c - [eof (incomplete-format-directive b i)] - [(#\:) (state s5-colon () (fx+ i 1) b p*)] - [(#\@) (state s5-at () (fx+ i 1) b p*)] - [else (state s6 () i b p* #f #f)])))) - (define s5-colon - (state lambda (i b p*) - (let ([c (char i)]) - (state-case c - [eof (incomplete-format-directive b i)] - [(#\@) (state s6 () (fx+ i 1) b p* #t #t)] - [else (state s6 () i b p* #t #f)])))) - (define s5-at - (state lambda (i b p*) - (let ([c (char i)]) - (state-case c - [eof (incomplete-format-directive b i)] - [(#\:) (state s6 () (fx+ i 1) b p* #t #t)] - [else (state s6 () i b p* #f #t)])))) - (define s6 - (state lambda (i b p* colon? at?) - (define skip-non-newline-white - (lambda (i) - (let ([c (char i)]) - (state-case c - [eof i] - [(#\space #\tab #\page #\return) - (skip-non-newline-white (fx+ i 1))] - [else i])))) - (let ([c (char i)]) - (define no-colon - (lambda () - (when colon? - ($oops who "~~~c directive has no : flag" c)))) - (define no-at - (lambda () - (when at? - ($oops who "~~~c directive has no @ flag" c)))) - (define too-many-parameters - (lambda () - ($oops who - "too many parameters in ~~~c directive ~s" - c (substring cntl b (fx+ i 1))))) - (define missing-parameter - (lambda (what) - ($oops who - "missing required ~s parameter in ~~~c directive ~s" - what c (substring cntl b (fx+ i 1))))) - (define invalid-parameter - (lambda (what arg) - ($oops who - "invalid ~s parameter ~a in ~~~c directive ~s" - what arg c (substring cntl b (fx+ i 1))))) - (define misplaced-directive - (lambda () - ($oops who "misplaced directive ~s" - (substring cntl b (fx+ i 1))))) - (define-syntax parameters - (lambda (x) - (define process-param - (lambda (t* param* body) - (if (null? param*) - body - (with-syntax ([body (process-param (cdr t*) (cdr param*) body)] - [t (car t*)]) - (syntax-case (car param*) (implicit) - [(implicit e) #'(let ([t e]) body)] - [(type? p) - #'(begin - (when (null? p*) (missing-parameter 'p)) - (let ([t (car p*)] [p* (cdr p*)]) - (when (not t) (missing-parameter 'p)) - (unless (or (type? t) (memq t '(hash v))) (invalid-parameter 'p t)) - body))] - [(type? p default) - #'(let ([proc (lambda (t p*) body)]) - (if (null? p*) - (proc 'default p*) - (let ([t (car p*)] [p* (cdr p*)]) - (if (not t) - (proc default p*) - (begin - (unless (or (type? t) (memq t '(hash v))) (invalid-parameter 'p t)) - (proc t p*))))))]))))) - (syntax-case x () - [(_ ([t param] ...) e1 e2 ...) - (process-param - #'(t ...) - #'(param ...) - #'(begin - (unless (null? p*) (too-many-parameters)) - (let () e1 e2 ...)))]))) - (define-syntax directive - (lambda (x) - (define construct-name - (lambda (template-identifier . args) - (datum->syntax - template-identifier - (string->symbol - (apply string-append - (map (lambda (x) - (if (string? x) - x - (symbol->string (syntax->datum x)))) - args)))))) - (syntax-case x () - [(k (d param ...) n) - (with-syntax ([(t ...) (generate-temporaries #'(param ...))] - [fmt-d (construct-name #'d "fmt-" #'d)]) - (with-implicit (k state cmd* nargs) - #'(parameters ([t param] ...) - (state s0 - ([cmd* (cons (fmt-d (substring cntl b (fx+ i 1)) t ...) cmd*)] - [nargs (bump nargs n)]) - (fx+ i 1)))))]))) - (define-syntax parse-radix - (syntax-rules () - [(_ base) - (directive - (write-radix [implicit base] - [nnfixnum? w #f] - [char? pad-char #\space] - [char? comma-char #\,] - [pfixnum? comma-interval 3] - [implicit at?] - [implicit colon?]) - 1)])) - (state-case c - [eof (incomplete-format-directive b i)] - [(#\% #\n #\N) - (no-at) - (no-colon) - (if (or (null? p*) (equal? p* '(1))) - (state s0 ([cmd* (cons #\newline cmd*)]) (fx+ i 1)) - (directive (dup-char [nnfixnum? n 1] [implicit #\newline]) 0))] - [(#\&) - (no-at) - (no-colon) - (directive (fresh-line [nnfixnum? n 1]) 0)] - [(#\a #\A) - (no-colon) - (if (null? p*) - (directive - (simple-display) - 1) - (directive - (display [nnfixnum? mincol 0] - [pfixnum? colinc 1] - [nnfixnum? minpad 0] - [char? pad-char #\space] - [implicit at?]) - 1))] - [(#\s #\S #\w #\W) - (if (and (null? p*) (not colon?)) - (directive - (simple-write) - 1) - (directive - (write [nnfixnum? mincol 0] - [pfixnum? colinc 1] - [nnfixnum? minpad 0] - [char? pad-char #\space] - [implicit colon?] - [implicit at?]) - 1))] - [(#\f #\F) - (no-colon) - (directive - (fwrite [nnfixnum? w #f] - [nnfixnum? d #f] - [fixnum? k 0] - [char? overflow-char #f] - [char? pad-char #\space] - [implicit at?]) - 1)] - [(#\e #\E) - (no-colon) - (directive - (ewrite [nnfixnum? w #f] - [nnfixnum? d #f] - [pfixnum? e #f] - [fixnum? k 1] - [char? overflow-char #f] - [char? pad-char #\space] - [char? exponent-char #\e] - [implicit at?]) - 1)] - [(#\g #\G) - (no-colon) - (directive - (gwrite [nnfixnum? w #f] - [nnfixnum? d #f] - [pfixnum? e #f] - [fixnum? k 1] ; assumption - [char? overflow-char #f] - [char? pad-char #\space] - [char? exponent-char #\e] - [implicit at?]) - 1)] - [(#\$) - (directive - ($write [nnfixnum? d 2] - [nnfixnum? n 1] - [nnfixnum? w 0] - [char? pad-char #\space] - [implicit colon?] - [implicit at?]) - 1)] - [(#\c #\C) - (directive - (cwrite [implicit colon?] [implicit at?]) - 1)] - [(#\b #\B) (parse-radix 2)] - [(#\o #\O) (parse-radix 8)] - [(#\d #\D) (parse-radix 10)] - [(#\x #\X) (parse-radix 16)] - [(#\r #\R) - (if (null? p*) - (directive - (fancy-radix [implicit colon?] [implicit at?]) - 1) - (directive - (write-radix [radix? n 10] - [nnfixnum? w #f] - [char? pad-char #\space] - [char? comma-char #\,] - [pfixnum? comma-interval 3] - [implicit at?] - [implicit colon?]) - 1))] - [(#\p #\P) - (directive - (plural [implicit colon?] [implicit at?]) - (if colon? 0 1))] - [(#\t #\T) - (no-colon) - (set! column? #t) - (directive - (tabulate [nnfixnum? colnum 1] - [nnfixnum? colinc 1] - [implicit at?]) - 0)] - [(#\?) - (no-colon) - (set! column? #t) - (directive - (indirect [implicit at?]) - (if at? #f 2))] - [(#\*) - (when (and colon? at?) - ($oops who - "@ and : modifiers are mutually exclusive for format directive ~~~c" - c)) - (directive - (goto [nnfixnum? n #f] [implicit colon?] [implicit at?]) - #f)] - [(#\( #|)|#) - (parameters () - (state s0 - ([stack (cons (make-cvtcase-frame (substring cntl b (fx+ i 1)) cmd* colon? at?) stack)] - [cmd* '()]) - (fx+ i 1)))] - [(#|(|# #\)) - (no-at) - (no-colon) - (let ([x (and (not (null? stack)) (car stack))]) - (unless (cvtcase-frame? x) (misplaced-directive)) - (let ([nested-cmd* (reverse cmd*)]) - (let ([stack (cdr stack)] [cmd* (frame-cmd* x)]) - (directive - (convert-case [implicit nested-cmd*] - [implicit (cvtcase-frame-colon? x)] - [implicit (cvtcase-frame-at? x)]) - 0))))] - [(#\;) - (no-at) - (let ([x (and (not (null? stack)) (car stack))]) - (cond - [(and (conditional/colon-frame? x) - (not colon?) - (not (conditional/colon-frame-altern x))) - (parameters () - (conditional/colon-frame-altern-set! x (reverse cmd*))) - (state s0 ([cmd* '()]) (fx+ i 1))] - [(and (conditional-frame? x) (not (conditional-frame-default? x))) - (parameters () - (when colon? (conditional-frame-default?-set! x #t)) - (conditional-frame-cases-set! x - (cons (reverse cmd*) (conditional-frame-cases x)))) - (state s0 ([cmd* '()]) (fx+ i 1))] - [(and (justify-frame? x) - (or (not colon?) - (and (not (justify-frame-initial x)) - (null? (justify-frame-segments x))))) - (if colon? - (parameters ([margin (nnfixnum? n 0)] - [cols (nnfixnum? lw 72)]) - (set! column? #t) - (justify-frame-initial-set! x (reverse cmd*)) - (justify-frame-margin-set! x margin) - (justify-frame-columns-set! x cols)) - (parameters () - (justify-frame-segments-set! x - (cons (reverse cmd*) (justify-frame-segments x))))) - (state s0 ([cmd* '()]) (fx+ i 1))] - [else (misplaced-directive)]))] - [(#\^) - (no-at) - (directive - (abort [true? n #f] [true? m #f] [implicit colon?]) - #f)] - [(#\{ #|}|#) - (when (null? cmd*) (set! column? #t)) - (parameters ([n (nnfixnum? n #f)]) - (state s0 - ([stack (cons (make-iteration-frame (substring cntl b (fx+ i 1)) cmd* n colon? at?) stack)] - [cmd* '()]) - (fx+ i 1)))] - [(#|{|# #\}) - (no-at) - (let ([x (and (not (null? stack)) (car stack))]) - (unless (iteration-frame? x) (misplaced-directive)) - (let ([nested-cmd* (reverse cmd*)]) - (let ([stack (cdr stack)] [cmd* (frame-cmd* x)]) - (directive - (iteration [implicit nested-cmd*] - [implicit (iteration-frame-n x)] - [implicit (iteration-frame-sublists? x)] - [implicit (iteration-frame-use-remaining? x)] - [implicit colon?]) - #f))))] - [(#\[ #|]|#) - (if at? - (if colon? - ($oops who "@ and : modifiers are mutually exclusive for format directive ~~~c" c) - (parameters () - (state s0 - ([stack (cons (make-conditional/at-frame (substring cntl b (fx+ i 1)) cmd*) stack)] - [cmd* '()]) - (fx+ i 1)))) - (if colon? - (parameters () - (state s0 - ([stack (cons (make-conditional/colon-frame (substring cntl b (fx+ i 1)) cmd*) stack)] - [cmd* '()]) - (fx+ i 1))) - (parameters ([n (nnfixnum? n #f)]) - (state s0 - ([stack (cons (make-conditional-frame (substring cntl b (fx+ i 1)) cmd* n) stack)] - [cmd* '()]) - (fx+ i 1)))))] - [(#|[|# #\]) - (no-at) - (no-colon) - (let ([x (and (not (null? stack)) (car stack))]) - (let ([nested-cmd* (reverse cmd*)]) - (cond - [(conditional/at-frame? x) - (let ([stack (cdr stack)] [cmd* (frame-cmd* x)]) - (directive - (conditional/at [implicit nested-cmd*]) - #f))] - [(conditional/colon-frame? x) - (let ([altern (conditional/colon-frame-altern x)]) - (unless altern - ($oops who "no ~~; found within ~a...~~]" (frame-directive (car stack)))) - (let ([stack (cdr stack)] [cmd* (frame-cmd* x)]) - (directive - (conditional/colon [implicit altern] - [implicit nested-cmd*]) - #f)))] - [(conditional-frame? x) - (let ([stack (cdr stack)] [cmd* (frame-cmd* x)]) - (let ([n (conditional-frame-n x)]) - (if (conditional-frame-default? x) - (directive - (conditional [implicit n] - [implicit (list->vector (reverse (conditional-frame-cases x)))] - [implicit nested-cmd*]) - #f) - (directive - (conditional [implicit n] - [implicit (list->vector (reverse (cons nested-cmd* (conditional-frame-cases x))))] - [implicit '()]) - #f))))] - [else (misplaced-directive)])))] - [(#\<) - (parameters ([mincol (nnfixnum? mincol 0)] - [colinc (nnfixnum? colinc 1)] - [minpad (nnfixnum? minpad 0)] - [pc (char? pad-char #\space)]) - (state s0 - ([stack (cons (make-justify-frame (substring cntl b (fx+ i 1)) cmd* mincol colinc minpad pc colon? at?) stack)] - [cmd* '()]) - (fx+ i 1)))] - [(#\>) - (no-at) - (let ([x (and (not (null? stack)) (car stack))]) - (unless (justify-frame? x) (misplaced-directive)) - (let ([nested-cmd* (reverse cmd*)]) - (let ([stack (cdr stack)] [cmd* (frame-cmd* x)]) - (directive - (justify [implicit (justify-frame-mincol x)] - [implicit (justify-frame-colinc x)] - [implicit (justify-frame-minpad x)] - [implicit (justify-frame-pc x)] - [implicit (justify-frame-before? x)] - [implicit (justify-frame-after? x)] - [implicit (justify-frame-initial x)] - [implicit (justify-frame-margin x)] - [implicit (justify-frame-columns x)] - [implicit (reverse (cons nested-cmd* (justify-frame-segments x)))]) - 0))))] - [(#\~) - (no-at) - (no-colon) - (if (or (null? p*) (equal? p* '(1))) - (state s0 ([cmd* (cons #\~ cmd*)]) (fx+ i 1)) - (directive (dup-char [nnfixnum? n 1] [implicit #\~]) 0))] - [(#\|) - (no-at) - (no-colon) - (if (or (null? p*) (equal? p* '(1))) - (state s0 ([cmd* (cons #\page cmd*)]) (fx+ i 1)) - (directive (dup-char [nnfixnum? n 1] [implicit #\page]) 0))] - [(#\return) ; ~\r\n is treated like ~\n - (if (eq? (char (fx+ i 1)) #\newline) - (state s6 () (fx+ i 1) b p* colon? at?) - ($oops who "unrecognized directive ~~~:c" c))] - [(#\newline) - (parameters () - (when (and colon? at?) - ($oops who - "@ and : modifiers are mutually exclusive for format directive ~~~c" - c)) - (cond - [colon? (state s0 () (fx+ i 1))] - [at? (state s0 ([cmd* (cons c cmd*)]) (skip-non-newline-white (fx+ i 1)))] - [else (state s0 () (skip-non-newline-white (fx+ i 1)))]))] - [else ($oops who "unrecognized directive ~~~:c" c)])))) - (state s0 ([nargs 0] [cmd* '()] [stack '()]) 0)))) - - ;;; squash together adjacent strings and characters - (define squash - (lambda (ls) - (define insert-string! - (lambda (s1 i1 s2) - (let ([n2 (string-length s2)]) - (do ([i1 i1 (fx+ i1 1)] [i2 0 (fx+ i2 1)]) - ((fx= i2 n2)) - (string-set! s1 i1 (string-ref s2 i2)))))) - (define squash0 - (lambda (ls) - (let ([a (car ls)] [d (cdr ls)]) - (if (null? d) - ls - (if (string? a) - (let-values ([(s d) (squash1 d (string-length a))]) - (if (string? s) - (begin (insert-string! s 0 a) (cons s d)) - (cons a d))) - (if (char? a) - (let-values ([(s d) (squash1 d 1)]) - (if (string? s) - (begin (string-set! s 0 a) (cons s d)) - (cons a d))) - (cons a (squash0 d)))))))) - (define squash1 - (lambda (ls n) - (if (null? ls) - (values n ls) - (let ([a (car ls)] [d (cdr ls)]) - (if (string? a) - (let-values ([(s d) (squash1 d (fx+ n (string-length a)))]) - (let ([s (if (string? s) s (make-string s))]) - (insert-string! s n a) - (values s d))) - (if (char? a) - (let-values ([(s d) (squash1 d (fx+ n 1))]) - (let ([s (if (string? s) s (make-string s))]) - (string-set! s n a) - (values s d))) - (values n (if (null? d) ls (cons a (squash0 d)))))))))) - (if (null? ls) '() (squash0 ls)))) - - ;;; convert simple formats to expressions. returns #f for other inputs. - (define (make-fmt->expr build-quote build-seq build-primcall) - (lambda (src sexpr cmd* op arg*) - (define-syntax make-seq - (syntax-rules () - [(_ ?a ?d) - (let ([d ?d]) - (and d - (let ([a ?a]) - (if (null? d) a (build-seq a d)))))])) - (define-syntax make-call - (syntax-rules () - [(_ src proc arg ...) - (build-primcall src sexpr 'proc (list arg ...))])) - (if (null? cmd*) - (build-quote (void)) - (let f ([cmd* cmd*] [arg* arg*] [src src]) - (if (null? cmd*) - '() - (let ([cmd (car cmd*)] [cmd* (cdr cmd*)]) - (cond - [(string? cmd) - (make-seq (make-call src display-string (build-quote cmd) op) - (f cmd* arg* #f))] - [(char? cmd) - (make-seq (make-call src write-char (build-quote cmd) op) - (f cmd* arg* #f))] - [(fmt? cmd) - (and (not (null? arg*)) - (fmt-case cmd - [simple-display () - (make-seq (make-call src display (car arg*) op) - (f cmd* (cdr arg*) #f))] - [simple-write () - (make-seq (make-call src write (car arg*) op) - (f cmd* (cdr arg*) #f))] - [cwrite (colon? at?) - (and (not colon?) - (not at?) - (make-seq (make-call src write-char (car arg*) op) - (f cmd* (cdr arg*) #f)))] - [else #f]))] - [else ($oops 'fmt->expr "internal error: ~s" cmd)]))))))) - - ;;; perform formatting operation from parsed string (cmd*) - (define dofmt - (lambda (who fmt-op cntl cmd* arg*) - (define flonum->digits #%$flonum->digits) - (define flonum-sign #%$flonum-sign) - (define (exact-integer? x) (or (fixnum? x) (bignum? x))) - (define float-base 10) ; hardcoding base 10 for now - (define fd->string - (lambda (ls d n sign?) - (define flonum-digit->char - (lambda (n) - (string-ref - "#00123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - (fx+ n 2)))) - (let ([s (car ls)] [e (cadr ls)] [ls (cddr ls)]) - (let ([op (open-output-string)]) - (if (eqv? s -1) - (write-char #\- op) - (when sign? (write-char #\+ op))) - (cond - [(fx< e 0) - (when (fx> n 0) (display (make-string n #\0) op)) - (write-char #\. op) - (if (and (not d) (fx= (car ls) -1)) ; some flavor of 0.0 - (write-char #\0 op) - (do ([e e (fx+ e 1)] [d d (and d (fx- d 1))]) - ((or (fx>= e -1) (and d (fx= d 0))) - (do ([ls ls (cdr ls)] [d d (and d (fx- d 1))]) - ((if d (fx= d 0) (fx< (car ls) 0))) - (write-char (flonum-digit->char (car ls)) op))) - (write-char #\0 op)))] - [(fx= (car ls) -1) ; some flavor of 0.0 - (display (make-string (if (and (fx= n 0) (eqv? d 0)) 1 n) #\0) op) - (write-char #\. op) - (display (make-string (or d 1) #\0) op)] - [else - (let ([n (fx- n e 1)]) - (when (fx> n 0) (display (make-string n #\0) op))) - (write-char (flonum-digit->char (car ls)) op) - (do ([ls (cdr ls) (cdr ls)] [e e (fx- e 1)]) - ((fx= e 0) - (write-char #\. op) - (if (and (not d) (fx< (car ls) 0)) - (write-char (flonum-digit->char (car ls)) op) - (do ([ls ls (cdr ls)] [d d (and d (fx- d 1))]) - ((if d (fx= d 0) (fx< (car ls) 0))) - (write-char (flonum-digit->char (car ls)) op)))) - (write-char (flonum-digit->char (car ls)) op))]) - (get-output-string op))))) - (define string-upcase! - (lambda (s) - (let ([n (string-length s)]) - (do ([i 0 (fx+ i 1)]) - ((fx= i n)) - (string-set! s i (char-upcase (string-ref s i))))))) - (define string-downcase! - (lambda (s) - (let ([n (string-length s)]) - (do ([i 0 (fx+ i 1)]) - ((fx= i n)) - (string-set! s i (char-downcase (string-ref s i))))))) - (define string-capitalize! - (lambda (s) - (let ([n (string-length s)]) - (define interword - (lambda (i) - (unless (fx= i n) - (let ([c (string-ref s i)]) - (if (or (char-alphabetic? c) (char-numeric? c)) - (begin - (string-set! s i (char-upcase c)) - (intraword (fx+ i 1))) - (interword (fx+ i 1))))))) - (define intraword - (lambda (i) - (unless (fx= i n) - (let ([c (string-ref s i)]) - (if (or (char-alphabetic? c) (char-numeric? c)) - (begin - (string-set! s i (char-downcase c)) - (intraword (fx+ i 1))) - (interword (fx+ i 1))))))) - (interword 0)))) - (define string-capitalize-first! - (lambda (s) - (let ([n (string-length s)]) - (unless (fx= (string-length s) 0) - (string-set! s 0 (char-upcase (string-ref s 0))) - (do ([i 1 (fx+ i 1)]) - ((fx= i n)) - (string-set! s i (char-downcase (string-ref s i)))))))) - (define-syntax pad - (syntax-rules () - [(_ mincol colinc minpad pad-char left? op expr) - (if (and (fx= mincol 0) (fx= minpad 0)) - expr - (let ([s (let ([op (open-output-string)]) - expr - (get-output-string op))]) - (unless left? (display s op)) - (let ([n (let ([n (fxmax 0 (fx- mincol minpad (string-length s)))]) - (fx+ minpad - (fx* (fxquotient - (fx+ n (fx- colinc 1)) - colinc) - colinc)))]) - (unless (fx= n 0) - (display (make-string n pad-char) op))) - (when left? (display s op))))])) - (define (padnum w oc pc op s) - (if (not w) - (display s op) - (let ([n (string-length s)]) - (cond - [(fx> n w) - (if oc - (display (make-string w oc) op) - (display s op))] - [else - (when (fx< n w) (display (make-string (fx- w n) pc) op)) - (display s op)])))) - (define (write-old-roman x op) - (if (<= 1 x 4999) - (let f ([x x] [a '(1000 . #\M)] [ls '((500 . #\D) (100 . #\C) (50 . #\L) (10 . #\X) (5 . #\V) (1 . #\I))]) - (if (>= x (car a)) - (begin (write-char (cdr a) op) (f (- x (car a)) a ls)) - (unless (null? ls) (f x (car ls) (cdr ls))))) - (fprintf op "~d" x))) - (define (write-roman x op) - (if (<= 1 x 3999) - (let f ([x x] [a '(1000 . "M")] [ls '((900 . "CM") (500 . "D") (400 . "CD") (100 . "C") (90 . "XC") (50 . "L") (40 . "XL") (10 . "X") (9 . "IX") (5 . "V") (4 . "IV") (1 . "I"))]) - (if (>= x (car a)) - (begin (display (cdr a) op) (f (- x (car a)) a ls)) - (unless (null? ls) (f x (car ls) (cdr ls))))) - (fprintf op "~d" x))) - (module (write-ordinal write-cardinal) - (define (f100 x op) - (cond - [(>= x 100) - (f10 (quotient x 100) op) - (display " hundred" op) - (let ([x (remainder x 100)]) - (unless (= x 0) - (display " " op) - (f10 x op)))] - [else (f10 x op)])) - (define (f10 x op) - (cond - [(>= x 20) - (display (vector-ref v20 (quotient x 10)) op) - (let ([x (remainder x 10)]) - (unless (= x 0) - (display "-" op) - (f10 x op)))] - [else (display (vector-ref v0 x) op)])) - (define (f1000000 x op) - (cond - [(>= x 1000000) - (f100 (quotient x 1000000) op) - (display " million" op) - (let ([x (remainder x 1000000)]) - (unless (= x 0) - (display " " op) - (f1000 x op)))] - [else (f1000 x op)])) - (define (f1000 x op) - (cond - [(<= 1100 x 1999) (f100 x op)] - [(>= x 1000) - (f100 (quotient x 1000) op) - (display " thousand" op) - (let ([x (remainder x 1000)]) - (unless (= x 0) - (display " " op) - (f100 x op)))] - [else (f100 x op)])) - (define (*f1000000 x op) - (cond - [(>= x 1000000) - (f100 (quotient x 1000000) op) - (let ([x (remainder x 1000000)]) - (if (= x 0) - (display " millionth" op) - (begin - (display " million " op) - (*f1000 x op))))] - [else (*f1000 x op)])) - (define (*f1000 x op) - (cond - [(<= 1100 x 1999) (*f100 x op)] - [(>= x 1000) - (f100 (quotient x 1000) op) - (let ([x (remainder x 1000)]) - (if (= x 0) - (display " thousandth" op) - (begin - (display " thousand " op) - (*f100 x op))))] - [else (*f100 x op)])) - (define (*f100 x op) - (cond - [(>= x 100) - (f10 (quotient x 100) op) - (let ([x (remainder x 100)]) - (if (= x 0) - (display " hundredth" op) - (begin - (display " hundred " op) - (*f10 x op))))] - [else (*f10 x op)])) - (define (*f10 x op) - (cond - [(>= x 20) - (let ([q (quotient x 10)] [x (remainder x 10)]) - (if (= x 0) - (display (vector-ref *v20 q) op) - (begin - (display (vector-ref v20 q) op) - (display "-" op) - (*f10 x op))))] - [else (display (vector-ref *v0 x) op)])) - (define v20 '#(#f #f twenty thirty forty fifty sixty seventy eighty ninety)) - (define v0 '#(zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen)) - (define *v20 '#(#f #f twentieth thirtieth fortieth fiftieth sixtieth seventieth eightieth ninetieth)) - (define *v0 '#(zeroth first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth thirteenth fourteenth fifteenth sixteenth seventeenth eighteenth nineteenth)) - (define (write-ordinal x op) - (if (<= -999999999 x +999999999) - (if (< x 0) - (begin (display "minus " op) (*f1000000 (- x) op)) - (*f1000000 x op)) - (fprintf op "~:d~a" x - (let ([n (remainder (abs x) 100)]) - (if (<= 11 n 19) - "th" - (case (remainder n 10) - [(1) "st"] - [(2) "nd"] - [(3) "rd"] - [else "th"])))))) - (define (write-cardinal x op) - (if (<= -999999999 x +999999999) - (if (< x 0) - (begin (display "minus " op) (f1000000 (- x) op)) - (f1000000 x op)) - (fprintf op "~:d" x)))) - (define cheap-scale - (lambda (ls k) - `(,(car ls) ,(fx+ (cadr ls) k) ,@(cddr ls)))) - (define (do-fwrite-d op x w d k oc pc sign? ls) - (let ([ls (cheap-scale ls k)]) - (padnum w oc pc op - (fd->string ls d - (if (and w (fx< (cadr ls) 0) (fx> (fx+ (if (or sign? (fx= (car ls) -1)) 3 2) d) w)) 0 1) - sign?)))) - (define (do-fwrite op x w d k oc pc sign?) - (cond - [d (do-fwrite-d op x w d k oc pc sign? - (flonum->digits x float-base 'absolute (fx- (fx+ k d))))] - [w (padnum w oc pc op - (let ([ls (cheap-scale (flonum->digits x float-base 'normal 0) k)]) - (let ([s (car ls)] [e (cadr ls)]) - (if (fx< e 0) - (let ([n (fx+ w e (if (or sign? (fx< s 0)) -1 0))]) - (let f ([ds (cddr ls)] [i n]) - (if (fx<= i 0) - (let ([ls (cheap-scale (flonum->digits x float-base 'absolute (fx- (fx+ k (fxmax (fx- n e 1) 1)))) k)]) - (if (fx= (caddr ls) -1) ; rounded to zero? - (if (fx< s 0) - (if (fx< w 4) "-.0" "-0.0") - (if sign? - (if (fx< w 4) "+.0" "+0.0") - (if (fx< w 3) ".0" "0.0"))) - (fd->string ls #f 0 sign?))) - (if (fx= (cadr ds) -1) ; can't be -2 w/normal - (fd->string ls #f (if (fx= i 1) 0 1) sign?) - (f (cdr ds) (fx- i 1)))))) - (let ([n (fx+ w (if (or sign? (fx< s 0)) -2 -1))]) - (let g ([e e] [ds (cddr ls)] [i n]) - (if (fx< i 0) - (if (fx< e -1) - (fd->string (cheap-scale (flonum->digits x float-base 'absolute (fx- (fx+ e 2) k)) k) (and (fx= e -2) 0) 1 sign?) - (fd->string (cheap-scale (flonum->digits x float-base 'absolute (fx- k)) k) 0 1 sign?)) - (if (fx= (car ds) -1) ; can't be -2 w/normal - (if (fx< e 0) - (fd->string ls (and (fx= e -1) (fx= i 0) 0) 1 sign?) - (if (fx< e (fx- i 1)) - (fd->string (cheap-scale (flonum->digits x float-base 'absolute (fx- k (fx- i e))) k) #f 1 sign?) - (fd->string (cheap-scale (flonum->digits x float-base 'absolute (fx- k)) k) 0 1 sign?))) - (g (fx- e 1) (cdr ds) (fx- i 1))))))))))] - [else (padnum w oc pc op - (fd->string - (let ([ls (cheap-scale (flonum->digits x float-base 'normal 0) k)]) - (let f ([e (cadr ls)] [ds (cddr ls)]) - (if (fx= (car ds) -1) ; w/normal, can't be -2 - (cheap-scale (flonum->digits x float-base 'absolute (fx- -1 k)) k) - (if (fx< e 0) - ls - (f (fx- e 1) (cdr ds)))))) - d 1 sign?))])) - (define (do-ewrite op x w d ew k oc pc ec sign?) - (cond - [(fl= x 0.0) - (padnum w oc pc op - (let ([ss (if (fx= (flonum-sign x) 1) "-" (if sign? "+" ""))] - [es (if ew (make-string ew #\0) "0")]) - (let ([d (and d (if (fx<= k 0) d (fx+ (fx- d k) 1)))]) - (if (and w (fx> (fx+ (string-length ss) 4 (or d 1) (string-length es)) w)) - (if (if d (fx= d 0) (fx> k 0)) - (string-append ss "0." (string ec) "+" es) - (string-append ss "." (if d (make-string d #\0) "0") (string ec) "+" es)) - (string-append ss "0." (if d (make-string d #\0) "0") (string ec) "+" es)))))] - [d (let ([ls (flonum->digits x float-base 'relative (if (fx<= k 0) (fx- (fx+ d k)) (fx- -1 d)))]) - (let* ([e (fx- (cadr ls) (fx- k 1))] - [es (number->string (fxabs e))] - [esl (string-length es)]) - (if (and w oc ew (fx> esl ew)) - (display (make-string w oc) op) - (let ([ew (if ew (fxmax ew esl) esl)]) - (padnum w oc pc op - (string-append - (fd->string - `(,(car ls) ,(fx- k 1) ,@(cddr ls)) - (if (fx<= k 0) d (fx+ (fx- d k) 1)) - (if (and w (fx> (fx+ (if (or sign? (fx= (car ls) -1)) 5 4) ew d) w)) 0 1) - sign?) - (if ec (string ec) "e") - (if (fx< e 0) "-" "+") - (make-string (fx- ew esl) #\0) - es))))))] - [w (let ([sign? (or sign? (fx= (flonum-sign x) 1))]) - (let loop ([ew-guess (or ew 1)]) - (let d ([d (fxmax (fx- w (if sign? 5 4) ew-guess) - (if (fx= k 0) 0 (if (fx< k 0) (fx- 1 k) (fx- k 1))))]) - (let ([ls (flonum->digits x float-base 'relative (if (fx<= k 0) (fx- (fx+ d k)) (fx- -1 d)))]) - (let* ([e (fx- (cadr ls) (fx- k 1))] - [es (number->string (fxabs e))] - [esl (string-length es)]) - (if (fx> esl ew-guess) - (if (and oc ew) - (display (make-string w oc) op) - (loop esl)) - (let ([ew (if ew (fxmax ew esl) esl)]) - (padnum w oc pc op - (string-append - (fd->string - `(,(car ls) ,(fx- k 1) ,@(cddr ls)) - (and (fx= (fx- k d) 1) (fx>= (fx+ (if sign? 5 4) ew d) w) 0) - (if (fx> (fx+ (if sign? 5 4) ew d) w) 0 1) - sign?) - (if ec (string ec) "e") - (if (fx< e 0) "-" "+") - (make-string (fx- ew esl) #\0) - es)))))))))] - [else (display - (let ([ls (flonum->digits x float-base 'normal 0)]) - (let ([e (fx- (cadr ls) (fx- k 1))]) - (string-append - (fd->string `(,(car ls) ,(fx- k 1) ,@(cddr ls)) #f 1 sign?) - (if ec (string ec) "e") - (if (fx< e 0) "-" "+") - (let ([op (open-output-string)]) - (padnum ew #f #\0 op (number->string (fxabs e))) - (get-output-string op))))) - op)])) - (define invalid-parameter - (lambda (who cmd what p) - ($oops who - "invalid ~s parameter ~a in directive ~s" - what p (fmt-directive cmd)))) - (define (outer-loop cmd* arg* op cntl all-arg* super-arg* ct? succ fail) - (define tostr - (lambda (cmd* arg* super-arg* succ fail) - (let ([op (open-output-string)]) - (let ([xop (if ct? (make-format-port op) op)]) - (outer-loop cmd* arg* xop cntl all-arg* super-arg* ct? - (lambda (arg*) - (when ct? (close-output-port xop)) - (succ (get-output-string op) arg*)) - (lambda (arg* super?) - (when ct? (close-output-port xop)) - (fail (get-output-string op) arg* super?))))))) - (define next - (lambda (arg*) - (when (null? arg*) - ($oops who "too few arguments for control string ~s" cntl)) - (car arg*))) - (let loop ([cmd* cmd*] [arg* arg*]) - (if (null? cmd*) - (succ arg*) - (let ([cmd (car cmd*)]) - (define-syntax vparams - (lambda (x) - (define process-param - (lambda (arg* t* param* body) - (if (null? param*) - body - (with-syntax ([body (process-param arg* (cdr t*) (cdr param*) body)] [arg* arg*] [t (car t*)]) - (syntax-case (car param*) () - [(type? p) - #'(let-values ([(t arg*) - (cond - [(eq? t 'v) (let ([t (next arg*)]) - (unless (type? t) (invalid-parameter who cmd 'p t)) - (values t (cdr arg*)))] - [(eq? t 'hash) (let ([t (length arg*)]) - (unless (type? t) (invalid-parameter who cmd 'p t)) - (values t arg*))] - [else (values t arg*)])]) - body)]))))) - (syntax-case x () - [(_ arg* ([t param] ...) e1 e2 ...) - (process-param - #'arg* - #'(t ...) - #'(param ...) - #'(let () e1 e2 ...))]))) - (cond - [(string? cmd) (display-string cmd op) (loop (cdr cmd*) arg*)] - [(char? cmd) (write-char cmd op) (loop (cdr cmd*) arg*)] - [(fmt? cmd) - (fmt-case cmd - [simple-display () - (display (next arg*) op) - (loop (cdr cmd*) (cdr arg*))] - [simple-write () - (write (next arg*) op) - (loop (cdr cmd*) (cdr arg*))] - [fresh-line (n) - (vparams arg* ([n (nnfixnum? n)]) - (when (fx> n 0) - (fresh-line op) - (when (fx> n 1) - (display (make-string (fx- n 1) #\newline) op))) - (loop (cdr cmd*) arg*))] - [display (mincol colinc minpad pad-char left?) - (vparams arg* ([mincol (nnfixnum? mincol)] - [colinc (pfixnum? colinc)] - [minpad (nnfixnum? minpad)] - [pad-char (char? pad-char)]) - (pad mincol colinc minpad pad-char left? op - (display (next arg*) op)) - (loop (cdr cmd*) (cdr arg*)))] - [write (mincol colinc minpad pad-char nogensym? left?) - (vparams arg* ([mincol (nnfixnum? mincol)] - [colinc (pfixnum? colinc)] - [minpad (nnfixnum? minpad)] - [pad-char (char? pad-char)]) - (pad mincol colinc minpad pad-char left? op - (if nogensym? - (parameterize ([print-gensym #f]) - (write (next arg*) op)) - (write (next arg*) op))) - (loop (cdr cmd*) (cdr arg*)))] - [cwrite (colon? at?) - (let ([c (next arg*)]) - (unless (char? c) - ($oops who "expected character for ~~c, received ~s" c)) - (if colon? - (let ([x (char-name c)]) - (if x - (begin - (write-char #\< op) - (display x op) - (write-char #\> op)) - (let ([n (char->integer c)]) - (if (fx< n #x20) - (begin - (write-char #\^ op) - (write-char (integer->char (fx+ n #x40)) op)) - (write-char c op))))) - (if at? - (write c op) - (write-char c op)))) - (loop (cdr cmd*) (cdr arg*))] - [fwrite (w d k oc pc sign?) - (vparams arg* ([w (nnfixnum? w)] - [d (nnfixnum? d)] - [k (fixnum? k)] - [oc (char? overflow-char)] - [pc (char? pad-char)]) - (let ([x (next arg*)]) - (unless (real? x) - ($oops who "expected real number for ~~f, received ~s" x)) - (let ([x (inexact x)]) - (if (exceptional-flonum? x) - (padnum w oc pc op (number->string x)) - (do-fwrite op x w d k oc pc sign?)))) - (loop (cdr cmd*) (cdr arg*)))] - [ewrite (w d ew k oc pc ec sign?) - (vparams arg* ([w (nnfixnum? w)] - [d (nnfixnum? d)] - [ew (nnfixnum? e)] - [k (fixnum? k)] - [oc (char? overflow-char)] - [pc (char? pad-char)] - [ec (char? exponent-char)]) - (let ([x (next arg*)]) - (unless (real? x) - ($oops who "expected real number for ~~e, received ~s" x)) - (let ([x (inexact x)]) - (if (exceptional-flonum? x) - (padnum w oc pc op (number->string x)) - (if (or (not d) (fx< (fx- d) k (fx+ d 2))) - (do-ewrite op x w d ew k oc pc ec sign?) - ; signaling an error might be kind, but cltl2 says otherwise - (if (and w oc) - (display (make-string w oc) op) - (let ([d (if (fx> k 0) (fx- k 1) (fx- 1 k))]) - (do-ewrite op x w d ew k oc pc ec sign?))))))) - (loop (cdr cmd*) (cdr arg*)))] - [gwrite (w d ew k oc pc ec sign?) - (vparams arg* ([w (nnfixnum? w)] - [d (nnfixnum? d)] - [ew (nnfixnum? e)] - [k (fixnum? k)] - [oc (char? overflow-char)] - [pc (char? pad-char)] - [ec (char? exponent-char)]) - (let ([x (next arg*)]) - #;(define (ilog x) (fx+ (cadr (flonum->digits x float-base 'normal 0)) 1)) - (define (ilog x) ; 4x faster and good enough - (if (fl= x 0.0) - 0 - (fx+ (flonum->fixnum (floor (fl- (fl* (log (flabs x)) (fl/ (log 10))) 1e-10))) 1))) - (define significant-digits - (lambda (ls) - (if (fx< (car ls) 0) - 0 - (fx+ 1 (significant-digits (cdr ls)))))) - (unless (real? x) - ($oops who "expected real number for ~~g, received ~s" x)) - (let ([x (inexact x)]) - (if (exceptional-flonum? x) - (padnum w oc pc op (number->string x)) - (if d - (let f ([n (ilog x)]) ; can x be negative here? - (let ([dd (fx- d n)]) - (if (not (fx<= 0 dd d)) - (do-ewrite op x w d ew k oc pc ec sign?) - (let ([ls (flonum->digits x float-base 'absolute (fx- dd))]) - (let ([actual-n (fx+ (cadr ls) 1)]) - (if (fx> actual-n n) ; e.g., .9999 came back as 1.000 - (f actual-n) - (let* ([ee (if ew (fx+ ew 2) 4)] - [ww (and w (fx- w ee))]) - ; scale k not used when treated as ~f - (do-fwrite-d op x ww dd 0 oc pc sign? ls) - (when w (display (make-string ee #\space) op))))))))) - (let* ([ls (flonum->digits x float-base 'normal 0)] - [n (fx+ (cadr ls) 1)] - [est-d (max (significant-digits (cddr ls)) (min n 7))] - [dd (fx- est-d n)]) - (if (fx<= 0 dd est-d) - (let* ([ee (if ew (fx+ ew 2) 4)] - [ww (and w (fx- w ee))]) - ; scale k not used when treated as ~f - (do-fwrite op x ww dd 0 oc pc sign?) - ; suppressing trailing whitespace when (not w) - (when w (display (make-string ee #\space) op))) - ; cltl seems to want our estimated d here (est-d) - ; but original d (#f) makes more sense - (do-ewrite op x w d ew k oc pc ec sign?))))))) - (loop (cdr cmd*) (cdr arg*)))] - [$write (d n w pc sign-before-pad? sign?) - (vparams arg* ([d (nnfixnum? d)] - [n (nnfixnum? n)] - [w (nnfixnum? w)] - [pc (char? pad-char)]) - (let ([x (next arg*)]) - (unless (real? x) - ($oops who "expected real number for ~~$, received ~s" x)) - (let ([x (inexact x)]) - (if (exceptional-flonum? x) - (padnum w #f pc op (number->string x)) - (let ([ls (flonum->digits x float-base 'absolute (fx- d))]) - (if (and sign-before-pad? (or sign? (fx= (car ls) -1))) - (begin - (write-char (if (fx= (car ls) -1) #\- #\+) op) - (padnum (fx- w 1) #f pc op - (fd->string (cons 1 (cdr ls)) d n #f))) - (padnum w #f pc op - (fd->string ls d n sign?))))))) - (loop (cdr cmd*) (cdr arg*)))] - [write-radix (base w pc cc ci sign? commas?) - (vparams arg* ([base (radix? n)] - [w (nnfixnum? w)] - [pc (char? pad-char)] - [cc (char? comma-char)] - [ci (pfixnum? comma-interval)]) - (let ([x (next arg*)]) - (padnum w #f pc op - (cond - [(exact-integer? x) - (let* ([s (number->string x base)] - [s (if (and sign? (>= x 0)) (string-append "+" s) s)]) - (if commas? - (let* ([n (string-length s)] - [sign (let ([c (string-ref s 0)]) - (and (memv c '(#\+ #\-)) c))] - [m (if sign (fx- n 1) n)] - [nc (fxquotient (fx- m 1) ci)] - [s2 (make-string (fx+ n nc))] - [k (fxremainder m ci)] - [k (if (fx= k 0) ci k)]) - (define (loop i j k) - (cond - [(fx= i n) s2] - [(fx= k 0) - (string-set! s2 j cc) - (loop i (fx+ j 1) ci)] - [else - (string-set! s2 j (string-ref s i)) - (loop (fx+ i 1) (fx+ j 1) (fx- k 1))])) - (cond - [sign - (string-set! s2 0 sign) - (loop 1 1 k)] - [else (loop 0 0 k)])) - s))] - [else - (let ([op (open-output-string)]) - (parameterize ([print-radix base]) - (display x op)) - (get-output-string op))]))) - (loop (cdr cmd*) (cdr arg*)))] - [plural (back-up? y/ies?) - (let ([arg* (if back-up? - (let f ([prev #f] [ls all-arg*]) - (if (eq? ls arg*) - (if prev - prev - ($oops who "no previous argument for ~a" (fmt-directive (car cmd*)))) - (f ls (cdr ls)))) - arg*)]) - (if (eqv? (next arg*) 1) - (when y/ies? (write-char #\y op)) - (if y/ies? - (display "ies" op) - (write-char #\s op))) - (loop (cdr cmd*) (cdr arg*)))] - [fancy-radix (colon? at?) - (let ([x (next arg*)]) - (unless (exact-integer? x) - ($oops who "expected exact integer for ~~r, received ~s" x)) - (if colon? - (if at? - (write-old-roman x op) - (write-ordinal x op)) - (if at? - (write-roman x op) - (write-cardinal x op)))) - (loop (cdr cmd*) (cdr arg*))] - [dup-char (n c) - (vparams arg* ([n (nnfixnum? n)]) - (display (make-string n c) op) - (loop (cdr cmd*) arg*))] - [tabulate (colnum colinc relative?) - (vparams arg* ([colnum (nnfixnum? colnum)] - [colinc (nnfixnum? colinc)]) - (cond - [relative? - (display (make-string colnum #\space) op) - (unless (= colinc 0) - (let ([col (output-column op)]) - (when col - (let ([n (modulo col colinc)]) - (unless (= n 0) - (display (make-string (- colinc n) #\space) op))))))] - [else - (let ([col (output-column op)]) - (if col - (if (>= col colnum) - (unless (= colinc 0) - (display (make-string (- colinc (modulo (- col colnum) colinc)) #\space) op)) - (display (make-string (- colnum col) #\space) op)) - (display " " op)))]) - (loop (cdr cmd*) arg*))] - [indirect (splice?) - (let ([xcntl (next arg*)]) - (unless (string? xcntl) - ($oops who "first ~a argument ~s is not a string" (fmt-directive (car cmd*)) xcntl)) - (let-values ([(xcmd* expected) (parse who xcntl)]) - (if splice? - (outer-loop xcmd* (cdr arg*) op cntl all-arg* #f ct? - (lambda (arg*) (loop (cdr cmd*) arg*)) - (lambda (arg* super?) (loop (cdr cmd*) arg*))) - (let* ([arg* (cdr arg*)] - [xarg* (next arg*)]) - (let ([len ($list-length xarg* who)]) - (when (and indirect-too-many-args-check expected) - (check-nargs who expected len xcntl))) - (outer-loop xcmd* xarg* op xcntl xarg* #f ct? - (lambda (xarg*) - (when (and dynamic-too-many-args-check (not (null? xarg*))) - ($oops who "too many arguments for control string ~s" xcntl)) - (loop (cdr cmd*) (cdr arg*))) - (lambda (xarg* super?) - (loop (cdr cmd*) (cdr arg*))))))))] - [conditional (n cases default) - (vparams arg* ([n (nnfixnum? n)]) - (let-values ([(n arg*) (if n (values n arg*) (let ([n (next arg*)]) (values n (cdr arg*))))]) - (loop - (append (if (and (fixnum? n) (fx<= 0 n) (fx< n (vector-length cases))) - (vector-ref cases n) - default) - (cdr cmd*)) - arg*)))] - [conditional/colon (alternative consequent) - (let ([arg (next arg*)]) - (loop (append (if arg consequent alternative) (cdr cmd*)) - (cdr arg*)))] - [conditional/at (consequent) - (if (next arg*) - (loop (append consequent (cdr cmd*)) arg*) - (loop (cdr cmd*) (cdr arg*)))] - [justify (mincol colinc minpad pc before? after? initial margin columns segments) - (vparams arg* ([mincol (nnfixnum? mincol)] - [colinc (nnfixnum? colinc)] - [minpad (nnfixnum? minpad)] - [pc (char? pad-char)]) - (let () - (define (process-segments initial complete segments arg*) - (if (null? segments) - (finalize initial (reverse complete) arg*) - (tostr (car segments) arg* #f - (lambda (s arg*) (process-segments initial (cons s complete) (cdr segments) arg*)) - (lambda (s arg* super?) (finalize initial (reverse complete) arg*))))) - (define (finalize initial segments arg*) - (let* ([chars (apply fx+ (map string-length segments))] - [segments (if before? - (if after? - `("" ,@segments "") - `("" ,@segments)) - (if after? - `(,@segments "") - (if (null? segments) - '("") - segments)))] - [npads (fx- (length segments) 1)] - [size (fx+ chars (fx* minpad npads))] - [size (if (fx<= size mincol) - mincol - (fx+ size (fxmodulo (fx- mincol size) colinc)))]) - (when initial - (let ([oc (output-column op)]) - (when (and oc (fx> (fx+ oc size margin) columns)) - (display initial op)))) - (cond - [(fx= npads 0) ; right justify single item - (display (make-string (fx- size chars) pc) op) - (display (car segments) op)] - [else - (let* ([pad-amt (fx- size chars)] - [pad-q (fxquotient pad-amt npads)] - [pad-r (fxremainder pad-amt npads)] - [pad-i (if (fx= pad-r 0) 0 (fxquotient npads pad-r))]) - (let f ([s (car segments)] [s* (cdr segments)] [i 1] [pad-r pad-r]) - (display s op) - (unless (null? s*) - (cond - [(and (fx> pad-r 0) (fx= i 1)) - (display (make-string (fx+ pad-q 1) pc) op) - (f (car s*) (cdr s*) pad-i (fx- pad-r 1))] - [else - (display (make-string pad-q pc) op) - (f (car s*) (cdr s*) (fx- i 1) pad-r)]))))])) - (loop (cdr cmd*) arg*)) - (if initial - (tostr initial arg* #f - (lambda (initial arg*) (process-segments initial '() segments arg*)) - (lambda (s arg* super?) (finalize #f '() arg*))) - (process-segments #f '() segments arg*))))] - [goto (n reverse? absolute?) - (vparams arg* ([n (nnfixnum? n)]) - (loop (cdr cmd*) - (cond - [absolute? - (let ([n (or n 0)]) - (unless (fx<= n (length all-arg*)) - ($oops who "~a would move beyond argument list" (fmt-directive (car cmd*)))) - (list-tail all-arg* n))] - [reverse? - (let ([n (or n 1)]) - (let ([n (fx- (length all-arg*) (length arg*) n)]) - (unless (fx>= n 0) - ($oops who "~a would move before first argument" (fmt-directive (car cmd*)))) - (list-tail all-arg* n)))] - [else - (let ([n (or n 1)]) - (unless (fx<= n (length arg*)) - ($oops who "~a would move beyond argument list" (fmt-directive (car cmd*)))) - (list-tail arg* n))])))] - [convert-case (nested-cmd* colon? at?) - (let () - (define convert-display - (lambda (s) - (if colon? - (if at? - (string-upcase! s) - (string-capitalize! s)) - (if at? - (string-capitalize-first! s) - (string-downcase! s))) - (display s op))) - (tostr nested-cmd* arg* super-arg* - (lambda (s arg*) (convert-display s) (loop (cdr cmd*) arg*)) - (lambda (s arg* super?) (convert-display s) (fail arg* super?))))] - [iteration (body n sublists? use-remaining? at-least-once?) - (vparams arg* ([n (nnfixnum? n)]) - (let-values ([(body body-cntl body-expected arg*) - (if (null? body) - (let ([arg (next arg*)]) - (let-values ([(cmd* expected) (parse who arg)]) - (values cmd* arg expected (cdr arg*)))) - (values body cntl #f arg*))]) - (if use-remaining? - (if sublists? - (let f ([n n] [arg* arg*] [at-least-once? at-least-once?]) - (if (or (and n (fx= n 0)) (and (not at-least-once?) (null? arg*))) - (loop (cdr cmd*) arg*) - (let-values ([(xarg* arg*) (if (null? arg*) (values '() '()) (values (car arg*) (cdr arg*)))]) - (let ([len ($list-length xarg* who)]) - (when (and indirect-too-many-args-check body-expected) - (check-nargs who body-expected len body-cntl))) - (outer-loop body xarg* op body-cntl xarg* arg* ct? - (lambda (xarg*) - (when (and dynamic-too-many-args-check (not (null? xarg*))) - ($oops who "too many arguments for control string ~s" body-cntl)) - (f (and n (fx- n 1)) arg* #f)) - (lambda (xarg* super?) - (if super? - (loop (cdr cmd*) arg*) - (f (and n (fx- n 1)) arg* #f))))))) - (let f ([n n] [arg* arg*] [at-least-once? at-least-once?]) - (if (or (and n (fx= n 0)) (and (not at-least-once?) (null? arg*))) - (loop (cdr cmd*) arg*) - (outer-loop body arg* op body-cntl all-arg* #f ct? - (lambda (arg*) (f (and n (fx- n 1)) arg* #f)) - (lambda (arg* super?) (f (and n (fx- n 1)) arg* #f)))))) - (let ([all-larg* (next arg*)]) - (unless (list? all-larg*) - ($oops who "~s is not a proper list" all-larg*)) - (if sublists? - (let f ([n n] [larg* all-larg*] [at-least-once? at-least-once?]) - (if (or (and n (fx= n 0)) (and (not at-least-once?) (null? larg*))) - (loop (cdr cmd*) (cdr arg*)) - (let-values ([(xarg* larg*) (if (null? larg*) (values '() '()) (values (car larg*) (cdr larg*)))]) - (let ([len ($list-length xarg* who)]) - (when (and indirect-too-many-args-check body-expected) - (check-nargs who body-expected len body-cntl))) - (outer-loop body xarg* op body-cntl xarg* larg* ct? - (lambda (xarg*) - (when (and dynamic-too-many-args-check (not (null? xarg*))) - ($oops who "too many arguments for control string ~s" body-cntl)) - (f (and n (fx- n 1)) larg* #f)) - (lambda (xarg* super?) - (if super? - (loop (cdr cmd*) (cdr arg*)) - (f (and n (fx- n 1)) larg* #f))))))) - (let f ([n n] [larg* all-larg*] [at-least-once? at-least-once?]) - (if (or (and n (fx= n 0)) (and (not at-least-once?) (null? larg*))) - (loop (cdr cmd*) (cdr arg*)) - (outer-loop body larg* op body-cntl all-larg* #f ct? - (lambda (larg*) (f (and n (fx- n 1)) larg* #f)) - (lambda (larg* super?) (f (and n (fx- n 1)) larg* #f))))))))))] - [abort (n m super?) - (vparams arg* ([n (true? n)] [m (true? m)]) - (if (if n - (if m (eqv? n m) (eqv? n 0)) - (null? (if super? super-arg* arg*))) - (fail arg* super?) - (loop (cdr cmd*) arg*)))] - [columntrack (body) - (let ([xop (make-format-port op)]) - (outer-loop body arg* xop cntl arg* super-arg* #t - (lambda (arg*) - (close-output-port xop) - (outer-loop (cdr cmd*) arg* op cntl arg* super-arg* ct? succ fail)) - (lambda (arg* super?) - (close-output-port xop) - (fail arg* super?))))] - [else ($oops who "internal error: ~s" cmd)])] - [else ($oops who "internal error: ~s" cmd)]))))) - (let ([op (or fmt-op (open-output-string))]) - (outer-loop cmd* arg* op cntl arg* #f #f - (lambda (arg*) - (when (and dynamic-too-many-args-check (not (null? arg*))) - ($oops who "too many arguments for control string ~s" cntl)) - (void)) - (lambda (arg* super?) (void))) - (unless fmt-op (get-output-string op))))) - - (define check-nargs - (lambda (who expected received cntl) - (when (and expected received) - (unless (fx= expected received) - (if (fx< received expected) - ($oops who "too few arguments for control string ~s" cntl) - ($oops who "too many arguments for control string ~s" cntl)))))) - - (define format-port-name "format port") - (define (output-column p) - (unless (eq? (port-name p) format-port-name) - ($oops 'format "internal error: port is not a format port")) - ((port-handler p) 'column p)) - - (define make-format-port - (lambda (subop) - (define column 0) - (define update-column! - (lambda (p s n) - (let f ([i 0] [col 0] [newline? #f]) - (if (fx= i n) - (begin - (set! column (if newline? col (+ column col))) - (set-port-bol! p newline?)) - (if (char=? (string-ref s i) #\newline) - (f (fx+ i 1) 0 #t) - (f (fx+ i 1) (fx+ col 1) newline?)))))) - (define handler - (message-lambda - (lambda (msg . args) ($oops 'format-port "operation ~s not handled" msg)) - [(block-write p s n) - (flush-output-port p) - (update-column! p s n) - (block-write subop s n)] - [(clear-output-port p) (set-textual-port-output-index! p 0)] - [(close-port p) - (flush-output-port p) - (set-textual-port-output-size! p 0) - (mark-port-closed! p)] -; [(file-length p) #f] - [(file-position p) (most-negative-fixnum)] - [(file-position p pos) ($oops 'format-port "cannot reposition")] - [(flush-output-port p) - (let ([b (textual-port-output-buffer p)] - [i (textual-port-output-index p)]) - (unless (fx= i 0) - (update-column! p b i) - (block-write subop b i))) - (set-textual-port-output-index! p 0)] - [(port-name p) format-port-name] - [(write-char c p) - (let ([b (textual-port-output-buffer p)] - [i (textual-port-output-index p)]) - (string-set! b i c) - (block-write subop b (fx+ i 1))) - (set-textual-port-output-index! p 0)] - [(column p) (flush-output-port p) column])) - (let ([len 1024]) - (let ([p (make-output-port handler (make-string len))]) - (set-textual-port-output-size! p (fx- len 1)) - (set-port-bol! p #t) - p)))) - - (define go - (lambda (who op cntl args) - (let-values ([(cmd* expected) (parse who cntl)]) - (when static-too-many-args-check - (check-nargs who expected (length args) cntl)) - (dofmt who op cntl cmd* args)))) - - (set! format - (case-lambda - [(port/cntl cntl/arg . args) - (cond - [(port? port/cntl) - (unless (and (output-port? port/cntl) (textual-port? port/cntl)) - ($oops 'format "~s is not a textual output port" port/cntl)) - (go 'format port/cntl cntl/arg args)] - [(eq? port/cntl #t) (go 'format (current-output-port) cntl/arg args)] - [(eq? port/cntl #f) (go 'format #f cntl/arg args)] - [else (go 'format #f port/cntl (cons cntl/arg args))])] - [(cntl . args) (go 'format #f cntl args)])) - - (set! $dofmt dofmt) - - (set! $make-fmt->expr make-fmt->expr) - - (set! $parse-format-string - (lambda (who cntl received) - (let-values ([(cmd* expected) (parse who cntl)]) - (when static-too-many-args-check - (check-nargs who expected received cntl)) - (squash cmd*)))) - - (set! printf - (lambda (cntl . args) - (go 'printf (current-output-port) cntl args))) - - (set! fprintf - (lambda (op cntl . args) - (unless (and (output-port? op) (textual-port? op)) - ($oops 'fprintf "~s is not a textual output port" op)) - (go 'fprintf op cntl args)))) diff --git a/ta6ob/s/format.ta6ob b/ta6ob/s/format.ta6ob deleted file mode 100644 index 142ddf5..0000000 Binary files a/ta6ob/s/format.ta6ob and /dev/null differ diff --git a/ta6ob/s/front.ss b/ta6ob/s/front.ss deleted file mode 100644 index f214ceb..0000000 --- a/ta6ob/s/front.ss +++ /dev/null @@ -1,252 +0,0 @@ -;;; front.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(begin -(define-who make-parameter - (case-lambda - [(init guard) (#2%make-parameter init guard)] - [(v) (#2%make-parameter v)])) - -(when-feature pthreads -(let () - (define allocate-thread-parameter - (let () - (define free-list '()) ; list of pairs w/ index as car - (define index-guardian (make-guardian)) - (lambda (initval) - (with-tc-mutex - (let ([index - (or (index-guardian) - (and (not (null? free-list)) - (let ([index (car free-list)]) - (set! free-list (cdr free-list)) - index)) - (let* ([n (vector-length ($tc-field 'parameters ($tc)))] - [m (fx* (fx+ n 1) 2)]) - (for-each - (lambda (thread) - (let ([tc ($thread-tc thread)]) - (let ([old ($tc-field 'parameters tc)] - [new (make-vector m)]) - (do ([i (fx- n 1) (fx- i 1)]) - ((fx< i 0)) - (vector-set! new i (vector-ref old i))) - ($tc-field 'parameters tc new)))) - ($thread-list)) - (set! free-list - (do ([i (fx- m 1) (fx- i 1)] - [ls free-list (cons (list i) ls)]) - ((fx= i n) ls))) - (list n)))]) - (let loop () - (let ([index (index-guardian)]) - (when index - (for-each - (lambda (thread) - (vector-set! - ($tc-field 'parameters ($thread-tc thread)) - (car index) - 0)) - ($thread-list)) - (set! free-list (cons index free-list)) - (loop)))) - (for-each - (lambda (thread) - (vector-set! - ($tc-field 'parameters ($thread-tc thread)) - (car index) - initval)) - ($thread-list)) - (index-guardian index) - index))))) - (define set-thread-parameter! - (lambda (index value) - (with-tc-mutex - (vector-set! ($tc-field 'parameters ($tc)) (car index) value)))) - (set-who! make-thread-parameter - (case-lambda - [(init guard) - (unless (procedure? guard) ($oops who "~s is not a procedure" guard)) - (let ([index (allocate-thread-parameter (guard init))]) - (case-lambda - [() (vector-ref ($tc-field 'parameters ($tc)) (car index))] - [(u) (set-thread-parameter! index (guard u))]))] - [(init) - (let ([index (allocate-thread-parameter init)]) - (case-lambda - [() (vector-ref ($tc-field 'parameters ($tc)) (car index))] - [(u) (set-thread-parameter! index u)]))])) - (set! $allocate-thread-parameter allocate-thread-parameter) - (set! $set-thread-parameter! set-thread-parameter!)) -) - -(define case-sensitive ($make-thread-parameter #t (lambda (x) (and x #t)))) - -(define compile-interpret-simple ($make-thread-parameter #t (lambda (x) (and x #t)))) - -(define generate-interrupt-trap ($make-thread-parameter #t (lambda (x) (and x #t)))) - -(define generate-allocation-counts ($make-thread-parameter #f (lambda (x) (and x #t)))) - -(define generate-instruction-counts ($make-thread-parameter #f (lambda (x) (and x #t)))) - -(define enable-cross-library-optimization ($make-thread-parameter #t (lambda (x) (and x #t)))) - -(define machine-type - (lambda () - (constant machine-type-name))) - -(define-who $fasl-target ($make-thread-parameter #f)) - -;;; package stubs are defined here in case we exclude certain packages -(eval-when (compile) -(define-syntax package-stub - (lambda (x) - (syntax-case x () - [(_ name msg) - (identifier? #'name) - #'(package-stub (name name) msg)] - [(_ (name pub-name) msg) - #'(define name (lambda args ($oops 'pub-name msg)))]))) - -(define-syntax package-stubs - (lambda (x) - (syntax-case x () - [(_ pkg name ...) - (with-syntax ([msg (format "~a package is not loaded" (datum pkg))]) - #'(begin (package-stub name msg) ...))]))) -) - -(package-stubs cafe - waiter-prompt-and-read - waiter-write - waiter-prompt-string - new-cafe) -(package-stubs compile - ($clear-dynamic-closure-counts compile) - ($c-make-closure compile) - ($c-make-code compile) - compile - ($compile-backend compile) - compile-file - ($compile-host-library compile) - compile-library - compile-port - compile-program - compile-script - compile-to-file - compile-to-port - compile-whole-library - compile-whole-program - ($dynamic-closure-counts compile) - ($loop-unroll-limit compile) - make-boot-file - ($make-boot-file make-boot-file) - make-boot-header - ($make-boot-header make-boot-header) - maybe-compile-file - maybe-compile-library - maybe-compile-program - ($np-boot-code compile) - ($np-compile compile) - ($np-get-timers compile) - ($np-last-pass compile) - ($np-reset-timers! compile) - ($np-tracer compile) - ($optimize-closures compile) - ($track-dynamic-closure-counts compile) - ($track-static-closure-counts compile)) -(package-stubs fasl - ($fasl-bld-graph fasl-write) - ($fasl-enter fasl-write) - ($fasl-start fasl-write) - ($fasl-table fasl-write) - ($fasl-out fasl-write) - ($fasl-wrf-graph fasl-write) - fasl-write - fasl-file) -(package-stubs inspect - inspect - inspect/object) -(package-stubs interpret - interpret) -(package-stubs pretty-print - pretty-format - pretty-line-length - pretty-one-line-limit - pretty-initial-indent - pretty-standard-indent - pretty-maximum-lines - pretty-print - pretty-file) -(package-stubs profile - profile-clear - profile-dump) -(package-stubs sc-expand - sc-expand - ($syntax-dispatch sc-expand) - syntax-error - literal-identifier=? - bound-identifier=? - free-identifier=? - identifier? - generate-temporaries - syntax->datum - datum->syntax) -(package-stubs trace - trace-output-port - trace-print - ($trace trace) - ($untrace untrace) - ($trace-closure trace)) -(package-stubs compiler-support - $cp0 - $cpvalid - $cpletrec - $cpcheck) -(package-stubs syntax-support - $uncprep) - -(define current-eval - ($make-thread-parameter - (lambda args ($oops 'eval "no current evaluator")) - (lambda (x) - (unless (procedure? x) - ($oops 'current-eval "~s is not a procedure" x)) - x))) - -(define current-expand - ($make-thread-parameter - (lambda args ($oops 'expand "no current expander")) - (lambda (x) - (unless (procedure? x) - ($oops 'current-expand "~s is not a procedure" x)) - x))) - -(define eval - (case-lambda - [(x) ((current-eval) x)] - [(x env-spec) ((current-eval) x env-spec)])) - -(define expand - (case-lambda - [(x) ((current-expand) x)] - [(x env-spec) ((current-expand) x env-spec)] - [(x env-spec records?) ((current-expand) x env-spec records?)] - [(x env-spec records? compiling-a-file) ((current-expand) x env-spec records? compiling-a-file)] - [(x env-spec records? compiling-a-file outfn) ((current-expand) x env-spec records? compiling-a-file outfn)])) - -(define $compiler-is-loaded? #f) -) diff --git a/ta6ob/s/front.ta6ob b/ta6ob/s/front.ta6ob deleted file mode 100644 index 8932371..0000000 Binary files a/ta6ob/s/front.ta6ob and /dev/null differ diff --git a/ta6ob/s/ftype.ss b/ta6ob/s/ftype.ss deleted file mode 100644 index 282b974..0000000 --- a/ta6ob/s/ftype.ss +++ /dev/null @@ -1,2062 +0,0 @@ -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -#| -todo: - - consider adding uid form, with warnings if nested ftypes do not - also have uid forms...need to check ftd generative? flag. - alternatively, consider implementing textual ftype equality. - would need some sort of union-find algorithm and a couple of extra - indirects to reduce the cost of checks. either way, generalize - syntaxes that now require ftype names to allow arbitrary ftypes - - consider passing $fptr-ref-xxx, $fptr-set-xxx! more info to - produce better error messages - - consider support for variable-length arrays. there may be no good - way to do so. don't want to make ftds generative, but can't - avoid doing so if the lengths aren't known until run time since - each evaluation of an ftype form could result in different sizes. - as an alternative, perhaps give some way to define array-length - constants, e.g., (define-ftype-constant x 10). - - consider moving verify-ftype-pointer checks into $fptr-&ref, - $fptr-ref, and $fptr-set! to reduce the amount of generated code. - we'd end up doing more checks that way when pointer indirects are - followed and new fptrs are generated, but that probably isn't a - big deal. would need to pass $fptr-ref a who argument for use in - following pointers from ftype-&ref and ftype-set! - - consider trying to fix 32-bit macos x powerpc alignment issues. - doubles and long-longs are aligned on 8-byte boundaries if they - are first in a struct; otherwise, they are mostly aligned on - 4-byte boundaries. haven't entirely penetrated the rules governing - unions, but it's clear the same union can have a different size - depending on whether it is stand-alone or embedded in a struct -|# - -#| -(define-ftype ftype-name ftype) [syntax] - -ftype-name -> identifier - -ftype -> - ftype-name - (* ftype) - (struct (field-name ftype) ...) - (union (field-name ftype) ...) - (array length ftype) - (bits (field-name signedness bits) ...) - (function (arg-type ...) result-type) - (function conv ... (arg-type ...) result-type) - (packed ftype) - (unpacked ftype) - (endian endianness ftype) - -length -> exact nonnegative integer - -field-name -> identifier - -signedness -> signed | unsigned - -bits -> exact positive integer - -endianness -> native | big | little - -built-in ftype names: - short | unsigned-short - int | unsigned | unsigned-int - long | unsigned-long - long-long | unsigned-long-long - char | wchar - float | double - void* | iptr | uptr - fixnum | boolean - integer-8 | unsigned-8 - integer-16 | unsigned-16 - integer-24 | unsigned-24 - integer-32 | unsigned-32 - integer-40 | unsigned-40 - integer-48 | unsigned-48 - integer-56 | unsigned-56 - integer-64 | unsigned-64 - single-float | double-float - size_t | ssize_t | ptrdiff_t | wchar_t - -notes: - - underscore ( _ ) can be used as the field name for one or - more fields of a struct or union. such fields are included - in the layout but are considered unnamed and cannot be accessed - via the ftype operators described below. - - - non-underscore field names are handled symbolically, i.e., - they are treated as symbols rather than identifiers. each - symbol must be unique (as a symbol) with respect to the other - field names within a single struct or union, but need not be - unique with respect to field names in other structs or - unions, including those nested inside the struct or union. - - - by default, padding is inserted where appropriate to maintain - proper alignment of multibyte scalar values in an attempt to - mirror the target machine's (often poorly documented) C struct - layout conventions. for packed ftypes (ftypes wrapped in a - packed form with no closer enclosing unpacked form), this - padding is not inserted. - - - the overall size of an ftype (including padding) must be a fixnum. - - - the total size n of the fields within an ftype bits form must - be 8, 16, 24, 32, 40, 48, 56, or 64. padding must be added manually - if needed. (Performance might suffer when the total is not a power - of two or is 64 on a 32-bit machine.) For little-endian machines, - the first field occupies the low-order bits of the container, with - each subsequent field just above the preceding field, while for - big-endian machines, the first field occupies the high-order bits, - with each subsequent field just below the preceding field. - - - ftype pointers are records encapsulating an ftype descriptor - (ftd) along with the address of the foreign object, except that - pointers of type void* are just addresses. the encapsulated - ftd is used to verify the applicability of an ftype-&ref, - ftype-ref, or ftype-set! operation. - - - two ftypes are considered equivalent if and only if their uids are - equivalent. a fresh uid is created each time an ftype declaration - is expanded. thus, textually distinct ftypes are not considered - equivalent even if they are identical in structure. - - - all signed or unsigned integer fields (including bit fields) can - be set to an exact integer in the range -2^{k-1}..+2^k-1, where - k is the size in bits of the integer - - - most run-time checks are disabled at optimize-level 3. - - - the use of packed ftypes or the use of improperly aligned - addresses can result in unaligned references, which are inefficient - on some machines and result in invalid-memory reference exceptions - on others. - -ftype operators: - -(ftype-sizeof ftype-name) [syntax] - - returns the size in bytes of an object with type ftype-name. - -(make-ftype-pointer ftype-name address) [syntax] - - creates an ftype pointer encapsulating an ftype descriptor (ftd) - for the named ftype along with the address. - -(ftype-pointer? expr) [syntax] -(ftype-pointer? ftype-name expr) [syntax] - - in the first form, return #t if the value of expr is an ftype - pointer, otherwise #f. in the second form, returns #t if the - value of expr is an ftype pointer of the named ftype, - otherwise #f. - -(ftype-pointer-address fptr) [procedure] - - returns the address encapsulated within fptr. - -(ftype-pointer-null? fptr) [procedure] - - returns #t if the address encapsulated within fptr is 0, - otherwise #f. - -(ftype-pointer=? fptr1 fptr2) [procedure] - - returns #t if the addresses encapsulated within fptr are - the same, otherwise #f. - -(ftype-pointer-ftype fptr) [procedure] - - returns an s-expression representation of fptr's ftype. the - s-expression should not be modified. - -(ftype-pointer->sexpr fptr) [procedure] - - returns an s-expression representation of the foreign object - pointed to by fptr. the s-expression should not be modified. - -(ftype-&ref ftype-name (access ...) fptr-expr) [syntax] - - returns an ftype pointer to the named field of the foreign object - pointed to by the value of fptr-expr, which must be an ftype - pointer of the named ftype. each access must be a field name or - array index expression, as appropriate for the named ftype; it is a - syntax error if this is not the case. the values of all array indices - must be in bounds for the array. any nonnegative index is considered - in bounds for an array of size zero. the return value is a freshly - allocated ftype pointer, except that if (access ...) is empty, the - return value might be eq to the value of fptr-expr. - -(ftype-ref ftype-name (access ...) fptr-expr) [syntax] - - returns the value of the specified field of the foreign object pointed - to by the value of fptr-expr, which must be an ftype pointer of the - named ftype. The access and fptr-expr requirements stated under - ftype-&ref apply as well to ftype-ref. In addition, the field must - be a scalar field, i.e., one of the base types, an alias for one of - the base types, or a pointer. If the result is a pointer value, - other than one declared as void*, the return value is a freshly - allocated ftype pointer. - - It (access ...) is empty, the "specified field" is the object pointed - to by the ftype pointer. For example, if x is an ftype-pointer pointing - to a double, (ftype-ref double () x) returns the double. - -(ftype-set! ftype-name (access ...) fptr-expr val-expr) [syntax] - - sets the value of the named field of the foreign object pointed to - by the value of fptr-expr, which must be an ftype pointer of the - named ftype, to the value of val-expr. The access and fptr-expr - requirements stated under ftype-&ref and ftype-ref apply as well - to ftype-set!. val-expr must evaluate to a value appropriate for - the identified field; for pointer fields other than those declared as - void*, the value must be an ftype pointer with the appropriate ftype. - Otherwise, the value of val-expr must be of the appropriate type, - e.g., a character for types char and wchar and an integer of the - appropriate size for int and unsigned. -|# - -(begin -(let () - (include "types.ss") - (define-syntax rtd/fptr - (let ([rtd ($make-record-type #!base-rtd #f - '#{ftype-pointer a9pth58056u34h517jsrqv-0} - '((immutable uptr address)) - #f - #f)]) - (lambda (x) #`'#,rtd))) - (define $fptr? (record-predicate rtd/fptr)) - (define $ftype-pointer-address (record-accessor rtd/fptr 0)) - (define-syntax rtd/ftd - (let ([rtd ($make-record-type #!base-rtd #!base-rtd - '#{rtd/ftd a9pth58056u34h517jsrqv-1} - '((immutable ptr stype) - (immutable ptr size) - (immutable ptr alignment)) - #f - #f)]) - (lambda (x) #`'#,rtd))) - (define ftd? (record-predicate rtd/ftd)) - (define ftd-stype (record-accessor rtd/ftd 0)) - (define ftd-size (record-accessor rtd/ftd 1)) - (define ftd-alignment (record-accessor rtd/ftd 2)) - (define-syntax define-ftd-record-type - (lambda (x) - (define construct-name - (lambda (template-identifier . args) - (datum->syntax - template-identifier - (string->symbol - (apply string-append - (map (lambda (x) - (if (string? x) - x - (symbol->string (syntax->datum x)))) - args)))))) - (define ftd-field - (lambda (field) - (syntax-case field (mutable) - [field-name - (identifier? #'field-name) - #'field-name] - [(mutable field-name) - (identifier? #'field-name) - #'field-name]))) - (define ftd-accessors - (lambda (record-name field*) - (define accessor - (lambda (field-name ordinal) - #`(define #,(construct-name field-name "ftd-" record-name "-" field-name) - (record-accessor rtd #,ordinal)))) - (define mutator - (lambda (field-name ordinal) - #`(define #,(construct-name field-name "ftd-" record-name "-" field-name "-set!") - (record-mutator rtd #,ordinal)))) - (let f ([field* field*] [ordinal 0]) - (if (null? field*) - '() - (syntax-case (car field*) (mutable) - [field-name - (identifier? #'field-name) - (cons (accessor #'field-name ordinal) - (f (cdr field*) (+ ordinal 1)))] - [(mutable field-name) - (identifier? #'field-name) - (cons (mutator #'field-name ordinal) - (cons (accessor #'field-name ordinal) - (f (cdr field*) (+ ordinal 1))))]))))) - (syntax-case x () - [(_ record-name ?uid field ...) - (with-syntax ([(field-name ...) (map ftd-field #'(field ...))] - [constructor-name (construct-name #'record-name "make-ftd-" #'record-name)]) - #`(begin - (define-syntax rtd - (let ([rtd ($make-record-type #!base-rtd rtd/ftd - '?uid - '(field ...) - #t - #f)]) - (lambda (x) #`'#,rtd))) - (define constructor-name - (lambda (parent uid stype size alignment field-name ...) - ($make-record-type rtd parent (or uid #,(symbol->string (datum record-name))) '() #f #f stype size alignment field-name ...))) - (define #,(construct-name #'record-name "ftd-" #'record-name "?") - (record-predicate rtd)) - #,@(ftd-accessors #'record-name #'(field ...))))]))) - - (define-ftd-record-type base #{rtd/ftd-base a9pth58056u34h517jsrqv-8} swap? type) - (define-ftd-record-type struct #{rtd/ftd-struct a9pth58056u34h517jsrqv-3} field*) - (define-ftd-record-type union #{rtd/ftd-union a9pth58056u34h517jsrqv-4} field*) - (define-ftd-record-type array #{rtd/ftd-array a9pth58056u34h517jsrqv-5} length ftd) - (define-ftd-record-type pointer #{rtd/ftd-pointer a9pth58056u34h517jsrqv-6} (mutable ftd)) - (define-ftd-record-type bits #{rtd/ftd-ibits a9pth58056u34h517jsrqv-9} swap? field*) - (define-ftd-record-type function #{rtd/ftd-function a9pth58056u34h517jsrqv-11} conv* arg-type* result-type) - (module (pointer-size alignment pointer-alignment native-base-ftds swap-base-ftds) - (define alignment - (lambda (max-alignment size) - (gcd max-alignment size))) - (define pointer-size (/ (constant address-bits) 8)) - (define pointer-alignment (gcd (constant max-integer-alignment) pointer-size)) - (define base-types - '(short unsigned-short int unsigned unsigned-int long - unsigned-long long-long unsigned-long-long char wchar float - double void* iptr uptr fixnum boolean integer-8 unsigned-8 - integer-16 unsigned-16 integer-24 unsigned-24 integer-32 unsigned-32 - integer-40 unsigned-40 integer-48 unsigned-48 integer-56 unsigned-56 - integer-64 unsigned-64 single-float double-float wchar_t size_t ssize_t ptrdiff_t)) - (define-who mfb - (lambda (swap?) - (lambda (ty) - (define-syntax make - (syntax-rules () - [(_ type bytes pred) - (if (and swap? (fx= bytes 1)) - (find (lambda (ftd) (eq? (ftd-base-type ftd) ty)) native-base-ftds) - (make-ftd-base rtd/fptr - ; creating static gensym so base ftypes are nongenerative to support - ; separate compilation of ftype definitions and uses. creating unique - ; name so this works even when this file is reloaded, e.g., as a patch - ; file. machine-type is included in the unique name so that we get - ; a different rtd/ftd with the correct "extras" (including size and - ; alignment) when cross compiling between machines with different - ; base-type characteristics. - (let ([pname (format "~a~:[~;s~]" ty swap?)]) - (let ([gstring (format "~aa9pth58056u34h517jsrqv-~s-~a" pname (constant machine-type-name) pname)]) - ($intern3 gstring (string-length pname) (string-length gstring)))) - (if swap? - `(endian ,(constant-case native-endianness - [(big) 'little] - [(little) 'big]) - ,ty) - ty) - bytes (alignment (if (memq 'type '(single-float double-float)) (constant max-float-alignment) (constant max-integer-alignment)) bytes) swap? ty))])) - (record-datatype cases (filter-foreign-type ty) make - ($oops who "unrecognized type ~s" ty))))) - (define native-base-ftds (map (mfb #f) base-types)) - (define swap-base-ftds (map (mfb #t) base-types))) - (define expand-field-names - (lambda (x*) - (let f ([x* x*] [seen* '()]) - (if (null? x*) - '() - (let ([x (car x*)] [x* (cdr x*)]) - (unless (identifier? x) (syntax-error x "invalid field name")) - (if (free-identifier=? x #'_) - (cons #f (f x* seen*)) - (let ([s (syntax->datum x)]) - (if (memq s seen*) - (syntax-error x "duplicate field name") - (cons s (f x* (cons s seen*))))))))))) - (define expand-ftype-name - (case-lambda - [(r ftype) (expand-ftype-name r ftype #t)] - [(r ftype error?) - (cond - [(let ([maybe-ftd (r ftype)]) (and maybe-ftd (ftd? maybe-ftd) maybe-ftd)) => (lambda (ftd) ftd)] - [(find (let ([x (syntax->datum ftype)]) - (lambda (ftd) (eq? (ftd-base-type ftd) x))) - native-base-ftds)] - [else (and error? (syntax-error ftype "unrecognized ftype name"))])])) - (define expand-ftype - (case-lambda - [(r defid ftype) (expand-ftype r '() defid ftype)] - [(r def-alist defid ftype) - (define (check-size ftd) - (unless (ftd-function? ftd) - (let ([size (ftd-size ftd)]) - (unless (and (>= size 0) (< size (constant most-positive-fixnum))) - (syntax-error ftype "non-fixnum overall size for ftype")))) - ftd) - (check-size - (let f/flags ([ftype ftype] [defid defid] [stype (syntax->datum ftype)] [packed? #f] [swap? #f] [funok? #t]) - (define (pad n k) (if packed? n (logand (+ n (- k 1)) (- k)))) - (let f ([ftype ftype] [defid defid] [stype stype] [funok? funok?]) - (if (identifier? ftype) - (cond - [(assp (lambda (x) (bound-identifier=? ftype x)) def-alist) => - (lambda (a) - (let ([ftd (let ([ftd (cdr a)]) - (if (ftd? ftd) - ftd - (or (find (let ([x (syntax->datum ftype)]) - (lambda (ftd) - (eq? (ftd-base-type ftd) x))) - (if swap? swap-base-ftds native-base-ftds)) - ftd)))]) - (unless (ftd? ftd) - (syntax-error ftype "recursive or forward reference outside pointer field")) - (unless funok? - (when (ftd-function? ftd) - (syntax-error ftype "unexpected function ftype name outside pointer field"))) - ftd))] - [(let ([maybe-ftd (r ftype)]) (and maybe-ftd (ftd? maybe-ftd) maybe-ftd)) => - (lambda (ftd) - (unless funok? - (when (ftd-function? ftd) - (syntax-error ftype "unexpected function ftype name outside pointer field"))) - ftd)] - [(find (let ([x (syntax->datum ftype)]) - (lambda (ftd) (eq? (ftd-base-type ftd) x))) - (if swap? swap-base-ftds native-base-ftds))] - [else (syntax-error ftype "unrecognized ftype name")]) - (syntax-case ftype () - [(struct-kwd (field-name ftype) ...) - (eq? (datum struct-kwd) 'struct) - (let loop ([id* (expand-field-names #'(field-name ...))] - [ftd* (map (lambda (ftype stype) (f ftype #f stype #f)) - #'(ftype ...) (datum (ftype ...)))] - [offset 0] [alignment 1] [field* '()]) - (if (null? id*) - (let ([field* (reverse field*)]) - (make-ftd-struct (if (null? field*) rtd/fptr (caddar field*)) - (and defid (symbol->string (syntax->datum defid))) - stype (pad offset alignment) alignment field*)) - (let ([ftd (car ftd*)]) - (let ([offset (pad offset (ftd-alignment ftd))]) - (loop (cdr id*) (cdr ftd*) - (+ offset (ftd-size ftd)) - (max alignment (ftd-alignment ftd)) - (cons (list (car id*) offset ftd) field*))))))] - [(union-kwd (field-name ftype) ...) - (eq? (datum union-kwd) 'union) - (let ([id* (expand-field-names #'(field-name ...))] - [ftd* (map (lambda (ftype stype) (f ftype #f stype #f)) - #'(ftype ...) (datum (ftype ...)))]) - (let ([alignment (apply max 1 (map ftd-alignment ftd*))]) - (make-ftd-union rtd/fptr - (and defid (symbol->string (syntax->datum defid))) - stype - (pad (apply max 0 (map ftd-size ftd*)) alignment) - alignment - (map cons id* ftd*))))] - [(array-kwd ?n ftype) - (eq? (datum array-kwd) 'array) - (let ([n (datum ?n)]) - (unless (and (integer? n) (exact? n) (>= n 0)) - (syntax-error #'?n "invalid array size")) - (let ([ftd (f #'ftype #f (datum ftype) #f)]) - (make-ftd-array ftd - (and defid (symbol->string (syntax->datum defid))) - stype - (* n (ftd-size ftd)) - (ftd-alignment ftd) - n ftd)))] - [(bits-kwd (field-name signedness bits) ...) - (eq? (datum bits-kwd) 'bits) - (let () - (define parse-fields - (lambda () - (define signed? - (lambda (s) - (case (syntax->datum s) - [(signed) #t] - [(unsigned) #f] - [else (syntax-error s "invalid bit-field signedness specifier")]))) - (let f ([id* (expand-field-names #'(field-name ...))] - [s* #'(signedness ...)] - [bits* #'(bits ...)] - [bit-offset 0]) - (if (null? id*) - (values bit-offset '()) - (let ([bits (syntax->datum (car bits*))]) - (unless (and (fixnum? bits) (fx>= bits 1)) - (syntax-error (car bits*) "invalid bit-field bit count")) - (let-values ([(bit-size field*) (f (cdr id*) (cdr s*) (cdr bits*) (+ bit-offset bits))]) - (values bit-size - (let ([start (if (eq? (native-endianness) (if swap? 'little 'big)) - (- bit-size bit-offset bits) - bit-offset)]) - (cons (list (car id*) (signed? (car s*)) start (+ start bits)) - field*))))))))) - (let-values ([(bit-size field*) (parse-fields)]) - (unless (memq bit-size '(8 16 24 32 40 48 56 64)) - (syntax-error ftype "bit counts do not add up to 8, 16, 32, or 64")) - (let ([offset (fxsrl bit-size 3)]) - (make-ftd-bits rtd/fptr - (and defid (symbol->string (syntax->datum defid))) - stype offset (alignment (constant max-integer-alignment) offset) - (and swap? (fx> offset 1)) field*))))] - [(*-kwd ftype) - (eq? (datum *-kwd) '*) - (cond - [(and (identifier? #'ftype) - (assp (lambda (x) (bound-identifier=? #'ftype x)) def-alist)) => - (lambda (a) - (if (ftd? (cdr a)) - (make-ftd-pointer rtd/fptr - (and defid (symbol->string (syntax->datum defid))) - stype pointer-size pointer-alignment (cdr a)) - (let ([ftd (make-ftd-pointer rtd/fptr - (and defid (symbol->string (syntax->datum defid))) - stype pointer-size pointer-alignment #f)]) - (set-cdr! a (cons ftd (cdr a))) - ftd)))] - [else (make-ftd-pointer rtd/fptr - (and defid (symbol->string (syntax->datum defid))) - stype pointer-size pointer-alignment (f #'ftype #f (datum ftype) #t))])] - [(function-kwd (arg-type ...) result-type) - (eq? (datum function-kwd) 'function) - (f #'(function-kwd #f (arg-type ...) result-type) #f stype funok?)] - [(function-kwd conv ... (arg-type ...) result-type) - (eq? (datum function-kwd) 'function) - (let () - (define filter-type - (lambda (r x result?) - (let ([what (if result? 'result 'argument)]) - (or ($fp-filter-type (expand-fp-ftype 'function-ftype what r x def-alist) result?) - (syntax-error x (format "invalid function-ftype ~s type specifier" what)))))) - (unless funok? (syntax-error ftype "unexpected function ftype outside pointer field")) - (make-ftd-function rtd/fptr - (and defid (symbol->string (syntax->datum defid))) - stype #f #f - ($filter-conv 'function-ftype #'(conv ...)) - (map (lambda (x) (filter-type r x #f)) #'(arg-type ...)) - (filter-type r #'result-type #t)))] - [(packed-kwd ftype) - (eq? (datum packed-kwd) 'packed) - (f/flags #'ftype #f stype #t swap? funok?)] - [(unpacked-kwd ftype) - (eq? (datum unpacked-kwd) 'unpacked) - (f/flags #'ftype #f stype #f swap? funok?)] - [(endian-kwd ?eness ftype) - (eq? (datum endian-kwd) 'endian) - (let ([eness (datum ?eness)]) - (unless (memq eness '(big little native)) - (syntax-error #'?eness "invalid endianness")) - (let ([swap? (and (not (eq? eness 'native)) - (not (eq? eness (constant native-endianness))))]) - (f/flags #'ftype #f stype packed? swap? funok?)))] - [_ (syntax-error ftype "invalid ftype")])))))])) - (define expand-fp-ftype - (lambda (who what r ftype def-alist) - (syntax-case ftype () - [(*/&-kwd ftype-name) - (and (or (eq? (datum */&-kwd) '*) - (eq? (datum */&-kwd) '&)) - (identifier? #'ftype-name)) - (let* ([stype (syntax->datum ftype)] - [ftd - (cond - [(assp (lambda (x) (bound-identifier=? #'ftype-name x)) def-alist) => - (lambda (a) - (if (ftd? (cdr a)) - (make-ftd-pointer rtd/fptr #f stype pointer-size pointer-alignment (cdr a)) - (let ([ftd (make-ftd-pointer rtd/fptr #f stype pointer-size pointer-alignment #f)]) - (set-cdr! a (cons ftd (cdr a))) - ftd)))] - [(expand-ftype-name r #'ftype-name #f) => - (lambda (ftd) - (make-ftd-pointer rtd/fptr #f stype pointer-size pointer-alignment ftd))] - [else (syntax-error #'ftype-name (format "unrecognized ~s ~s ftype name" who what))])]) - ;; Scheme-side argument is a pointer to a value, but foreign side has two variants: - (if (eq? (datum */&-kwd) '&) - (cond - [(ftd-array? (ftd-pointer-ftd ftd)) - (syntax-error ftype (format "array value invalid as ~a ~s" who what))] - [else - (box ftd)]) ; boxed ftd => pass/receive the value (as opposed to a pointer to the value) - ftd))] ; plain ftd => pass/receive a pointer to the value - [_ (cond - [(and (identifier? ftype) (expand-ftype-name r ftype #f)) => - (lambda (ftd) - (unless (ftd-base? ftd) - (syntax-error ftype (format "invalid (non-base) ~s ~s ftype" who what))) - (when (ftd-base-swap? ftd) - (syntax-error ftype (format "invalid (swapped) ~s ~s ftype" who what))) - (ftd-base-type ftd))] - [else (syntax->datum ftype)])]))) - (define-who indirect-ftd-pointer - (lambda (x) - (cond - [(ftd? x) - (if (ftd-pointer? x) - (ftd-pointer-ftd x) - ($oops who "~s is not an ftd-pointer" x))] - [(box? x) - (box (indirect-ftd-pointer (unbox x)))] - [else x]))) - (define-who expand-ftype-defns - (lambda (r defid* ftype*) - (define patch-pointer-ftds! - (lambda (id ftd) - (lambda (pointer-ftd) - (ftd-pointer-ftd-set! pointer-ftd ftd)))) - (let ([alist (map list defid*)]) - (for-each - (lambda (defid ftype a) - (let ([ftd (expand-ftype r alist defid ftype)]) - (for-each (patch-pointer-ftds! defid ftd) (cdr a)) - (set-cdr! a ftd))) - defid* ftype* alist) - (map cdr alist)))) - (define unsigned-type - (lambda (size) - (case size - [(1) 'unsigned-8] - [(2) 'unsigned-16] - [(3) 'unsigned-24] - [(4) 'unsigned-32] - [(5) 'unsigned-40] - [(6) 'unsigned-48] - [(7) 'unsigned-56] - [(8) 'unsigned-64] - [else ($oops 'unsigned-type "unexpected size ~s" size)]))) - (define-record-type src-info - (nongenerative #{src-info sls7d75lyfm0jejerbq3n-0}) - (sealed #f) - (fields src) - (protocol - (lambda (new) - (lambda (expr) - (new - (let ([a (syntax->annotation expr)]) - (and (and a (fxlogtest (annotation-flags a) (constant annotation-debug))) - (annotation-source a)))))))) - (define-record-type field-info - (parent src-info) - (nongenerative #{field-info sls7d75lyfm0jejerbq3n-1}) - (sealed #t) - (fields type) - (protocol - (lambda (pargs->new) - (lambda (type expr) - ((pargs->new expr) type))))) - (define-record-type ftd-info - (parent src-info) - (nongenerative #{ftd-info sls7d75lyfm0jejerbq3n-2}) - (sealed #t) - (fields who ftd) - (protocol - (lambda (pargs->new) - (lambda (whoid expr ftd) - ((pargs->new expr) (syntax->datum whoid) ftd))))) - (define-record-type index-info - (parent src-info) - (nongenerative #{index-info sls7d75lyfm0jejerbq3n-3}) - (sealed #t) - (fields who ftd pointer?) - (protocol - (lambda (pargs->new) - (lambda (whoid expr ftd pointer?) - ((pargs->new expr) (syntax->datum whoid) ftd pointer?))))) - (record-writer rtd/ftd - (lambda (x p wr) - (fprintf p "#" (record-type-name x)))) - (record-writer rtd/fptr - (lambda (x p wr) - (fprintf p "#" (record-type-name (record-rtd x)) ($ftype-pointer-address x)))) - (set! $verify-ftype-address - (lambda (who addr) - (define address? - (lambda (x) - (constant-case address-bits - [(32) ($integer-32? x)] - [(64) ($integer-64? x)]))) - (unless (address? addr) - (if (or (procedure? addr) (string? addr)) - ($oops who "non-function ftype with ~s address" addr) - ($oops who "invalid address ~s" addr))))) - (set! $verify-ftype-pointer - (lambda (info fptr) - (unless (record? fptr (ftd-info-ftd info)) - ($source-violation (ftd-info-who info) (src-info-src info) #t - (if ($fptr? fptr) - "ftype mismatch for ~s" - "~s is not an ftype pointer") - fptr)))) - (set! $invalid-ftype-index - (lambda (info i) - ($source-violation (index-info-who info) (src-info-src info) #t - "invalid index ~s for ~:[~;indirection of ~]~s" i (index-info-pointer? info) (index-info-ftd info)))) - (set! $trans-define-ftype - (lambda (x) - (lambda (r) - (syntax-case x () - [(_ ftype-name ftype) - (identifier? #'ftype-name) - #`(define-syntax ftype-name - (make-compile-time-value - '#,(car (expand-ftype-defns r #'(ftype-name) #'(ftype)))))] - [(_ [ftype-name ftype] ...) - (andmap identifier? #'(ftype-name ...)) - (with-syntax ([(ftd ...) (expand-ftype-defns r #'(ftype-name ...) #'(ftype ...))]) - #'(begin - (define-syntax ftype-name - (make-compile-time-value 'ftd)) - ...))])))) - (set! $trans-make-ftype-pointer - (lambda (x) - (lambda (r) - (syntax-case x () - [(_ ftype ?addr) - (identifier? #'ftype) - (let ([ftd (expand-ftype-name r #'ftype)]) - (with-syntax ([addr-expr - (if (ftd-function? ftd) - #`(let ([x ?addr]) - (cond - ;; we need to make a code object, lock it, set addr to - ;; (foreign-callable-entry-point code-object) - [(procedure? x) - (let ([co #,($make-foreign-callable 'make-ftype-pointer - (ftd-function-conv* ftd) - #'x - (map indirect-ftd-pointer (ftd-function-arg-type* ftd)) - (indirect-ftd-pointer (ftd-function-result-type ftd)))]) - (lock-object co) - (foreign-callable-entry-point co))] - ;; otherwise, it is a string, so lookup the foreign-entry - [(string? x) (foreign-entry x)] - ;; otherwise, assume it is an address, let normal check - ;; complain otherwise - [else x])) - #'?addr)]) - #`($make-fptr '#,ftd - #,(if (or (fx= (optimize-level) 3) - (syntax-case #'addr-expr (ftype-pointer-address) - [(ftype-pointer-address x) #t] - [else #f])) - #'addr-expr - #'(let ([addr addr-expr]) - ($verify-ftype-address 'make-ftype addr) - addr)))))])))) - (set! $trans-ftype-pointer? - (lambda (x) - (lambda (r) - (syntax-case x () - [(_ x) #`(record? x '#,rtd/fptr)] - [(_ ftype x) (identifier? #'ftype) #`(record? x '#,(expand-ftype-name r #'ftype))])))) - (set-who! ftype-pointer-address - (lambda (fptr) - (unless ($fptr? fptr) ($oops who "~s is not an ftype pointer" fptr)) - ($ftype-pointer-address fptr))) - (set-who! ftype-pointer-null? - (lambda (fptr) - (unless ($fptr? fptr) ($oops who "~s is not an ftype pointer" fptr)) - (#3%ftype-pointer-null? fptr))) - (set-who! ftype-pointer=? - (lambda (fptr1 fptr2) - (unless ($fptr? fptr1) ($oops who "~s is not an ftype pointer" fptr1)) - (unless ($fptr? fptr2) ($oops who "~s is not an ftype pointer" fptr2)) - (#3%ftype-pointer=? fptr1 fptr2))) - (set-who! ftype-pointer-ftype - (lambda (fptr) - (unless ($fptr? fptr) ($oops who "~s is not an ftype pointer" fptr)) - (ftd-stype (record-rtd fptr)))) - (set-who! ftype-pointer->sexpr - (lambda (fptr) - (module (record replay) - (define ht (make-eqv-hashtable)) - (define-syntax record - (syntax-rules () - [(_ ?fptr expr) - (let ([fptr ?fptr]) - (let ([addr (ftype-pointer-address fptr)]) - (cond - [(hashtable-ref ht addr #f) => (lambda (x) fptr)] - [else - (hashtable-set! ht addr #t) - (let ([x expr]) - (hashtable-set! ht addr x) - x)])))])) - (define replay - (lambda (x) - (let f ([x x]) - (if ($fptr? x) - (hashtable-ref ht (ftype-pointer-address x) #f) - (begin - (when (pair? x) - (set-car! x (f (car x))) - (set-cdr! x (f (cdr x)))) - x))) - x))) - (unless ($fptr? fptr) ($oops who "~s is not an ftype pointer" fptr)) - (replay - (let fptr->sexpr ([fptr fptr]) - (record fptr - (let f ([fptr fptr] [ftd (record-rtd fptr)] [offset 0]) - (cond - [(ftd-struct? ftd) - `(struct - ,@(map (lambda (field) - (if (car field) - `(,(car field) ,(f fptr (caddr field) (+ offset (cadr field)))) - '(_ _))) - (ftd-struct-field* ftd)))] - [(ftd-union? ftd) - `(union - ,@(map (lambda (field) - (if (car field) - `(,(car field) ,(f fptr (cdr field) offset)) - '(_ _))) - (ftd-union-field* ftd)))] - [(ftd-array? ftd) - (let ([n (ftd-array-length ftd)] - [ftd (ftd-array-ftd ftd)]) - (if (and (ftd-base? ftd) (memq (ftd-base-type ftd) '(char wchar))) - (let g ([i 0]) - (if (fx= i n) - (make-string n) - (let ([c (f fptr ftd (+ offset (* i (ftd-size ftd))))]) - (if (or (eq? c 'invalid) (eqv? c #\nul)) - (if (fx= i 0) `(array ,n invalid) (make-string i)) - (let ([s (g (fx+ i 1))]) - (string-set! s i c) - s))))) - `(array ,n - ,@(let g ([i 0]) - (if (fx= i n) - '() - (cons (f fptr ftd (+ offset (* i (ftd-size ftd)))) - (g (fx+ i 1))))))))] - [(ftd-pointer? ftd) - (cond - [(guard (c [#t #f]) ($fptr-fptr-ref fptr offset (ftd-pointer-ftd ftd))) => - (lambda (fptr) - (if (zero? (ftype-pointer-address fptr)) - 'null - (let ([ftd (ftd-pointer-ftd ftd)]) - (if (and (ftd-base? ftd) (memq (ftd-base-type ftd) '(char wchar))) - (let g ([i 0]) - (let ([c (f fptr ftd (* i (ftd-size ftd)))]) - (if (or (eq? c 'invalid) (eqv? c #\nul)) - (if (fx= i 0) '(* invalid) (make-string i)) - (let ([s (g (fx+ i 1))]) - (string-set! s i c) - s)))) - `(* ,(fptr->sexpr fptr))))))] - [else 'invalid])] - [(ftd-function? ftd) - (let ([addr (ftype-pointer-address fptr)]) - `(function ,(or (foreign-address-name addr) addr)))] - [(ftd-bits? ftd) - (let ([type (unsigned-type (ftd-size ftd))]) - `(bits - ,@(map (lambda (field) - (apply - (lambda (id signed? start end) - (if id - `(,id - ,(guard (c [#t 'invalid]) - ($fptr-ref-bits type (ftd-bits-swap? ftd) signed? - fptr offset start end))) - '(_ _))) - field)) - (ftd-bits-field* ftd))))] - [(ftd-base? ftd) - (guard (c [#t 'invalid]) - ($fptr-ref (filter-foreign-type (ftd-base-type ftd)) - (ftd-base-swap? ftd) fptr offset))] - [else ($oops '$fptr->sexpr "unhandled ftd ~s" ftd)]))))))) - (set! $unwrap-ftype-pointer - (lambda (fptr) - (let f ([ftd (record-rtd fptr)]) - (cond - [(ftd-struct? ftd) - `(struct - ,@(map (lambda (field) - `(,(car field) . ,($fptr-&ref fptr (cadr field) (caddr field)))) - (ftd-struct-field* ftd)))] - [(ftd-union? ftd) - `(union - ,@(map (lambda (field) - `(,(car field) . ,($fptr-&ref fptr 0 (cdr field)))) - (ftd-union-field* ftd)))] - [(ftd-array? ftd) - (let ([n (ftd-array-length ftd)] - [ftd (ftd-array-ftd ftd)]) - `(array ,n - ,(lambda (i) - (unless (and (fixnum? i) (if (fx= n 0) (fx>= i 0) ($fxu< i n))) - (errorf '$dump-foreign-type "invalid index ~s for array of length ~s" i n)) - ($fptr-&ref fptr (* i (ftd-size ftd)) ftd))))] - [(ftd-pointer? ftd) - (let ([ftd (ftd-pointer-ftd ftd)]) - `(* ,(lambda () ($fptr-fptr-ref fptr 0 ftd)) - ,(lambda (who v) - ($verify-ftype-pointer (make-ftd-info who #f ftd) v) - (#3%$fptr-fptr-set! fptr 0 v))))] - [(ftd-function? ftd) - (let ([addr (ftype-pointer-address fptr)]) - `(function ,(foreign-address-name addr)))] - [(ftd-bits? ftd) - (let ([type (unsigned-type (ftd-size ftd))]) - `(bits - ,@(map (lambda (field) - (apply - (lambda (id signed? start end) - `(,id ,(lambda () - (guard (c [#t 'invalid]) - ($fptr-ref-bits type (ftd-bits-swap? ftd) signed? fptr 0 start end))) - ,(lambda (v) - (#2%$fptr-set-bits! type (ftd-bits-swap? ftd) fptr 0 - start end v)))) - field)) - (ftd-bits-field* ftd))))] - [(ftd-base? ftd) - (let ([type (filter-foreign-type (ftd-base-type ftd))]) - `(base - ,type - ,(lambda () (guard (c [#t 'invalid]) ($fptr-ref type (ftd-base-swap? ftd) fptr 0))) - ,(lambda (v) (#2%$fptr-set! (ftd-base-type ftd) type (ftd-base-swap? ftd) fptr 0 v))))] - [else ($oops '$unwrap-ftype-pointer "unhandled ftd ~s" ftd)])))) - (set! $trans-ftype-sizeof - (lambda (x) - (lambda (r) - (syntax-case x () - [(_ ftype) - (identifier? #'ftype) - (let ([ftd (expand-ftype-name r #'ftype)]) - (when (ftd-function? ftd) - ($oops 'ftype-sizeof "function ftypes have unknown size")) - (ftd-size ftd))])))) - (set! $ftd? - (lambda (x) - (ftd? x))) - (set! $ftd-as-box? ; represents `(& )` from `$expand-fp-ftype` - (lambda (x) - (and (box? x) (ftd? (unbox x))))) - (set! $ftd-size - (lambda (x) - (ftd-size x))) - (set! $ftd-alignment - (lambda (x) - (ftd-alignment x))) - (set! $ftd-compound? - (lambda (x) - (or (ftd-struct? x) - (ftd-union? x) - (ftd-array? x)))) - (set! $ftd-unsigned? - (lambda (x) - (and (ftd-base? x) - (case (ftd-base-type x) - [(unsigned-8 unsigned-16 unsigned-32 unsigned-64) #t] - [else #f])))) - (set! $ftd->members - (lambda (x) - ;; Currently used for x86_64 and arm32 ABI: Returns a list of - ;; (list 'integer/'float size offset) - (let loop ([x x] [offset 0] [accum '()]) - (cond - [(ftd-base? x) - (cons (list (case (ftd-base-type x) - [(double double-float float single-float) - 'float] - [else 'integer]) - (ftd-size x) - offset) - accum)] - [(ftd-struct? x) - (let struct-loop ([field* (ftd-struct-field* x)] [accum accum]) - (cond - [(null? field*) accum] - [else (let* ([fld (car field*)] - [sub-ftd (caddr fld)] - [sub-offset (cadr fld)]) - (struct-loop (cdr field*) - (loop sub-ftd (+ offset sub-offset) accum)))]))] - [(ftd-union? x) - (let union-loop ([field* (ftd-union-field* x)] [accum accum]) - (cond - [(null? field*) accum] - [else (let* ([fld (car field*)] - [sub-ftd (cdr fld)]) - (union-loop (cdr field*) - (loop sub-ftd offset accum)))]))] - [(ftd-array? x) - (let ([elem-ftd (ftd-array-ftd x)]) - (let array-loop ([len (ftd-array-length x)] [offset offset] [accum accum]) - (cond - [(fx= len 0) accum] - [else (array-loop (fx- len 1) - (+ offset (ftd-size elem-ftd)) - (loop elem-ftd offset accum))])))] - [else (cons (list 'integer (ftd-size x) offset) accum)])))) - (set! $ftd-atomic-category - (lambda (x) - ;; Currently used for PowerPC32 ABI - (cond - [(ftd-base? x) - (case (ftd-base-type x) - [(double double-float float single-float) - 'float] - [(unsigned-short unsigned unsigned-int - unsigned-long unsigned-long-long - unsigned-8 unsigned-16 unsigned-32 unsigned-64) - 'unsigned] - [else 'integer])] - [else 'integer]))) - (set! $expand-fp-ftype ; for foreign-procedure, foreign-callable - (lambda (who what r ftype) - (indirect-ftd-pointer - (expand-fp-ftype who what r ftype '())))) - (let () - (define-who ftype-access-code - (lambda (whoid ftd a* fptr-expr offset) - (let loop ([ftd ftd] [a* a*] [fptr-expr fptr-expr] [offset offset] [idx* '()]) - (if (null? a*) - (values fptr-expr offset ftd idx* #f) - (let ([a (car a*)]) - (cond - [(ftd-struct? ftd) - (let ([s (syntax->datum a)]) - (cond - [(and (symbol? s) (assq s (ftd-struct-field* ftd))) => - (lambda (field) - (let ([offset #`(#3%fx+ #,offset #,(cadr field))] [ftd (caddr field)]) - (loop ftd (cdr a*) fptr-expr offset idx*)))] - [else (syntax-error a "unexpected accessor")]))] - [(ftd-union? ftd) - (let ([s (syntax->datum a)]) - (cond - [(and (symbol? s) (assq s (ftd-union-field* ftd))) => - (lambda (field) - (let ([ftd (cdr field)]) - (loop ftd (cdr a*) fptr-expr offset idx*)))] - [else (syntax-error a "unexpected accessor")]))] - [(ftd-array? ftd) - (let ([elt-ftd (ftd-array-ftd ftd)] [len (ftd-array-length ftd)]) - (if (memv (syntax->datum a) '(* 0)) - (loop elt-ftd (cdr a*) fptr-expr offset idx*) - (let ([a-id (car (generate-temporaries (list #'i)))]) - (loop elt-ftd (cdr a*) fptr-expr - #`(#3%fx+ #,offset (#3%fx* #,a-id #,(ftd-size elt-ftd))) - (cons (list ftd a-id a len) idx*)))))] - [(ftd-pointer? ftd) - (let ([elt-ftd (ftd-pointer-ftd ftd)]) - (let ([fptr-expr #`(#3%$fptr-fptr-ref #,fptr-expr #,offset '#,elt-ftd)]) - (if (memv (syntax->datum a) '(* 0)) - (loop elt-ftd (cdr a*) fptr-expr 0 idx*) - (let ([a-id (car (generate-temporaries (list #'i)))]) - (loop elt-ftd (cdr a*) fptr-expr - (trans-idx a-id a elt-ftd (make-index-info whoid a ftd #f)) - (cons (list ftd a-id a #f) idx*))))))] - [(ftd-bits? ftd) - (let ([s (syntax->datum a)]) - (cond - [(and (symbol? s) (assq s (ftd-bits-field* ftd))) => - (lambda (field) - (unless (null? (cdr a*)) - (syntax-error (cadr a*) "unexpected accessor")) - (values fptr-expr offset ftd idx* field))] - [else (syntax-error a "unexpected accessor")]))] - [(ftd-base? ftd) (syntax-error a "unexpected accessor")] - [(ftd-function? ftd) (syntax-error a "unexpected accessor")] - [else ($oops who "unhandled ftd ~s" ftd)])))))) - (define trans-bitfield - (lambda (ftd signed? offset start end do-base do-bits) - (define (little-endian?) - (constant-case native-endianness - [(little) (not (ftd-bits-swap? ftd))] - [(big) (ftd-bits-swap? ftd)])) - (let ([width (fx- end start)]) - (cond - [(and (fx= width 8) (fx= (mod start 8) 0)) - (do-base (if signed? 'integer-8 'unsigned-8) #f - #`(fx+ #,offset - #,(if (little-endian?) - (div start 8) - (fx- (ftd-size ftd) (div start 8) 1))))] - [(and (fx= width 16) (fx= (mod start 16) 0)) - (do-base (if signed? 'integer-16 'unsigned-16) (ftd-bits-swap? ftd) - #`(fx+ #,offset - #,(if (little-endian?) - (div start 8) - (fx- (ftd-size ftd) (div start 8) 2))))] - [(and (fx= width 32) (fx= (mod start 32) 0)) - (do-base (if signed? 'integer-32 'unsigned-32) (ftd-bits-swap? ftd) - #`(fx+ #,offset - #,(if (little-endian?) - (div start 8) - (fx- (ftd-size ftd) (div start 8) 4))))] - [(and (fx= width 64) (fx= start 0)) - (do-base (if signed? 'integer-64 'unsigned-64) (ftd-bits-swap? ftd) offset)] - [else - (or (and (and (fx= (ftd-size ftd) 8) (fx= (constant ptr-bits) 32)) - (cond - [(and (fx>= start 0) (fx<= end 32)) - (do-bits 4 (if (little-endian?) offset #`(fx+ #,offset 4)) start end)] - [(and (fx>= start 32) (fx<= end 64)) - (do-bits 4 (if (little-endian?) #`(fx+ #,offset 4) offset) (fx- start 32) (fx- end 32))] - [else #f])) - (do-bits (ftd-size ftd) offset start end))])))) - (define trans-idx - (lambda (?idx ?orig-idx ftd info) - (if (memv (syntax->datum ?idx) '(* 0)) - 0 - (if (ftd-function? ftd) - (syntax-error ?orig-idx "cannot calculate offset for function index") - (let ([size (ftd-size ftd)]) - (if (fx= (optimize-level) 3) - #`(#3%fx* #,size #,?idx) - #`(let ([idx #,?idx]) - (or (and (fixnum? idx) - (let ([offset (* #,size idx)]) - (and (fixnum? offset) - (fixnum? (+ offset #,(fx- size 1))) - offset))) - ($invalid-ftype-index '#,info idx))))))))) - (set! $trans-ftype-&ref - (lambda (q) - (define trans - (lambda (ftype a* fptr-expr ?idx) - (lambda (r) - (let ([ftd (expand-ftype-name r ftype)]) - (let ([fptr-expr (if (fx= (optimize-level) 3) - fptr-expr - #`(let ([fptr #,fptr-expr]) - ($verify-ftype-pointer '#,(make-ftd-info 'ftype-&ref fptr-expr ftd) fptr) - fptr))]) - (if (and (null? a*) (memv (syntax->datum ?idx) '(* 0))) - fptr-expr - #`(let ([offset #,(trans-idx ?idx ?idx ftd (make-index-info #'ftype-&ref ?idx ftd #t))]) - #,(let-values ([(fptr-expr offset ftd idx* bitfield) - (ftype-access-code #'ftype-&ref ftd a* fptr-expr #'offset)]) - (when bitfield (syntax-error q "cannot take address of bit field")) - (with-syntax ([((containing-ftd a-id a len) ...) idx*]) - (with-syntax ([(info ...) (map (lambda (a containing-ftd) (make-index-info 'ftype-&ref a containing-ftd #f)) #'(a ...) #'(containing-ftd ...))]) - #`(let ([a-id a] ...) - (unless (or #,(fx= (optimize-level) 3) (not len)) - (unless (and (fixnum? a-id) (if (eqv? len 0) (fx>= a-id 0) ($fxu< a-id len))) - ($invalid-ftype-index 'info a-id))) - ... - (#3%$fptr-&ref #,fptr-expr #,offset '#,ftd)))))))))))) - (syntax-case q () - [(_ ftype (a ...) fptr-expr) - (identifier? #'ftype) - (trans #'ftype #'(a ...) #'fptr-expr 0)] - [(_ ftype (a ...) fptr-expr ?idx) - (identifier? #'ftype) - (trans #'ftype #'(a ...) #'fptr-expr #'?idx)]))) - (set! $trans-ftype-ref - (lambda (q) - (define trans - (lambda (ftype a* fptr-expr ?idx) - (lambda (r) - (let ([ftd (expand-ftype-name r ftype)]) - (let ([fptr-expr (if (fx= (optimize-level) 3) - fptr-expr - #`(let ([fptr #,fptr-expr]) - ($verify-ftype-pointer '#,(make-ftd-info 'ftype-ref fptr-expr ftd) fptr) - fptr))]) - #`(let ([offset #,(trans-idx ?idx ?idx ftd (make-index-info #'ftype-ref ?idx ftd #t))]) - #,(let-values ([(fptr-expr offset ftd idx* bitfield) - (ftype-access-code #'ftype-ref ftd a* fptr-expr #'offset)]) - (define (do-base type swap? offset) - (with-syntax ([$fptr-ref-x (datum->syntax #'kwd - (string->symbol - (format "$fptr-ref-~:[~;swap-~]~a" - swap? type)))]) - #`(#3%$fptr-ref-x #,fptr-expr #,offset))) - (with-syntax ([((containing-ftd a-id a len) ...) idx*]) - (with-syntax ([(info ...) (map (lambda (a containing-ftd) (make-index-info 'ftype-ref a containing-ftd #f)) #'(a ...) #'(containing-ftd ...))]) - #`(let ([a-id a] ...) - (unless (or #,(fx= (optimize-level) 3) (not len)) - (unless (and (fixnum? a-id) (if (eqv? len 0) (fx>= a-id 0) ($fxu< a-id len))) - ($invalid-ftype-index 'info a-id))) - ... - #,(cond - [bitfield - (apply - (lambda (id signed? start end) - (trans-bitfield ftd signed? offset start end do-base - (lambda (size offset start end) - (with-syntax ([$fptr-ref-bits-x (datum->syntax #'* - (string->symbol - (format "$fptr-ref-~:[u~;i~]bits-~:[~;swap-~]~a" - signed? - (ftd-bits-swap? ftd) - (unsigned-type size))))]) - #`(#3%$fptr-ref-bits-x #,fptr-expr #,offset #,start #,end))))) - bitfield)] - [(ftd-base? ftd) (do-base (filter-foreign-type (ftd-base-type ftd)) (ftd-base-swap? ftd) offset)] - [(ftd-pointer? ftd) #`(#3%$fptr-fptr-ref #,fptr-expr #,offset '#,(ftd-pointer-ftd ftd))] - [(ftd-function? ftd) - ($make-foreign-procedure 'make-ftype-pointer - (ftd-function-conv* ftd) - #f - #`($fptr-offset-addr #,fptr-expr offset) - (map indirect-ftd-pointer (ftd-function-arg-type* ftd)) - (indirect-ftd-pointer (ftd-function-result-type ftd)))] - [else (syntax-error q "non-scalar value cannot be referenced")]))))))))))) - (syntax-case q () - [(_ ftype (a ...) fptr-expr) - (identifier? #'ftype) - (trans #'ftype #'(a ...) #'fptr-expr 0)] - [(_ ftype (a ...) fptr-expr ?idx) - (identifier? #'ftype) - (trans #'ftype #'(a ...) #'fptr-expr #'?idx)]))) - (set! $trans-ftype-set! - (lambda (q) - (define trans - (lambda (ftype a* fptr-expr ?idx val-expr) - (lambda (r) - (let ([ftd (expand-ftype-name r ftype)]) - (let ([fptr-expr (if (fx= (optimize-level) 3) - fptr-expr - #`(let ([fptr #,fptr-expr]) - ($verify-ftype-pointer '#,(make-ftd-info 'ftype-set! fptr-expr ftd) fptr) - fptr))]) - #`(let ([offset #,(trans-idx ?idx ?idx ftd (make-index-info #'ftype-set! ?idx ftd #t))] [val #,val-expr]) - #,(let-values ([(fptr-expr offset ftd idx* bitfield) - (ftype-access-code #'ftype-set! ftd a* fptr-expr #'offset)]) - (define (do-base orig-type) - (lambda (type swap? offset) - (with-syntax ([$fptr-set-x! (datum->syntax #'kwd - (string->symbol - (format "$fptr-set-~:[~;swap-~]~a!" - swap? type)))]) - #`($fptr-set-x! '#,(make-field-info orig-type val-expr) #,fptr-expr #,offset val)))) - (with-syntax ([((containing-ftd a-id a len) ...) idx*]) - (with-syntax ([(info ...) (map (lambda (a containing-ftd) (make-index-info 'ftype-set! a containing-ftd #f)) #'(a ...) #'(containing-ftd ...))]) - #`(let ([a-id a] ...) - (unless (or #,(fx= (optimize-level) 3) (not len)) - (unless (and (fixnum? a-id) (if (eqv? len 0) (fx>= a-id 0) ($fxu< a-id len))) - ($invalid-ftype-index 'info a-id))) - ... - #,(cond - [bitfield - (apply - (lambda (id signed? start end) - (trans-bitfield ftd signed? offset start end (do-base 'bit-field) - (lambda (size offset start end) - (with-syntax ([$fptr-set-bits-x! (datum->syntax #'* - (string->symbol - (format "$fptr-set-bits-~:[~;swap-~]~a!" - (ftd-bits-swap? ftd) - (unsigned-type size))))]) - #`($fptr-set-bits-x! #,fptr-expr #,offset #,start #,end val))))) - bitfield)] - [(ftd-base? ftd) - (let ([orig-type (ftd-base-type ftd)]) - ((do-base orig-type) (filter-foreign-type orig-type) (ftd-base-swap? ftd) offset))] - [(ftd-pointer? ftd) - #`(begin - (unless #,(fx= (optimize-level) 3) - ($verify-ftype-pointer '#,(make-ftd-info 'ftype-set! val-expr (ftd-pointer-ftd ftd)) val)) - (#3%$fptr-fptr-set! #,fptr-expr #,offset val))] - [else (syntax-error q "non-scalar value cannot be assigned")]))))))))))) - (syntax-case q () - [(_ ftype (a ...) fptr-expr val-expr) - (identifier? #'ftype) - (trans #'ftype #'(a ...) #'fptr-expr 0 #'val-expr)] - [(_ ftype (a ...) fptr-expr ?idx val-expr) - (identifier? #'ftype) - (trans #'ftype #'(a ...) #'fptr-expr #'?idx #'val-expr)]))) - (set-who! $trans-ftype-locked-op! - (lambda (who q prim) - (define trans - (lambda (ftype a* fptr-expr ?idx) - (lambda (r) - (let ([ftd (expand-ftype-name r ftype)]) - (let ([fptr-expr (if (fx= (optimize-level) 3) - fptr-expr - #`(let ([fptr #,fptr-expr]) - ($verify-ftype-pointer '#,(make-ftd-info who fptr-expr ftd) fptr) - fptr))]) - #`(let ([offset #,(trans-idx ?idx ?idx ftd (make-index-info who ?idx ftd #t))]) - #,(let-values ([(fptr-expr offset ftd idx* bitfield) - (ftype-access-code who ftd a* fptr-expr #'offset)]) - (with-syntax ([((containing-ftd a-id a len) ...) idx*]) - (with-syntax ([(info ...) (map (lambda (a containing-ftd) (make-index-info who a containing-ftd #f)) #'(a ...) #'(containing-ftd ...))]) - #`(let ([a-id a] ...) - (unless (or #,(fx= (optimize-level) 3) (not len)) - (unless (and (fixnum? a-id) (if (eqv? len 0) (fx>= a-id 0) ($fxu< a-id len))) - ($invalid-ftype-index 'info a-id))) - ... - #,(cond - [(ftd-base? ftd) - (let ([type (filter-foreign-type (ftd-base-type ftd))]) - (unless (memq type - (constant-case ptr-bits - [(64) '(unsigned-64 integer-64)] - [(32) '(unsigned-32 integer-32)])) - (syntax-error q "locked operation on non-integer or non-word-size field unsupported")) - (when (ftd-base-swap? ftd) - (syntax-error q "locked operation on swapped field unsupported")) - #`(($primitive 3 #,prim) #,fptr-expr #,offset))] - [else (syntax-error q "locked operation on non-base-type field unsupported")]))))))))))) - (syntax-case q () - [(_ ftype (a ...) fptr-expr) - (identifier? #'ftype) - (trans #'ftype #'(a ...) #'fptr-expr 0)] - [(_ ftype (a ...) fptr-expr ?idx) - (identifier? #'ftype) - (trans #'ftype #'(a ...) #'fptr-expr #'?idx)]))) - (set! $trans-ftype-guardian - (lambda (q) - (lambda (r) - (syntax-case q () - [(_ ftype) - (identifier? #'ftype) - (let ([ftd (expand-ftype-name r #'ftype)]) - (unless (let lockable? ([ftd ftd]) - (cond - [(ftd-base? ftd) - (let ([type (filter-foreign-type (ftd-base-type ftd))]) - (and (memq type - (constant-case ptr-bits - [(64) '(unsigned-64 integer-64)] - [(32) '(unsigned-32 integer-32)])) - (not (ftd-base-swap? ftd))))] - [(ftd-struct? ftd) - (let ([ls (ftd-struct-field* ftd)]) - (if (null? ls) - #f - (lockable? (caddr (car ls)))))] - [(ftd-union? ftd) (ormap lockable? (map cdr (ftd-union-field* ftd)))] - [(ftd-array? ftd) (lockable? (ftd-array-ftd ftd))] - [else #f])) - (syntax-error q "first field must be a word-sized integer with native endianness")) - #`(($primitive #,(if (fx= (optimize-level) 3) 3 2) $make-ftype-guardian) '#,ftd))]))))) - ; procedural entry point for inspector to simplify bootstrapping - (set! $ftype-pointer? (lambda (x) ($fptr? x))) - (set! $make-fptr - (lambda (ftd addr) - (#2%$make-fptr ftd addr))) - (set! $fptr-offset-addr - (lambda (fptr offset) - (#3%$fptr-offset-addr fptr offset))) - (set! $fptr-&ref - (lambda (fptr offset ftd) - (#3%$fptr-&ref fptr offset ftd))) - (set! $fptr-fptr-ref - (lambda (fptr offset ftd) - (#3%$fptr-fptr-ref fptr offset ftd))) - - (set! $fptr-ref-integer-8 - (lambda (fptr offset) - (#3%$fptr-ref-integer-8 fptr offset))) - (set! $fptr-ref-unsigned-8 - (lambda (fptr offset) - (#3%$fptr-ref-unsigned-8 fptr offset))) - - (set! $fptr-ref-integer-16 - (lambda (fptr offset) - (#3%$fptr-ref-integer-16 fptr offset))) - (set! $fptr-ref-unsigned-16 - (lambda (fptr offset) - (#3%$fptr-ref-unsigned-16 fptr offset))) - (set! $fptr-ref-swap-integer-16 - (lambda (fptr offset) - (#3%$fptr-ref-swap-integer-16 fptr offset))) - (set! $fptr-ref-swap-unsigned-16 - (lambda (fptr offset) - (#3%$fptr-ref-swap-unsigned-16 fptr offset))) - - (set! $fptr-ref-integer-24 - (lambda (fptr offset) - (#3%$fptr-ref-integer-24 fptr offset))) - (set! $fptr-ref-unsigned-24 - (lambda (fptr offset) - (#3%$fptr-ref-unsigned-24 fptr offset))) - (set! $fptr-ref-swap-integer-24 - (lambda (fptr offset) - (#3%$fptr-ref-swap-integer-24 fptr offset))) - (set! $fptr-ref-swap-unsigned-24 - (lambda (fptr offset) - (#3%$fptr-ref-swap-unsigned-24 fptr offset))) - - (set! $fptr-ref-integer-32 - (lambda (fptr offset) - (#3%$fptr-ref-integer-32 fptr offset))) - (set! $fptr-ref-unsigned-32 - (lambda (fptr offset) - (#3%$fptr-ref-unsigned-32 fptr offset))) - (set! $fptr-ref-swap-integer-32 - (lambda (fptr offset) - (#3%$fptr-ref-swap-integer-32 fptr offset))) - (set! $fptr-ref-swap-unsigned-32 - (lambda (fptr offset) - (#3%$fptr-ref-swap-unsigned-32 fptr offset))) - - (set! $fptr-ref-integer-40 - (lambda (fptr offset) - (#3%$fptr-ref-integer-40 fptr offset))) - (set! $fptr-ref-unsigned-40 - (lambda (fptr offset) - (#3%$fptr-ref-unsigned-40 fptr offset))) - (set! $fptr-ref-swap-integer-40 - (lambda (fptr offset) - (#3%$fptr-ref-swap-integer-40 fptr offset))) - (set! $fptr-ref-swap-unsigned-40 - (lambda (fptr offset) - (#3%$fptr-ref-swap-unsigned-40 fptr offset))) - - (set! $fptr-ref-integer-48 - (lambda (fptr offset) - (#3%$fptr-ref-integer-48 fptr offset))) - (set! $fptr-ref-unsigned-48 - (lambda (fptr offset) - (#3%$fptr-ref-unsigned-48 fptr offset))) - (set! $fptr-ref-swap-integer-48 - (lambda (fptr offset) - (#3%$fptr-ref-swap-integer-48 fptr offset))) - (set! $fptr-ref-swap-unsigned-48 - (lambda (fptr offset) - (#3%$fptr-ref-swap-unsigned-48 fptr offset))) - - (set! $fptr-ref-integer-56 - (lambda (fptr offset) - (#3%$fptr-ref-integer-56 fptr offset))) - (set! $fptr-ref-unsigned-56 - (lambda (fptr offset) - (#3%$fptr-ref-unsigned-56 fptr offset))) - (set! $fptr-ref-swap-integer-56 - (lambda (fptr offset) - (#3%$fptr-ref-swap-integer-56 fptr offset))) - (set! $fptr-ref-swap-unsigned-56 - (lambda (fptr offset) - (#3%$fptr-ref-swap-unsigned-56 fptr offset))) - - (set! $fptr-ref-integer-64 - (lambda (fptr offset) - (#3%$fptr-ref-integer-64 fptr offset))) - (set! $fptr-ref-unsigned-64 - (lambda (fptr offset) - (#3%$fptr-ref-unsigned-64 fptr offset))) - (set! $fptr-ref-swap-integer-64 - (lambda (fptr offset) - (#3%$fptr-ref-swap-integer-64 fptr offset))) - (set! $fptr-ref-swap-unsigned-64 - (lambda (fptr offset) - (#3%$fptr-ref-swap-unsigned-64 fptr offset))) - - (set! $fptr-ref-double-float - (lambda (fptr offset) - (#3%$fptr-ref-double-float fptr offset))) - (set! $fptr-ref-swap-double-float - (lambda (fptr offset) - (constant-case ptr-bits - [(64) (#3%$fptr-ref-swap-double-float fptr offset)] - [(32) (let ([bv (make-bytevector 8)]) - (bytevector-u64-set! bv 0 - (foreign-ref 'unsigned-64 ($ftype-pointer-address fptr) offset) - (if (eq? (constant native-endianness) 'big) 'little 'big)) - ($object-ref 'double-float bv (constant bytevector-data-disp)))]))) - - (set! $fptr-ref-single-float - (lambda (fptr offset) - (#3%$fptr-ref-single-float fptr offset))) - (set! $fptr-ref-swap-single-float - (lambda (fptr offset) - (constant-case ptr-bits - [(64) (#3%$fptr-ref-swap-single-float fptr offset)] - [(32) (let ([bv (make-bytevector 4)]) - (bytevector-u32-set! bv 0 - (foreign-ref 'unsigned-32 ($ftype-pointer-address fptr) offset) - (if (eq? (constant native-endianness) 'big) 'little 'big)) - ($object-ref 'single-float bv (constant bytevector-data-disp)))]))) - - (set! $fptr-ref-char - (lambda (fptr offset) - (#3%$fptr-ref-char fptr offset))) - - (set! $fptr-ref-wchar - (lambda (fptr offset) - (#3%$fptr-ref-wchar fptr offset))) - (set! $fptr-ref-swap-wchar - (lambda (fptr offset) - (#3%$fptr-ref-swap-wchar fptr offset))) - - (set! $fptr-ref-boolean - (lambda (fptr offset) - (#3%$fptr-ref-boolean fptr offset))) - (set! $fptr-ref-swap-boolean - (lambda (fptr offset) - (#3%$fptr-ref-swap-boolean fptr offset))) - - (set! $fptr-ref-fixnum - (lambda (fptr offset) - (#3%$fptr-ref-fixnum fptr offset))) - (set! $fptr-ref-swap-fixnum - (lambda (fptr offset) - (#3%$fptr-ref-swap-fixnum fptr offset))) - - (set-who! $fptr-ref - (lambda (ty swap? fptr offset) - (define-syntax proc - (lambda (x) - (syntax-case x (scheme-object) - [(_ scheme-object bytes pred) #'($oops who "unexpected type ~s" ty)] - [(_ type bytes pred) - (if (memq (datum type) '(char integer-8 unsigned-8)) - (datum->syntax #'* - (string->symbol - (format "$fptr-ref-~a" (datum type)))) - #`(if swap? - #,(datum->syntax #'* - (string->symbol - (format "$fptr-ref-swap-~a" (datum type)))) - #,(datum->syntax #'* - (string->symbol - (format "$fptr-ref-~a" (datum type))))))]))) - ((record-datatype cases ty proc - ($oops who "unrecognized type ~s" ty)) - fptr offset))) - - (set-who! $fptr-fptr-set! - (lambda (fptr offset val) - (#3%$fptr-fptr-set! fptr offset val))) - - (let () - (define invalid-value - (lambda (info val) - ($source-violation 'ftype-set! (src-info-src info) #t - "invalid value ~s for type ~s" val (field-info-type info)))) - (set! $fptr-set-integer-8! - (lambda (info fptr offset val) - (unless ($integer-8? val) (invalid-value info val)) - (#3%$fptr-set-integer-8! info fptr offset val))) - (set! $fptr-set-unsigned-8! - (lambda (info fptr offset val) - (unless ($integer-8? val) (invalid-value info val)) - (#3%$fptr-set-unsigned-8! info fptr offset val))) - - (set! $fptr-set-integer-16! - (lambda (info fptr offset val) - (unless ($integer-16? val) (invalid-value info val)) - (#3%$fptr-set-integer-16! info fptr offset val))) - (set! $fptr-set-unsigned-16! - (lambda (info fptr offset val) - (unless ($integer-16? val) (invalid-value info val)) - (#3%$fptr-set-unsigned-16! info fptr offset val))) - (set! $fptr-set-swap-integer-16! - (lambda (info fptr offset val) - (unless ($integer-16? val) (invalid-value info val)) - (#3%$fptr-set-swap-integer-16! info fptr offset val))) - (set! $fptr-set-swap-unsigned-16! - (lambda (info fptr offset val) - (unless ($integer-16? val) (invalid-value info val)) - (#3%$fptr-set-swap-unsigned-16! info fptr offset val))) - - (set! $fptr-set-integer-24! - (lambda (info fptr offset val) - (unless ($integer-24? val) (invalid-value info val)) - (#3%$fptr-set-integer-24! info fptr offset val))) - (set! $fptr-set-unsigned-24! - (lambda (info fptr offset val) - (unless ($integer-24? val) (invalid-value info val)) - (#3%$fptr-set-unsigned-24! info fptr offset val))) - (set! $fptr-set-swap-integer-24! - (lambda (info fptr offset val) - (unless ($integer-24? val) (invalid-value info val)) - (#3%$fptr-set-swap-integer-24! info fptr offset val))) - (set! $fptr-set-swap-unsigned-24! - (lambda (info fptr offset val) - (unless ($integer-24? val) (invalid-value info val)) - (#3%$fptr-set-swap-unsigned-24! info fptr offset val))) - - (set! $fptr-set-integer-32! - (lambda (info fptr offset val) - (unless ($integer-32? val) (invalid-value info val)) - (#3%$fptr-set-integer-32! info fptr offset val))) - (set! $fptr-set-unsigned-32! - (lambda (info fptr offset val) - (unless ($integer-32? val) (invalid-value info val)) - (#3%$fptr-set-unsigned-32! info fptr offset val))) - (set! $fptr-set-swap-integer-32! - (lambda (info fptr offset val) - (unless ($integer-32? val) (invalid-value info val)) - (#3%$fptr-set-swap-integer-32! info fptr offset val))) - (set! $fptr-set-swap-unsigned-32! - (lambda (info fptr offset val) - (unless ($integer-32? val) (invalid-value info val)) - (#3%$fptr-set-swap-unsigned-32! info fptr offset val))) - - (set! $fptr-set-integer-40! - (lambda (info fptr offset val) - (unless ($integer-40? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-integer-40! info fptr offset val)] - [(32) (foreign-set! 'integer-40 ($ftype-pointer-address fptr) offset val)]))) - (set! $fptr-set-unsigned-40! - (lambda (info fptr offset val) - (unless ($integer-40? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-unsigned-40! info fptr offset val)] - [(32) (foreign-set! 'unsigned-40 ($ftype-pointer-address fptr) offset val)]))) - (set! $fptr-set-swap-integer-40! - (lambda (info fptr offset val) - (unless ($integer-40? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-swap-integer-40! info fptr offset val)] - [(32) (let ([bv (make-bytevector 8)]) - ($object-set! 'integer-40 bv (constant bytevector-data-disp) val) - (foreign-set! 'unsigned-40 ($ftype-pointer-address fptr) offset - (bytevector-u40-ref bv 0 - (if (eq? (constant native-endianness) 'big) 'little 'big))))]))) - (set! $fptr-set-swap-unsigned-40! - (lambda (info fptr offset val) - (unless ($integer-40? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-swap-unsigned-40! info fptr offset val)] - [(32) (let ([bv (make-bytevector 8)]) - ($object-set! 'unsigned-40 bv (constant bytevector-data-disp) val) - (foreign-set! 'unsigned-40 ($ftype-pointer-address fptr) offset - (bytevector-u40-ref bv 0 - (if (eq? (constant native-endianness) 'big) 'little 'big))))]))) - - (set! $fptr-set-integer-48! - (lambda (info fptr offset val) - (unless ($integer-48? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-integer-48! info fptr offset val)] - [(32) (foreign-set! 'integer-48 ($ftype-pointer-address fptr) offset val)]))) - (set! $fptr-set-unsigned-48! - (lambda (info fptr offset val) - (unless ($integer-48? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-unsigned-48! info fptr offset val)] - [(32) (foreign-set! 'unsigned-48 ($ftype-pointer-address fptr) offset val)]))) - (set! $fptr-set-swap-integer-48! - (lambda (info fptr offset val) - (unless ($integer-48? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-swap-integer-48! info fptr offset val)] - [(32) (let ([bv (make-bytevector 8)]) - ($object-set! 'integer-48 bv (constant bytevector-data-disp) val) - (foreign-set! 'unsigned-48 ($ftype-pointer-address fptr) offset - (bytevector-u48-ref bv 0 - (if (eq? (constant native-endianness) 'big) 'little 'big))))]))) - (set! $fptr-set-swap-unsigned-48! - (lambda (info fptr offset val) - (unless ($integer-48? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-swap-unsigned-48! info fptr offset val)] - [(32) (let ([bv (make-bytevector 8)]) - ($object-set! 'unsigned-48 bv (constant bytevector-data-disp) val) - (foreign-set! 'unsigned-48 ($ftype-pointer-address fptr) offset - (bytevector-u48-ref bv 0 - (if (eq? (constant native-endianness) 'big) 'little 'big))))]))) - - (set! $fptr-set-integer-56! - (lambda (info fptr offset val) - (unless ($integer-56? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-integer-56! info fptr offset val)] - [(32) (foreign-set! 'integer-56 ($ftype-pointer-address fptr) offset val)]))) - (set! $fptr-set-unsigned-56! - (lambda (info fptr offset val) - (unless ($integer-56? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-unsigned-56! info fptr offset val)] - [(32) (foreign-set! 'unsigned-56 ($ftype-pointer-address fptr) offset val)]))) - (set! $fptr-set-swap-integer-56! - (lambda (info fptr offset val) - (unless ($integer-56? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-swap-integer-56! info fptr offset val)] - [(32) (let ([bv (make-bytevector 8)]) - ($object-set! 'integer-56 bv (constant bytevector-data-disp) val) - (foreign-set! 'unsigned-56 ($ftype-pointer-address fptr) offset - (bytevector-u56-ref bv 0 - (if (eq? (constant native-endianness) 'big) 'little 'big))))]))) - (set! $fptr-set-swap-unsigned-56! - (lambda (info fptr offset val) - (unless ($integer-56? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-swap-unsigned-56! info fptr offset val)] - [(32) (let ([bv (make-bytevector 8)]) - ($object-set! 'unsigned-56 bv (constant bytevector-data-disp) val) - (foreign-set! 'unsigned-56 ($ftype-pointer-address fptr) offset - (bytevector-u56-ref bv 0 - (if (eq? (constant native-endianness) 'big) 'little 'big))))]))) - - (set! $fptr-set-integer-64! - (lambda (info fptr offset val) - (unless ($integer-64? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-integer-64! info fptr offset val)] - [(32) (foreign-set! 'integer-64 ($ftype-pointer-address fptr) offset val)]))) - (set! $fptr-set-unsigned-64! - (lambda (info fptr offset val) - (unless ($integer-64? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-unsigned-64! info fptr offset val)] - [(32) (foreign-set! 'unsigned-64 ($ftype-pointer-address fptr) offset val)]))) - (set! $fptr-set-swap-integer-64! - (lambda (info fptr offset val) - (unless ($integer-64? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-swap-integer-64! info fptr offset val)] - [(32) (let ([bv (make-bytevector 8)]) - ($object-set! 'integer-64 bv (constant bytevector-data-disp) val) - (foreign-set! 'unsigned-64 ($ftype-pointer-address fptr) offset - (bytevector-u64-ref bv 0 - (if (eq? (constant native-endianness) 'big) 'little 'big))))]))) - (set! $fptr-set-swap-unsigned-64! - (lambda (info fptr offset val) - (unless ($integer-64? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-swap-unsigned-64! info fptr offset val)] - [(32) (let ([bv (make-bytevector 8)]) - ($object-set! 'unsigned-64 bv (constant bytevector-data-disp) val) - (foreign-set! 'unsigned-64 ($ftype-pointer-address fptr) offset - (bytevector-u64-ref bv 0 - (if (eq? (constant native-endianness) 'big) 'little 'big))))]))) - - (set! $fptr-set-double-float! - (lambda (info fptr offset val) - (unless (flonum? val) (invalid-value info val)) - (#3%$fptr-set-double-float! info fptr offset val))) - (set! $fptr-set-swap-double-float! - (lambda (info fptr offset val) - (unless (flonum? val) (invalid-value info val)) - (constant-case ptr-bits - [(64) (#3%$fptr-set-swap-double-float! info fptr offset val)] - [(32) (let ([bv (make-bytevector 8)]) - ($object-set! 'double-float bv (constant bytevector-data-disp) val) - (foreign-set! 'unsigned-64 ($ftype-pointer-address fptr) offset - (bytevector-u64-ref bv 0 - (if (eq? (constant native-endianness) 'big) 'little 'big))))]))) - - (set! $fptr-set-single-float! - (lambda (info fptr offset val) - (unless (flonum? val) (invalid-value info val)) - (#3%$fptr-set-single-float! info fptr offset val))) - (set! $fptr-set-swap-single-float! - (lambda (info fptr offset val) - (unless (flonum? val) (invalid-value info val)) - (let ([bv (make-bytevector 4)]) - ($object-set! 'single-float bv (constant bytevector-data-disp) val) - (foreign-set! 'unsigned-32 ($ftype-pointer-address fptr) offset - (bytevector-u32-ref bv 0 - (if (eq? (constant native-endianness) 'big) 'little 'big)))))) - - (set! $fptr-set-char! - (lambda (info fptr offset val) - (unless (char? val) (invalid-value info val)) - (#3%$fptr-set-char! info fptr offset val))) - - (set! $fptr-set-wchar! - (lambda (info fptr offset val) - (unless (char? val) (invalid-value info val)) - (#3%$fptr-set-wchar! info fptr offset val))) - (set! $fptr-set-swap-wchar! - (lambda (info fptr offset val) - (unless (char? val) (invalid-value info val)) - (#3%$fptr-set-swap-wchar! info fptr offset val))) - - (set! $fptr-set-boolean! - (lambda (info fptr offset val) - (#3%$fptr-set-boolean! info fptr offset val))) - (set! $fptr-set-swap-boolean! - (lambda (info fptr offset val) - (#3%$fptr-set-swap-boolean! info fptr offset val))) - - (set! $fptr-set-fixnum! - (lambda (info fptr offset val) - (unless (fixnum? val) (invalid-value info val)) - (#3%$fptr-set-fixnum! info fptr offset val))) - (set! $fptr-set-swap-fixnum! - (lambda (info fptr offset val) - (unless (fixnum? val) (invalid-value info val)) - (#3%$fptr-set-swap-fixnum! info fptr offset val))) - ) - - (set-who! $fptr-set! - (lambda (orig-type ty swap? fptr offset val) - (define-syntax proc - (lambda (x) - (syntax-case x (scheme-object) - [(_ scheme-object bytes pred) #'($oops who "unexpected type ~s" ty)] - [(_ type bytes pred) - (if (memq (datum type) '(char integer-8 unsigned-8)) - #`($primitive 2 - #,(datum->syntax #'* - (string->symbol - (format "$fptr-set-~a!" (datum type))))) - #`(if swap? - ($primitive 2 - #,(datum->syntax #'* - (string->symbol - (format "$fptr-set-swap-~a!" (datum type))))) - ($primitive 2 - #,(datum->syntax #'* - (string->symbol - (format "$fptr-set-~a!" (datum type)))))))]))) - ((record-datatype cases ty proc - ($oops who "unrecognized type ~s" ty)) - orig-type fptr offset val))) - - (let () - (define-syntax $fptr-ref-ibits - (lambda (x) - (syntax-case x () - [(kwd k swap?) - (with-syntax ([$fptr-ref-x (datum->syntax #'kwd - (string->symbol - (format "$fptr-ref-~:[~;swap-~]unsigned-~a" - (datum swap?) - (datum k))))]) - (if (<= (expt 2 (datum k)) (constant most-positive-fixnum)) - #'(lambda (fptr offset start end) - (let ([radix (fxsll 1 (fx- end start))]) - (let ([n (fxlogand - (fxsra ($fptr-ref-x fptr offset) start) - (fx- radix 1))]) - (if (fx>= n (fxsra radix 1)) (fx- n radix) n)))) - #'(lambda (fptr offset start end) - (let ([radix (bitwise-arithmetic-shift-left 1 (fx- end start))]) - (let ([n (logand - (bitwise-arithmetic-shift-right - ($fptr-ref-x fptr offset) - start) - (- radix 1))]) - (if (>= n (bitwise-arithmetic-shift-right radix 1)) - (- n radix) - n))))))]))) - (set! $fptr-ref-ibits-unsigned-8 ($fptr-ref-ibits 8 #f)) - (set! $fptr-ref-ibits-swap-unsigned-16 ($fptr-ref-ibits 16 #t)) - (set! $fptr-ref-ibits-unsigned-16 ($fptr-ref-ibits 16 #f)) - (set! $fptr-ref-ibits-swap-unsigned-24 ($fptr-ref-ibits 24 #t)) - (set! $fptr-ref-ibits-unsigned-24 ($fptr-ref-ibits 24 #f)) - (set! $fptr-ref-ibits-swap-unsigned-32 ($fptr-ref-ibits 32 #t)) - (set! $fptr-ref-ibits-unsigned-32 ($fptr-ref-ibits 32 #f)) - (set! $fptr-ref-ibits-swap-unsigned-40 ($fptr-ref-ibits 40 #t)) - (set! $fptr-ref-ibits-unsigned-40 ($fptr-ref-ibits 40 #f)) - (set! $fptr-ref-ibits-swap-unsigned-48 ($fptr-ref-ibits 48 #t)) - (set! $fptr-ref-ibits-unsigned-48 ($fptr-ref-ibits 48 #f)) - (set! $fptr-ref-ibits-swap-unsigned-56 ($fptr-ref-ibits 56 #t)) - (set! $fptr-ref-ibits-unsigned-56 ($fptr-ref-ibits 56 #f)) - (set! $fptr-ref-ibits-swap-unsigned-64 ($fptr-ref-ibits 64 #t)) - (set! $fptr-ref-ibits-unsigned-64 ($fptr-ref-ibits 64 #f))) - - (let () - (define-syntax $fptr-ref-ubits - (lambda (x) - (syntax-case x () - [(kwd k swap?) - (with-syntax ([$fptr-ref-x (datum->syntax #'kwd - (string->symbol - (format "$fptr-ref-~:[~;swap-~]unsigned-~a" - (datum swap?) - (datum k))))]) - (if (<= (expt 2 (datum k)) (constant most-positive-fixnum)) - #'(lambda (fptr offset start end) - (let ([radix (fxsll 1 (fx- end start))]) - (fxlogand - (fxsrl ($fptr-ref-x fptr offset) start) - (fx- radix 1)))) - #'(lambda (fptr offset start end) - (let ([radix (bitwise-arithmetic-shift-left 1 (fx- end start))]) - (logand - (bitwise-arithmetic-shift-right ($fptr-ref-x fptr offset) start) - (- radix 1))))))]))) - (set! $fptr-ref-ubits-unsigned-8 ($fptr-ref-ubits 8 #f)) - (set! $fptr-ref-ubits-swap-unsigned-16 ($fptr-ref-ubits 16 #t)) - (set! $fptr-ref-ubits-unsigned-16 ($fptr-ref-ubits 16 #f)) - (set! $fptr-ref-ubits-swap-unsigned-24 ($fptr-ref-ubits 24 #t)) - (set! $fptr-ref-ubits-unsigned-24 ($fptr-ref-ubits 24 #f)) - (set! $fptr-ref-ubits-swap-unsigned-32 ($fptr-ref-ubits 32 #t)) - (set! $fptr-ref-ubits-unsigned-32 ($fptr-ref-ubits 32 #f)) - (set! $fptr-ref-ubits-swap-unsigned-40 ($fptr-ref-ubits 40 #t)) - (set! $fptr-ref-ubits-unsigned-40 ($fptr-ref-ubits 40 #f)) - (set! $fptr-ref-ubits-swap-unsigned-48 ($fptr-ref-ubits 48 #t)) - (set! $fptr-ref-ubits-unsigned-48 ($fptr-ref-ubits 48 #f)) - (set! $fptr-ref-ubits-swap-unsigned-56 ($fptr-ref-ubits 56 #t)) - (set! $fptr-ref-ubits-unsigned-56 ($fptr-ref-ubits 56 #f)) - (set! $fptr-ref-ubits-swap-unsigned-64 ($fptr-ref-ubits 64 #t)) - (set! $fptr-ref-ubits-unsigned-64 ($fptr-ref-ubits 64 #f))) - - (set-who! $fptr-ref-bits - (lambda (ty swap? signed? fptr offset start end) - (define-syntax proc - (lambda (x) - (syntax-case x () - [(_ type) - (if (memq (datum type) '(char integer-8 unsigned-8)) - #`(if signed? - #,(datum->syntax #'* - (string->symbol - (format "$fptr-ref-ibits-~a" (datum type)))) - #,(datum->syntax #'* - (string->symbol - (format "$fptr-ref-ubits-~a" (datum type))))) - #`(if swap? - (if signed? - #,(datum->syntax #'* - (string->symbol - (format "$fptr-ref-ibits-swap-~a" (datum type)))) - #,(datum->syntax #'* - (string->symbol - (format "$fptr-ref-ubits-swap-~a" (datum type))))) - (if signed? - #,(datum->syntax #'* - (string->symbol - (format "$fptr-ref-ibits-~a" (datum type)))) - #,(datum->syntax #'* - (string->symbol - (format "$fptr-ref-ubits-~a" (datum type)))))))]))) - ((case ty - [(unsigned-8) (proc unsigned-8)] - [(unsigned-16) (proc unsigned-16)] - [(unsigned-32) (proc unsigned-32)] - [(unsigned-64) (proc unsigned-64)] - [else ($oops who "unexpected type ~s" ty)]) - fptr offset start end))) - - (let () - (define-syntax $fptr-set-bits! - (lambda (x) - (syntax-case x () - [(kwd k swap?) - (with-syntax ([orig-type (datum->syntax #'kwd - (string->symbol - (format "unsigned-~a" (datum k))))] - [$fptr-ref-x (datum->syntax #'kwd - (string->symbol - (format "$fptr-ref-~:[~;swap-~]unsigned-~a" - (datum swap?) - (datum k))))] - [$fptr-set-x! (datum->syntax #'kwd - (string->symbol - (format "$fptr-set-~:[~;swap-~]unsigned-~a!" - (datum swap?) - (datum k))))]) - (if (<= (expt 2 (datum k)) (constant most-positive-fixnum)) - #'(lambda (fptr offset start end val) - (let* ([size (fx- end start)] - [radix (fxsll 1 size)] - [radix/2 (fxsrl radix 1)]) - (unless (and (integer? val) (exact? val) (>= val (- radix/2)) (< val radix)) - ($oops 'ftype-set! "invalid value ~s for bit field of size ~s" val size)) - ($fptr-set-x! 'orig-type fptr offset - (fxlogor - (fxlogand - ($fptr-ref-x fptr offset) - (fxlognot (fxsll (- radix 1) start))) - (fxsll - (if (fx< val 0) (fx+ val radix) val) - start))))) - #'(lambda (fptr offset start end val) - (let* ([size (fx- end start)] - [radix (bitwise-arithmetic-shift-left 1 size)] - [radix/2 (bitwise-arithmetic-shift-right radix 1)]) - (unless (and (integer? val) (exact? val) (>= val (- radix/2)) (< val radix)) - ($oops 'ftype-set! "invalid value ~s for bit field of size ~s" val size)) - ($fptr-set-x! 'orig-type fptr offset - (logor - (logand - ($fptr-ref-x fptr offset) - (lognot (bitwise-arithmetic-shift-left (- radix 1) start))) - (bitwise-arithmetic-shift-left - (if (< val 0) (+ val radix) val) - start)))))))]))) - (set! $fptr-set-bits-unsigned-8! ($fptr-set-bits! 8 #f)) - (set! $fptr-set-bits-swap-unsigned-16! ($fptr-set-bits! 16 #t)) - (set! $fptr-set-bits-unsigned-16! ($fptr-set-bits! 16 #f)) - (set! $fptr-set-bits-swap-unsigned-24! ($fptr-set-bits! 24 #t)) - (set! $fptr-set-bits-unsigned-24! ($fptr-set-bits! 24 #f)) - (set! $fptr-set-bits-swap-unsigned-32! ($fptr-set-bits! 32 #t)) - (set! $fptr-set-bits-unsigned-32! ($fptr-set-bits! 32 #f)) - (set! $fptr-set-bits-swap-unsigned-40! ($fptr-set-bits! 40 #t)) - (set! $fptr-set-bits-unsigned-40! ($fptr-set-bits! 40 #f)) - (set! $fptr-set-bits-swap-unsigned-48! ($fptr-set-bits! 48 #t)) - (set! $fptr-set-bits-unsigned-48! ($fptr-set-bits! 48 #f)) - (set! $fptr-set-bits-swap-unsigned-56! ($fptr-set-bits! 56 #t)) - (set! $fptr-set-bits-unsigned-56! ($fptr-set-bits! 56 #f)) - (set! $fptr-set-bits-swap-unsigned-64! ($fptr-set-bits! 64 #t)) - (set! $fptr-set-bits-unsigned-64! ($fptr-set-bits! 64 #f))) - - (set-who! $fptr-set-bits! - (lambda (ty swap? fptr offset start end val) - (define-syntax proc - (lambda (x) - (syntax-case x () - [(_ type) - (if (memq (datum type) '(char integer-8 unsigned-8)) - (datum->syntax #'* - (string->symbol - (format "$fptr-set-bits-~a!" (datum type)))) - #`(if swap? - ($primitive 2 - #,(datum->syntax #'* - (string->symbol - (format "$fptr-set-bits-swap-~a!" (datum type))))) - ($primitive 2 - #,(datum->syntax #'* - (string->symbol - (format "$fptr-set-bits-~a!" (datum type)))))))]))) - ((case ty - [(unsigned-8) (proc unsigned-8)] - [(unsigned-16) (proc unsigned-16)] - [(unsigned-32) (proc unsigned-32)] - [(unsigned-64) (proc unsigned-64)] - [else ($oops who "unexpected type ~s" ty)]) - fptr offset start end val))) - - (set! $fptr-locked-incr! - (lambda (fptr offset) - (#3%$fptr-locked-incr! fptr offset))) - - (set! $fptr-locked-decr! - (lambda (fptr offset) - (#3%$fptr-locked-decr! fptr offset))) - - (set! $fptr-init-lock! - (lambda (fptr offset) - (#3%$fptr-init-lock! fptr offset))) - - (set! $fptr-lock! - (lambda (fptr offset) - (#3%$fptr-lock! fptr offset))) - - (set! $fptr-spin-lock! - (lambda (fptr offset) - (#3%$fptr-spin-lock! fptr offset))) - - (set! $fptr-unlock! - (lambda (fptr offset) - (#3%$fptr-unlock! fptr offset))) -) - -(define-syntax define-ftype (lambda (x) ($trans-define-ftype x))) -(define-syntax make-ftype-pointer (lambda (x) ($trans-make-ftype-pointer x))) -(define-syntax ftype-pointer? (lambda (x) ($trans-ftype-pointer? x))) -(define-syntax ftype-sizeof (lambda (x) ($trans-ftype-sizeof x))) -(define-syntax ftype-guardian (lambda (x) ($trans-ftype-guardian x))) -(define-syntax ftype-&ref (lambda (x) ($trans-ftype-&ref x))) -(define-syntax ftype-ref (lambda (x) ($trans-ftype-ref x))) -(define-syntax ftype-locked-incr! (lambda (x) ($trans-ftype-locked-op! #'ftype-locked-incr! x #'$fptr-locked-incr!))) -(define-syntax ftype-locked-decr! (lambda (x) ($trans-ftype-locked-op! #'ftype-locked-decr! x #'$fptr-locked-decr!))) -(define-syntax ftype-init-lock! (lambda (x) ($trans-ftype-locked-op! #'ftype-init-lock! x #'$fptr-init-lock!))) -(define-syntax ftype-lock! (lambda (x) ($trans-ftype-locked-op! #'ftype-lock! x #'$fptr-lock!))) -(define-syntax ftype-spin-lock! (lambda (x) ($trans-ftype-locked-op! #'ftype-spin-lock! x #'$fptr-spin-lock!))) -(define-syntax ftype-unlock! (lambda (x) ($trans-ftype-locked-op! #'ftype-unlock! x #'$fptr-unlock!))) -(define-syntax ftype-set! (lambda (x) ($trans-ftype-set! x))) -) diff --git a/ta6ob/s/ftype.ta6ob b/ta6ob/s/ftype.ta6ob deleted file mode 100644 index c48f812..0000000 Binary files a/ta6ob/s/ftype.ta6ob and /dev/null differ diff --git a/ta6ob/s/hashtable-types.ss b/ta6ob/s/hashtable-types.ss deleted file mode 100644 index e805f54..0000000 --- a/ta6ob/s/hashtable-types.ss +++ /dev/null @@ -1,47 +0,0 @@ -;;; hashtable-types.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(define-record-type (hashtable make-xht xht?) - (fields (immutable type xht-type) (immutable mutable? xht-mutable?)) - (nongenerative #{hashtable bu811z2onf9o6tfc-0})) - -(define-record-type ht - (parent hashtable) - (fields (mutable vec) (mutable minlen) (mutable size)) - (nongenerative #{ht bu811z2onf9o6tfc-6})) - -(define-record-type eq-ht - (parent ht) - (fields (immutable subtype)) ; eq-hashtable-subtype-{normal,weak,ephemeron} - (nongenerative #{eq-ht icguu8mlhm1y7ywsairxck-0}) - (sealed #t)) - -(define-record-type symbol-ht - (parent ht) - (fields (immutable equiv?)) - (nongenerative #{symbol-ht bu811z2onf9o6tfc-8}) - (sealed #t)) - -(define-record-type gen-ht - (parent ht) - (fields (immutable hash) (immutable equiv?)) - (nongenerative #{gen-ht bu811z2onf9o6tfc-7}) - (sealed #t)) - -(define-record-type eqv-ht - (parent hashtable) - (fields (immutable eqht) (immutable genht)) - (nongenerative #{eqv-ht bu811z2onf9o6tfc-4}) - (sealed #t)) diff --git a/ta6ob/s/inspect.ss b/ta6ob/s/inspect.ss deleted file mode 100644 index 67940aa..0000000 --- a/ta6ob/s/inspect.ss +++ /dev/null @@ -1,2881 +0,0 @@ -;;; inspect.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; todo - -; ---be sensitive to system mode -; ---argument names for code objects -; ---nesting level numbers for all variables -; (sort variable displays by nesting and position) -; ---add "loop" variable type -; ---keep track of loop names? -; ---information about foreign procedures -; ---distinguish between user and compiler gensym variables? -; (right now both are stripped) -; ---disassembler -; ---port info should include file descriptor, perhaps provide access -; location in file - -(begin -(let () - -(define-syntax make-dispatch-table - (lambda (x) - (syntax-case x () - [(_ [key message (ids e1 e2 ...) ...] ...) - (and (andmap (lambda (x) - (or (string? x) - (and (pair? x) (string? (car x)) (string? (cdr x))))) - (datum (key ...))) - (andmap string? (datum (message ...)))) - #'`([key message - ,(case-lambda - (ids e1 e2 ...) - ... - (l (invalid-command)))] - ...)]))) - -(define-record-type sfile - (fields (immutable path) (immutable port) (mutable line) (mutable line-valid?)) - (nongenerative) - (sealed #t)) - -(define-threaded source-files '()) - -(define find-source-file - (lambda (path line) - (define path=? - ; trivial definition for now - (lambda (p1 p2) - (string=? p1 p2))) - (let f ((ls source-files)) - (if (null? ls) - (guard (c [#t #f]) - (let ((line (or line 1))) - (set! source-files - (cons (make-sfile path (open-input-file path) - line - (= line 1)) - source-files))) - #t) - (if (path=? path (sfile-path (car ls))) - (let ((sf (car ls))) - (when line - (unless (= line (sfile-line sf)) - (sfile-line-valid?-set! sf #f) - (sfile-line-set! sf line))) - (set! source-files - (cons sf (remq sf source-files))) - #t) - (f (cdr ls))))))) - -(define open-source-file - (case-lambda - [(path) (open-source-file path #f)] - [(path line) - (or (if ($fixed-path? path) - (find-source-file path line) - (let ([dir* (append (source-directories) (map car (library-directories)))]) - (let pathloop ([path path]) - (let dirloop ([dir* dir*]) - (if (null? dir*) - (let ([rest (path-rest path)]) - (and (not (string=? rest path)) - (pathloop rest))) - (or (find-source-file - (let* ((dir (car dir*)) (n (string-length dir))) - (format (if (and (fx> n 0) - (directory-separator? - (string-ref dir (fx- n 1)))) - "~a~a" - "~a/~a") - dir path)) - line) - (dirloop (cdr dir*)))))))) - (inspect-error "Cannot open ~a" path))])) - -(define open-recorded-source-file - (lambda (object) - (call-with-values - (lambda () (object 'source-path)) - (case-lambda - [() (inspect-error "Source file unknown.")] - [(path pos) - (inspect-error - "Cannot locate (unmodified) source file ~a.~%Try changing source-directories parameter.~%Source is at character ~s." - path pos)] - [(path line char) - (if (find-source-file path - (max (- line (quotient lines-to-list 2)) 1)) - (show "line ~d, character ~d of ~a" line char path) - (inspect-error "Cannot open ~a" path))])))) - -(define close-source-file - (lambda (sf) - (close-input-port (sfile-port sf)))) - -(define lines-to-list 10) - -(module (list-source-file) -(define base10-length - (lambda (n) - (cond - [(fx< n 10) 1] - [(fx< n 100) 2] - [(fx< n 1000) 3] - [(fx< n 10000) 4] - [else (+ 4 (base10-length (quotient n 10000)))]))) - -(define list-source-file - (case-lambda - [() (list-source-file #f #f)] - [(line) (list-source-file line #f)] - [(line count) - (when (null? source-files) - (inspect-error "No source file open.")) - (let* ((sf (car source-files)) - (ip (sfile-port sf))) - (when line (require (fixnum? line))) - (when count (require (and (fixnum? count) (fx> count 0)))) - (let* ((line (cond [(not line) (sfile-line sf)] - [(fx> line 0) line] - [else (max (+ (sfile-line sf) line (- lines-to-list)) - 1)])) - (count (if count - (begin (set! lines-to-list count) count) - lines-to-list))) - (let f ((new-line - (if (and (sfile-line-valid? sf) (fx>= line (sfile-line sf))) - (begin - (sfile-line-valid?-set! sf #f) - (sfile-line sf)) - (begin - (sfile-line-valid?-set! sf #f) - (file-position ip 0) - 1)))) - (unless (fx= new-line line) - (let ((c (read-char ip))) - (cond - [(eof-object? c) - (inspect-error "Not that many lines in ~a." (sfile-path sf))] - [(char=? c #\newline) (f (fx+ new-line 1))] - [else (f new-line)])))) - (let ((line-chars (base10-length (+ line count -1)))) - (let f ((line line) (count count)) - (if (fx= count 0) - (begin - (sfile-line-set! sf line) - (sfile-line-valid?-set! sf #t)) - (let ((c (read-char ip))) - (if (eof-object? c) - (fprintf (console-output-port) "*** end of file ***~%") - (begin - (do ((n (base10-length line) (fx+ n 1))) - ((fx= n line-chars)) - (write-char #\space (console-output-port))) - (fprintf (console-output-port) "~d: " line) - (do ((c c (read-char ip))) - ((or (eof-object? c) (char=? c #\newline)) - (newline (console-output-port))) - (write-char c (console-output-port))) - (f (fx+ line 1) (fx- count 1))))))))))])) -) - -(define (waiter-read) - (parameterize ([waiter-prompt-string ""]) - ((waiter-prompt-and-read) 1))) - -(define show - (lambda (s . args) - (apply fprintf (console-output-port) s args) - (newline (console-output-port)))) - -(define inspect-error - (lambda (s . args) - (apply show s args) - (reset))) - -(define invalid-command - (lambda () - (inspect-error "Invalid command or argument. Type ? for options."))) - -(define invalid-movement - (lambda () - (inspect-error "Invalid movement."))) - -(define line-indent " ") - -(define prompt-line-limit 65) - -(define display-line-limit 80) - -(define descrip-limit 25) - -(define-threaded marks) - -(define-threaded current-state) - -(define-record-type state - (fields (immutable object) (immutable level) (immutable position) (immutable link) (mutable find-next)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (case-lambda - [(object) (new object 0 #f #f #f)] - [(object level position link) (new object level position link #f)])))) - -(define object (lambda () (state-object current-state))) - -(define level (lambda () (state-level current-state))) - -(define position (lambda () (state-position current-state))) - -(define type? - (lambda (flag x) - (eq? (x 'type) flag))) - -(define default-mark (void)) - -(define make-mark - (lambda (m) - (if (string? m) - (string->symbol m) - m))) - -(define put-mark - (lambda (m) - (let ([a (eq-hashtable-cell marks m #f)]) - (set-cdr! a current-state)))) - -(define get-mark - (lambda (m) - (eq-hashtable-ref marks m #f))) - -(define to-mark - (lambda (m) - (let ([s (get-mark m)]) - (unless s (invalid-movement)) - (put-mark default-mark) - (set! current-state s)))) - -(define down - (lambda (x pos) - (set! current-state - (make-state (if (eq? (x 'type) 'variable) (x 'ref) x) - (+ (level) 1) - pos - current-state)))) - -(define up - (lambda () - (set! current-state (state-link current-state)) - (unless current-state (invalid-movement)))) - -(define display-links - (lambda (n) - (let loop ([i 0] [x (object)]) - (unless (= i n) - (when (type? 'continuation x) - (label-line-display x i) - (loop (+ i 1) (x 'link))))))) - -(define display-refs - (lambda (n) - (let ([x (object)]) - (let loop ([i 0]) - (unless (= i n) - (label-line-display (x 'ref i) i) - (loop (+ i 1))))))) - -(define display-variable-refs - (lambda (n) - (let ([x (object)]) - (if ((x 'code) 'info) - (let loop ([i 0]) - (unless (= i n) - (variable-line-display (x 'ref i) i) - (loop (+ i 1)))) - (display-refs n))))) - -(define display-list - (lambda (n) - (let ((x (object))) - (if (or (type? 'pair (x 'cdr)) - (and (type? 'simple (x 'cdr)) (null? ((x 'cdr) 'value)))) - (let loop ([i 0] [x x]) - (if (and (< i n) (type? 'pair x)) - (begin - (label-line-display (x 'car) i) - (loop (+ i 1) (x 'cdr))) - (unless (and (type? 'simple x) (null? (x 'value))) - (name-line-display x "tail")))) - (begin - (name-line-display (x 'car) "car") - (name-line-display (x 'cdr) "cdr")))))) - -(define charschemecode - (lambda (x) - (let ([x (format "~s" x)]) - (format "~a~a" x (spaces (- 11 (string-length x))))))) - -(define unicodehexcode - (lambda (x) - (format "~6,'0x " (char->integer x)))) - -(define asciihexcode - (lambda (x) - (let ([n (char->integer x)]) - (if (>= n 256) - "-- " - (format "~2,'0x " n))))) - -(define display-chars - (lambda (n former no/line) - (let ([x (object)]) - (let loop1 ([i 0]) - (unless (= i n) - (let ([label (format "~a~d: " line-indent i)]) - (let loop2 ([j 0] [i i] [strings '()]) - (if (or (= j no/line) (= i n)) - (begin - (show "~a~a~a" - label - (spaces (- 6 (string-length label))) - (apply string-append (reverse strings))) - (loop1 i)) - (loop2 (+ j 1) - (+ i 1) - (cons (former ((x 'ref i) 'value)) - strings)))))))))) - -(define label-line-display - (lambda (x n) - (let ([label (format "~a~d: " line-indent n)]) - (show "~a~a" - label - (form x (string-length label) display-line-limit))))) - -(define name-label-line-display - (lambda (x name n) - (let ([label (format "~a~d. ~a:" line-indent n name)]) - (let ([label (format "~a~a" - label - (spaces (- descrip-limit (string-length label))))]) - (show "~a~a" - label - (form x (string-length label) display-line-limit)))))) - -(define name-line-display - (lambda (x name) - (let ([label (format "~a~a:" line-indent name)]) - (let ([label (format "~a~a" - label - (spaces (- descrip-limit (string-length label))))]) - (show "~a~a" - label - (form x (string-length label) display-line-limit)))))) - -(define variable-line-display - (lambda (x n) - (if (x 'name) - (name-label-line-display (x 'ref) (x 'name) n) - (label-line-display (x 'ref) n)))) - -(define ref-list - (lambda (n) - (unless (and (fixnum? n) (>= n 0)) (invalid-movement)) - (let ref ([i n] [x (object)]) - (cond - [(not (type? 'pair x)) (invalid-movement)] - [(= i 0) (down (x 'car) n)] - [else (ref (- i 1) (x 'cdr))])))) - -(define ref - (lambda (n) - (unless (and (fixnum? n) (< -1 n ((object) 'length))) - (invalid-movement)) - (down ((object) 'ref n) n))) - -(define set - (lambda (n v) - (unless (and (fixnum? n) (< -1 n ((object) 'length))) - (invalid-movement)) - (let ([x ((object) 'ref n)]) - (unless (x 'assignable?) - (inspect-error "~s is not assignable" (or (x 'name) 'unnamed))) - (x 'set! v)))) - -(module (variable-ref variable-set) - (define get-var-obj - (lambda (sym) - (let ([n ((object) 'length)]) - (let loop ([i 0]) - (if (fx= i n) - (invalid-movement) - (let ([x ((object) 'ref i)]) - (if (let ([name (x 'name)]) - (and (symbol? name) - (string=? - (symbol->string name) - (symbol->string sym)))) - (values x i) - (loop (fx+ i 1))))))))) - (define variable-ref - (lambda (x) - (if (symbol? x) - (with-values (get-var-obj x) down) - (ref x)))) - (define variable-set - (lambda (x val) - (if (symbol? x) - (with-values (get-var-obj x) - (lambda (var-obj i) - (unless (var-obj 'assignable?) (inspect-error "~s is not assignable" x)) - (var-obj 'set! val))) - (set x val))))) - -(define move - (lambda (n) - (require (position)) - (let ([n (+ n (position))]) - (up) - (case ((object) 'type) - [(pair) (ref-list n)] - [(continuation procedure vector fxvector bytevector string record - ftype-struct ftype-union ftype-array ftype-bits) - (ref n)] - [else (invalid-movement)])))) - -(define require - (lambda (x) - (unless x (invalid-command)))) - -(define range-check - (case-lambda - [(n) (require (and (fixnum? n) (fx<= 0 n)))] - [(n max) (require (and (fixnum? n) (fx<= 0 n max)))] - [(min n max) (require (and (fixnum? n) (fx<= min n max)))])) - -(define display-one-option - (lambda (key message) - (let ([s (if (pair? key) (format "~a(~a)" (car key) (cdr key)) key)]) - (show " ~a ~a ~a" - s - (make-string (max (- 20 (string-length s)) 0) #\.) - message)))) - -(define display-options - (lambda (table generic?) - (show "") - (for-each display-one-option (map car table) (map cadr table)) - (unless generic? (display-one-option "??" "display more options")) - (show ""))) - -(define select-dispatch-table - (lambda () - (case ((object) 'type) - [(pair) pair-dispatch-table] - [(symbol) (if (eq? (subset-mode) 'system) - system-symbol-dispatch-table - symbol-dispatch-table)] - [(vector) vector-dispatch-table] - [(fxvector) fxvector-dispatch-table] - [(bytevector) bytevector-dispatch-table] - [(record) record-dispatch-table] - [(string) string-dispatch-table] - [(box) box-dispatch-table] - [(continuation) continuation-dispatch-table] - [(procedure) procedure-dispatch-table] - [(code) code-dispatch-table] - [(port) port-dispatch-table] - [(simple) - (let ([x ((object) 'value)]) - (cond - [(char? x) char-dispatch-table] - [else empty-dispatch-table]))] - [(tlc) tlc-dispatch-table] - [(ftype-struct) ftype-struct-dispatch-table] - [(ftype-union) ftype-union-dispatch-table] - [(ftype-array) ftype-array-dispatch-table] - [(ftype-*) ftype-pointer-dispatch-table] - [(ftype-bits) ftype-bits-dispatch-table] - [(ftype-base) ftype-pointer-dispatch-table] - [(ftype-function) ftype-function-dispatch-table] - [else empty-dispatch-table]))) - -(define inspector-read - (lambda (ip) - (let* ([ip (console-input-port)] [c (read-char ip)]) - (cond - [(eof-object? c) - (newline (console-output-port)) - '("quit")] - [(char=? c #\newline) - (set-port-bol! (console-output-port) #t) - '()] - [(char-whitespace? c) - (inspector-read ip)] - [else - (unread-char c ip) - (let ([first (inspector-read-command ip)]) - (cons first (inspector-read-tail ip)))])))) - -(define inspector-read-command - (lambda (ip) - (let ([p (open-output-string)]) - (let read-letters () - (let ([c (peek-char ip)]) - (if (and (char? c) - (not (char-numeric? c)) - (not (char-whitespace? c))) - (begin (read-char ip) - (write-char c p) - (read-letters)) - (get-output-string p))))))) - -(define inspector-read-tail - (lambda (ip) - (let ([c (peek-char ip)]) - (cond - [(char=? c #\newline) - (read-char ip) - (set-port-bol! (console-output-port) #t) - '()] - [(or (char-whitespace? c) ; [( - (memv c '(#\) #\]))) - (read-char ip) - (inspector-read-tail ip)] - [else - (let ([x (read ip)]) - (cons x (inspector-read-tail ip)))])))) - -(define dispatch - (lambda (c t) - (let ([handler (or (search-dispatch-table (car c) t) - (search-dispatch-table (car c) - generic-dispatch-table))]) - (if handler - (apply handler (cdr c)) - (invalid-command))))) - -(define search-dispatch-table - (lambda (s t) - (and (not (null? t)) - (let ([first (car t)]) - (let ([key (car first)]) - (if (if (string? key) - (string=? key s) - (or (string=? (car key) s) - (string=? (cdr key) s))) - (caddr first) - (search-dispatch-table s (cdr t)))))))) - -(define spaces - (lambda (n) - (if (> n 0) - (make-string n #\space) - ""))) - -(define write-to-string - (lambda (x) - (let ([p (open-output-string)]) - (x 'write p) - (get-output-string p)))) - -(define short-form-rec - (lambda (x limit) - (let try ([low 1] - [high #f] - [r (parameterize ([print-level 0] [print-length 0]) - (write-to-string x))]) - (let ([mid (+ low (if high (quotient (- high low) 2) low))]) - (if (= mid low) - r - (let ([s (parameterize ([print-level mid] [print-length mid]) - (write-to-string x))]) - (cond - [(string=? s r) s] - [(> (string-length s) limit) (try low mid r)] - [else (try mid high s)]))))))) - -(define short-form-lambda - ; x looks like "(lambda vars body)" - ; print the "lambda" and all of the vars that fit - (lambda (x limit) - (let ([first (format "(lambda ~a " ;) - (short-form-rec ((x 'cdr) 'car) (- limit 14)))]) - (let ([rest (short-form-rec ((x 'cdr) 'cdr) - (- limit (string-length first)))]) - (if (and (> (string-length rest) 0) - (char=? (string-ref rest 0) #\()) ;) - (string-append first (substring rest 1 (string-length rest))) - (short-form-rec x limit)))))) - -(define short-form - (lambda (x limit) - (case (x 'type) - [(pair) - (if (and (eq? ((x 'car) 'type) 'symbol) - (eq? ((x 'car) 'value) 'lambda) - (eq? ((x 'cdr) 'type) 'pair) - (eq? (((x 'cdr) 'cdr) 'type) 'pair)) - (short-form-lambda x limit) - (short-form-rec x limit))] - [(string) - (let ([s (format "~s" - ; avoid passing format the whole of a large string - (let ([s (x 'value)]) - (if (<= (string-length s) limit) - s - (substring s 0 limit))))]) - (if (<= (string-length s) limit) - s - (string-append - (substring s 0 (max (- limit 4) 1)) - "...\"")))] - [else (short-form-rec x limit)]))) - -(define form - (lambda (x used limit) - (short-form x (- limit used)))) - -(define inspector-prompt - (lambda () - (let ([obj (form (object) 0 prompt-line-limit)]) - (fprintf (console-output-port) - "~a~a : " - obj - (spaces (- prompt-line-limit (string-length obj))))))) - -(define outer-reset-handler ($make-thread-parameter values)) - -(define inspector - (lambda (last-command) - (inspector - (let ([saved-state current-state]) - (parameterize ([reset-handler (call/cc - (lambda (k) - (rec f - (lambda () - (clear-output-port (console-output-port)) - (set! current-state saved-state) - (k f)))))]) - (let ([ip (console-input-port)]) - (clear-input-port ip) - (inspector-prompt) - (let ([cmd (let ([cmd (inspector-read ip)]) - (cond - [(null? cmd) - (if (equal? (car last-command) "list") - '("list") - last-command)] - [(number? (car cmd)) (cons "ref" cmd)] - [else cmd]))]) - (cond - [(equal? cmd '("?")) - (let ([t (select-dispatch-table)]) - (if (null? t) - (display-options generic-dispatch-table #t) - (display-options t #f)))] - [(equal? cmd '("??")) - (display-options generic-dispatch-table #t)] - [else - (guard (c [#t (let ([op (console-output-port)]) - (fresh-line op) - (display-condition c op) - (newline op) - (set! current-state saved-state))]) - (dispatch cmd (select-dispatch-table)))]) - cmd))))))) - -(define-syntax inspector-print - (syntax-rules () - [(_ e) - (call-with-values (lambda () e) - (case-lambda - [(x) (unless (eq? x (void)) (pretty-print x (console-output-port)))] - [args (for-each (lambda (x) (pretty-print x (console-output-port))) args)]))])) - -(module (inspector-find inspector-find-next) - (define down-path - (lambda (path) - (assert (and (list? path) (>= (length path) 1))) - (let f ([path path]) - (let ([x (car path)] [path (cdr path)]) - (if (null? path) - (assert (eq? x ((object) 'value))) - (begin - (f path) - (down ((object) 'make-me-a-child x) #f))))))) - (define inspector-find - (lambda (pred gen) - (state-find-next-set! current-state (make-object-finder pred ((object) 'value) gen)) - (let ([path ((state-find-next current-state))]) - (unless path (inspect-error "Not found")) - (down-path path)))) - (define inspector-find-next - (lambda () - (let loop ([state current-state]) - (cond - [(not state) (inspect-error "No current find.")] - [(state-find-next state) => - (lambda (find-next) - (let ([path (find-next)]) - (unless path (inspect-error "Not found")) - (set! current-state state) - (down-path path)))] - [else (loop (state-link state))]))))) - -(define generic-dispatch-table - (make-dispatch-table - - [("print" . "p") - "pretty-print object" - (() - (newline (console-output-port)) - ((object) 'print (console-output-port)) - (newline (console-output-port)))] - - [("write" . "w") - "write object" - (() - (newline (console-output-port)) - ((object) 'write (console-output-port)) - (newline (console-output-port)) - (newline (console-output-port)))] - - ["size" - "recursively compute storage occupied by object" - (() (fprintf (console-output-port) "~s\n" ((object) 'size (collect-maximum-generation)))) - ((g) - (require (or (and (fixnum? g) (fx<= 0 g (collect-maximum-generation))) (eq? g 'static))) - (fprintf (console-output-port) "~s\n" ((object) 'size g)))] - - ["find" - "find within object, given a predicate" - (() - (let ([x (waiter-read)]) - (unless (eof-object? x) - (let ([x (eval x)]) - (unless (procedure? x) (inspect-error "~s is not a procedure" x)) - (inspector-find x (collect-maximum-generation)))))) - ((x) - (let ([x (eval x)]) - (unless (procedure? x) (inspect-error "~s is not a procedure" x)) - (inspector-find x (collect-maximum-generation)))) - ((x g) - (require (or (and (fixnum? g) (fx<= 0 g (collect-maximum-generation))) (eq? g 'static))) - (let ([x (eval x)]) - (unless (procedure? x) (inspect-error "~s is not a procedure" x)) - (inspector-find x g)))] - - ["find-next" - "repeat find" - (() - (inspector-find-next))] - - [("up" . "u") - "return to [nth] previous level" - (() (up)) - ((n) - (range-check n) - (let backup ([n n]) - (unless (= n 0) - (up) - (backup (- n 1)))))] - - [("top" . "t") - "return to initial object" - (() - (let top () - (let ([next (state-link current-state)]) - (when next - (set! current-state next) - (top)))))] - - [("forward" . "f") - "move to [nth] next expression" - (() (move 1)) - ((n) - (range-check n) - (move n))] - - [("back" . "b") - "move to [nth] previous expression" - (() (move -1)) - ((n) - (range-check n) - (move (- n)))] - - ["=>" - "send object to procedure" - (() - (let ([x (waiter-read)]) - (unless (eof-object? x) - (let ([x (eval x)]) - (unless (procedure? x) (inspect-error "~s is not a procedure" x)) - (inspector-print (x ((object) 'value))))))) - ((x) - (let ([x (eval x)]) - (unless (procedure? x) (inspect-error "~s is not a procedure" x)) - (inspector-print (x ((object) 'value)))))] - - ["file" - "switch to named source file" - ((path) - (unless (or (string? path) (symbol? path)) - (inspect-error "invalid path ~s" path)) - (open-source-file (if (symbol? path) (symbol->string path) path)))] - - ["list" - "list the current source file [line [count]]" - (() (list-source-file)) - ((n) (list-source-file n)) - ((n m) (list-source-file n m))] - - ["files" - "show open files" - (() - (for-each - (lambda (sf) (show "~a" (sfile-path sf))) - source-files))] - - [("mark" . "m") - "mark location [with symbolic mark]" - (() (put-mark default-mark)) - ((m) (put-mark (make-mark m)))] - - [("goto" . "g") - "go to marked location [mark]" - (() (to-mark default-mark)) - ((m) (to-mark (make-mark m)))] - - [("new-cafe" . "n") - "enter a new cafe" - (() - (newline (console-output-port)) - (new-cafe) - (newline (console-output-port)))] - - [("quit" . "q") - "exit inspector" - (() - (newline (console-output-port)) - (exit))] - - [("reset" . "r") - "reset scheme" - (() - (newline (console-output-port)) - ((outer-reset-handler)))] - - [("abort" . "a") - "abort scheme [with exit code n]" - (() - (newline (console-output-port)) - (abort)) - ((x) - (newline (console-output-port)) - (abort x))] - - [("help" . "h") - "help" - (() - (show " - An overview of the current object is displayed as part of each - prompt. There are commands for displaying more of an object or - inspecting its components. \"?\" displays type-specific command - options and \"??\" displays command options that are always - available. Some commands take parameters, which are entered - following the command on the same line. An empty command line - repeats the previous command. To perform more complex actions, - enter the command \"n\", which creates a new top level with access - to the usual Scheme environment. The inspector is resumed upon - exit from the new top level. Enter \"quit\" (or end-of-file) to - exit from the inspector. -"))] - -)) - -(define empty-dispatch-table (make-dispatch-table)) - -(define pair-dispatch-table - (make-dispatch-table - - [("length" . "l") - "display list length" - (() - (apply (lambda (type len) - (case type - [(proper) (show " proper list, length ~d" len)] - [(improper) (show " improper list, length ~d" len)] - [(circular) (show " circular list, length ~d" len)])) - ((object) 'length)))] - - ["car" - "inspect car of pair" - (() (ref-list 0))] - - ["cdr" - "inspect cdr of pair" - (() (down ((object) 'cdr) #f))] - - [("ref" . "r") - "inspect [nth] car" - (() (ref-list 0)) - ((n) (ref-list n))] - - ["tail" - "inspect [nth] cdr" - (() (down ((object) 'cdr) #f)) - ((n) - (range-check n) - (let tail ([i n]) - (unless (= i 0) - (unless (type? 'pair (object)) (invalid-movement)) - (down ((object) 'cdr) #f) - (tail (- i 1)))))] - - [("show" . "s") - "show [n] elements of list" - (() (display-list (cadr ((object) 'length)))) - ((n) - (range-check n) - (display-list n))] - -)) - -(define vector-dispatch-table - (make-dispatch-table - - [("length" . "l") - "display vector length" - (() (show " ~d elements" ((object) 'length)))] - - [("ref" . "r") - "inspect [nth] element" - (() (ref 0)) - ((n) (ref n))] - - [("show" . "s") - "show [n] elements" - (() (display-refs ((object) 'length))) - ((n) - (range-check n ((object) 'length)) - (display-refs n))] - -)) - -(define fxvector-dispatch-table - (make-dispatch-table - - [("length" . "l") - "display fxvector length" - (() (show " ~d elements" ((object) 'length)))] - - [("ref" . "r") - "inspect [nth] element" - (() (ref 0)) - ((n) (ref n))] - - [("show" . "s") - "show [n] elements" - (() (display-refs ((object) 'length))) - ((n) - (range-check n ((object) 'length)) - (display-refs n))] - -)) - -(define bytevector-dispatch-table - (make-dispatch-table - - [("length" . "l") - "display bytevector length" - (() (show " ~d elements" ((object) 'length)))] - - [("ref" . "r") - "inspect [nth] element" - (() (ref 0)) - ((n) (ref n))] - - [("show" . "s") - "show [n] elements" - (() (display-refs ((object) 'length))) - ((n) - (range-check n ((object) 'length)) - (display-refs n))] - -)) - -(define ftype-struct-dispatch-table - (make-dispatch-table - ["fields" - "inspect fields" - (() (down ((object) 'fields) #f))] - - [("ref" . "r") - "inspect named or nth element" - (() (down ((object) 'ref 0) 0)) - ((f) (down ((object) 'ref f) (and (fixnum? f) f)))] - - ["set!" - "set named element, if assignable" - ((f) - (let ([x (waiter-read)]) - (unless (eof-object? x) - (let ((x (eval x))) - ((object) 'set! f x))))) - ((f v) ((object) 'set! f (eval v)))] - - ["ftype" - "inspect the ftype" - (() (down ((object) 'ftype) #f))] - - [("show" . "s") - "show contents of struct" - (() - (let ([fields (((object) 'fields) 'value)]) - (if (null? fields) - (show "*** struct has no fields ***") - (for-each - (lambda (f i) - (name-label-line-display - ((object) 'ref i) - f - i)) - fields - (iota (length fields))))))])) - -(define ftype-union-dispatch-table - (make-dispatch-table - ["fields" - "inspect fields" - (() (down ((object) 'fields) #f))] - - [("ref" . "r") - "inspect named or nth element" - (() (down ((object) 'ref 0) 0)) - ((f) (down ((object) 'ref f) (and (fixnum? f) f)))] - - ["set!" - "set named element, if assignable" - ((f) - (let ([x (waiter-read)]) - (unless (eof-object? x) - (let ((x (eval x))) - ((object) 'set! f x))))) - ((f v) ((object) 'set! f (eval v)))] - - ["ftype" - "inspect the ftype" - (() (down ((object) 'ftype) #f))] - - [("show" . "s") - "show contents of union" - (() - (let ([fields (((object) 'fields) 'value)]) - (if (null? fields) - (show "*** union has no fields ***") - (for-each - (lambda (f i) - (name-label-line-display - ((object) 'ref i) - f - i)) - fields - (iota (length fields))))))])) - -(define ftype-array-dispatch-table - (make-dispatch-table - [("length" . "l") - "display array length" - (() (show " ~d elements" ((object) 'length)))] - - [("ref" . "r") - "inspect [nth] element" - (() (ref 0)) - ((n) (ref n))] - - ["set!" - "set [nth] element, if assignable" - ((f) - (let ([x (waiter-read)]) - (unless (eof-object? x) - (let ((x (eval x))) - ((object) 'set! f x))))) - ((f v) ((object) 'set! f (eval v)))] - - ["ftype" - "inspect the ftype" - (() (down ((object) 'ftype) #f))] - - [("show" . "s") - "show [n] elements" - (() (display-refs ((object) 'length))) - ((n) - (range-check n ((object) 'length)) - (display-refs n))] - )) - -(define ftype-pointer-dispatch-table - (make-dispatch-table - [("ref" . "r") - "inspect target of pointer" - (() (down ((object) 'ref) #f)) - ((n) - (unless (memv n '(* 0)) (invalid-movement)) - (down ((object) 'ref) #f))] - - ["set!" - "set target of pointer, if assignable" - (() - (let ([x (waiter-read)]) - (unless (eof-object? x) - (let ((x (eval x))) - ((object) 'set! x))))) - ((v) ((object) 'set! (eval v)))] - - ["ftype" - "inspect ftype of target" - (() (down ((object) 'ftype) #f))] - - [("show" . "s") - "show the target" - (() (label-line-display ((object) 'ref) 0))] - )) - -(define ftype-function-dispatch-table - (make-dispatch-table - ["name" - "inspect foreign-function name" - (() (down ((object) 'name) #f))] - - ["address" - "inspect foreign-function address" - (() (down ((object) 'address) #f))] - - ["ftype" - "inspect ftype of target" - (() (down ((object) 'ftype) #f))] - - [("show" . "s") - "show the target" - (() (label-line-display ((object) 'name) 0) - (label-line-display ((object) 'address) 1))] - )) - -(define ftype-bits-dispatch-table - (make-dispatch-table - ["fields" - "inspect fields" - (() (down ((object) 'fields) #f))] - - [("ref" . "r") - "inspect named or nth element" - (() (down ((object) 'ref 0) 0)) - ((f) (down ((object) 'ref f) (and (fixnum? f) f)))] - - ["set!" - "set named element, if assignable" - ((f) - (let ([x (waiter-read)]) - (unless (eof-object? x) - (let ((x (eval x))) - ((object) 'set! f x))))) - ((f v) ((object) 'set! f (eval v)))] - - ["ftype" - "inspect the ftype" - (() (down ((object) 'ftype) #f))] - - [("show" . "s") - "show bit fields" - (() - (let ([fields (((object) 'fields) 'value)]) - (if (null? fields) - (show "*** no fields ***") - (for-each - (lambda (f i) - (name-label-line-display - ((object) 'ref i) - f - i)) - fields - (iota (length fields))))))])) - -(define record-dispatch-table - (make-dispatch-table - - ["fields" - "inspect fields" - (() (down ((object) 'fields) #f))] - - ["name" - "inspect record name" - (() (down ((object) 'name) #f))] - - ["rtd" - "inspect record-type descriptor" - (() (down ((object) 'rtd) #f))] - - [("ref" . "r") - "inspect named or nth element" - ((f) (down ((object) 'ref f) (and (fixnum? f) f)))] - - ["set!" - "set named element, if assignable" - ((f) - (let ([x (waiter-read)]) - (unless (eof-object? x) - (let ((x (eval x))) - ((object) 'set! f x))))) - ((f v) ((object) 'set! f (eval v)))] - - [("show" . "s") - "show contents of record" - (() - (when (and (eq? (subset-mode) 'system) - (record-type-opaque? (((object) 'rtd) 'value))) - (show "*** inspecting opaque record ***")) - (let ([fields (((object) 'fields) 'value)]) - (if (null? fields) - (show "*** record has no fields ***") - (for-each - (lambda (f i) - (name-label-line-display - (if ((object) 'accessible? i) - ((object) 'ref i) - (inspect/object "*** inaccessible ***")) - f - i)) - fields - (iota (length fields))))))] -)) - - -(define string-dispatch-table - (make-dispatch-table - - [("length" . "l") - "display string length" - (() (show " ~d characters" ((object) 'length)))] - - [("ref" . "r") - "inspect [nth] character" - (() (ref 0)) - ((n) (ref n))] - - [("show" . "s") - "show [n] characters" - (() (display-chars ((object) 'length) charschemecode 5)) - ((n) - (range-check n ((object) 'length)) - (display-chars n charschemecode 5))] - - ["unicode" - "display [n] characters as hexadecimal unicode codes" - (() (display-chars ((object) 'length) unicodehexcode 8)) - ((n) - (range-check n ((object) 'length)) - (display-chars n unicodehexcode 8))] - - ["ascii" - "display [n] characters as hexadecimal ascii codes" - (() (display-chars ((object) 'length) asciihexcode 16)) - ((n) - (range-check n ((object) 'length)) - (display-chars n asciihexcode 16))] -)) - -(define char-dispatch-table - (make-dispatch-table - - ["unicode" - "display character as hexadecimal ascii code" - (() (show " U+~x" (unicodehexcode ((object) 'value))))] - - ["ascii" - "display character as hexadecimal ascii code" - (() (show " ~x" (asciihexcode ((object) 'value))))] - -)) - -(define box-dispatch-table - (make-dispatch-table - - ["unbox" - "inspect contents of box" - (() (down ((object) 'unbox) #f))] - - [("ref" . "r") - "inspect contents of box" - (() (down ((object) 'unbox) #f))] - - [("show" . "s") - "show contents of box" - (() (label-line-display ((object) 'unbox) 0)) - ((n) - (range-check n 0) - (label-line-display ((object) 'unbox) 0))] -)) - - -(define system-symbol-dispatch-table - (make-dispatch-table - - [("ref" . "r") - "inspect value field [n] of symbol" - (() - (down ((object) 'top-level-value) 0)) - ((n) - (range-check n 5) - (down ((object) - (case n - [(0) 'top-level-value] - [(1) '$top-level-value] - [(2) 'name] - [(3) 'property-list] - [(4) 'system-property-list] - [(5) 'symbol-hash])) - n))] - - [("value" . "v") - "inspect top-level-value of symbol" - (() (down ((object) 'top-level-value) 0))] - - [("value-slot" . "vs") - "inspect value slot of symbol" - (() (down ((object) '$top-level-value) 0))] - - [("name" . "n") - "inspect name of symbol" - (() (down ((object) 'name) 1))] - - [("property-list" . "pl") - "inspect property-list of symbol" - (() (down ((object) 'property-list) 2))] - - [("system-property-list" . "spl") - "inspect system property-list of symbol" - (() (down ((object) 'system-property-list) 4))] - - [("symbol-hash" . "sh") - "inspect hash code" - (() (down ((object) 'symbol-hash) 5))] - - [("show" . "s") - "show fields of symbol" - (() - (name-label-line-display ((object) 'top-level-value) "top-level value" 0) - (name-label-line-display ((object) '$top-level-value) "value slot" 1) - (name-label-line-display ((object) 'name) "name" 2) - (name-label-line-display ((object) 'property-list) "properties" 3) - (name-label-line-display ((object) 'system-property-list) "system properties" 4) - (name-label-line-display ((object) 'symbol-hash) "hash code" 5))] -)) - -(define symbol-dispatch-table - (make-dispatch-table - - [("ref" . "r") - "inspect value field [n] of symbol" - (() - (down ((object) 'top-level-value) 0)) - ((n) - (range-check n 2) - (down ((object) - (case n - [(0) 'top-level-value] - [(1) 'name] - [(2) 'property-list])) - n))] - - [("value" . "v") - "inspect top-level-value of symbol" - (() (down ((object) 'top-level-value) 0))] - - [("name" . "n") - "inspect name of symbol" - (() (down ((object) 'name) 1))] - - [("property-list" . "pl") - "inspect property-list of symbol" - (() (down ((object) 'property-list) 2))] - - [("show" . "s") - "show fields of symbol" - (() - (name-label-line-display ((object) 'top-level-value) "top level value" 0) - (name-label-line-display ((object) 'name) "name" 1) - (name-label-line-display ((object) 'property-list) "properties" 2))] -)) - -(define procedure-dispatch-table - (make-dispatch-table - - [("length" . "l") - "display number of free variables" - (() (show " ~d free variables" ((object) 'length)))] - - [("ref" . "r") - "inspect [nth] free variable" - (() (ref 0)) - ((x) (variable-ref x))] - - [("set!" . "!") - "set [nth or named] free variable to value, if assignable" - (() - (let ([e (waiter-read)]) - (unless (eof-object? e) - (set 0 ((object) 'eval e))))) - ((x) - (let ([e (waiter-read)]) - (unless (eof-object? e) - (variable-set x ((object) 'eval e))))) - ((x e) (variable-set x ((object) 'eval e)))] - - [("eval" . "e") - "evaluate expression in context of procedure environment" - (() - (let ([x (waiter-read)]) - (unless (eof-object? x) - (inspector-print ((object) 'eval x))))) - ((x) - (inspector-print ((object) 'eval x)))] - - [("show" . "s") - "show code and free variables" - (() - (let ([source (((object) 'code) 'source)]) - (when source (name-line-display source "code"))) - (when (> ((object) 'length) 0) - (show "~afree variables:" line-indent) - (display-variable-refs ((object) 'length))))] - - [("code" . "c") - "inspect the code for the procedure" - (() - (let ([source (((object) 'code) 'source)]) - (if source - (down source #f) - (show "source code not available"))))] - - ["file" - "switch to source file containing the procedure" - (() (open-recorded-source-file ((object) 'code))) - ((path) - (unless (or (string? path) (symbol? path)) - (inspect-error "invalid path ~s" path)) - (open-source-file (if (symbol? path) (symbol->string path) path)))] -)) - -(define code-dispatch-table - (make-dispatch-table - - [("length" . "l") - "display number of free variables" - (() (show " ~d free variables" ((object) 'free-count)))] - - [("show" . "s") - "show code" - (() - (let ([source ((object) 'source)]) - (when source (name-line-display source "code"))))] - - [("code" . "c") - "inspect the code" - (() - (let ([source ((object) 'source)]) - (if source - (down source #f) - (show "source code not available"))))] - - ["file" - "switch to source file containing the procedure" - (() (open-recorded-source-file (object))) - ((path) - (unless (or (string? path) (symbol? path)) - (inspect-error "invalid path ~s" path)) - (open-source-file (if (symbol? path) (symbol->string path) path)))] -)) - - -(define continuation-dispatch-table - (let () - (define reposition - (lambda (incr) - (let ([old-pos ((object) 'pos)]) - (unless (fx= old-pos 0) (up)) - (let ([pos (fx+ old-pos incr)]) - (when (fx>= pos ((object) 'depth)) (invalid-movement)) - (if (fx> pos 0) - (let ((link ((object) 'reposition pos))) - (unless (type? 'continuation link) (invalid-movement)) - (down link #f)) - (unless (fx= pos 0) (invalid-movement))))))) - - (define continuation-show - (lambda (free?) - (name-line-display ((object) 'link) "continuation") - (let ([source (((object) 'code) 'source)]) - (when source (name-line-display source "procedure code"))) - (let ([source ((object) 'source)]) - (when source (name-line-display source "call code"))) - (let ([cp ((object) 'closure)]) - (when cp (name-line-display cp "closure"))) - (let ([len ((object) (if free? 'length 'frame-length))]) - (when (> len 0) - (show "~a~a:" line-indent (if free? "frame and free variables" "frame variables")) - (display-variable-refs len))))) - - (make-dispatch-table - - [("length" . "l") - "display number of frame and closure variables" - (() (show " ~d variables" ((object) 'length)))] - - ["depth" - "display number of frames in continuation stack" - (() (let ((d ((object) 'depth))) - (show (if (= d 1) " ~d frame" " ~d frames") d)))] - - [("ref" . "r") - "inspect [named or nth] variable" - (() (ref 0)) - ((x) (variable-ref x))] - - [("set!" . "!") - "set [named or nth] variable to value, if assignable" - (() - (let ([e (waiter-read)]) - (unless (eof-object? e) - (set 0 ((object) 'eval e))))) - ((x) - (let ([e (waiter-read)]) - (unless (eof-object? e) - (variable-set x ((object) 'eval e))))) - ((x e) (variable-set x ((object) 'eval e)))] - - [("forward" . "f") - "move to [nth] next frame" - (() (reposition 1)) - ((pos) - (range-check pos) - (reposition pos))] - - [("back" . "b") - "move to [nth] previous frame" - (() (reposition -1)) - ((pos) - (range-check pos) - (reposition (fx- pos)))] - - [("down" . "d") - "inspect [nth] next frame" - (() (let ((link ((object) 'link))) - (unless (type? 'continuation link) (invalid-movement)) - (down link #f))) - ((n) - (range-check n (- ((object) 'depth) 1)) - (let ((link ((object) 'link* n))) - (unless (type? 'continuation link) (invalid-movement)) - (down link #f)))] - - [("closure" . "cp") - "inspect the frame's closure, if any" - (() (let ([cp ((object) 'closure)]) - (unless cp (inspect-error "this frame has no closure")) - (down cp #f)))] - - [("eval" . "e") - "evaluate expression in context of current frame" - (() - (let ([x (waiter-read)]) - (unless (eof-object? x) - (inspector-print ((object) 'eval x))))) - ((x) - (inspector-print ((object) 'eval x)))] - - [("show" . "s") - "show frame with free variables" - (() (continuation-show #t))] - - [("show-local" . "sl") - "show frame without free variables" - (() (continuation-show #f))] - - [("show-frames" . "sf") - "show the next [n] frames" - (() (display-links (most-positive-fixnum))) - ((n) - (range-check n) - (display-links n))] - - ["call" - "inspect the code for the pending call" - (() - (let ([source ((object) 'source)]) - (if source - (down source #f) - (show "source code not available"))))] - - [("code" . "c") - "inspect the code for the pending procedure" - (() - (let ([source (((object) 'code) 'source)]) - (if source - (down source #f) - (show "source code not available"))))] - - ["file" - "switch to source file containing the pending call" - (() (open-recorded-source-file (object))) - ((path) - (unless (or (string? path) (symbol? path)) - (inspect-error "invalid path ~s" path)) - (open-source-file (if (symbol? path) (symbol->string path) path)))] - - ))) - -(define port-dispatch-table - (make-dispatch-table - - [("show" . "s") - "show port contents" - (() - (name-line-display ((object) 'name) "name") - (name-line-display ((object) 'handler) "handler") - (when ((object) 'input?) - (show "~ainput size: ~s" line-indent ((object) 'input-size)) - (show "~ainput index: ~s" line-indent ((object) 'input-index))) - (when ((object) 'output?) - (show "~aoutput size: ~s" line-indent ((object) 'output-size)) - (show "~aoutput index: ~s" line-indent ((object) 'output-index))))] - - ["name" - "inspect port name" - (() (down ((object) 'name) #f))] - - ["handler" - "inspect port handler" - (() (down ((object) 'handler) #f))] - - [("output-buffer" . "ob") - "inspect output buffer" - (() (if ((object) 'output?) - (down ((object) 'output-buffer) #f) - (show "not an output port")))] - - [("input-buffer" . "ib") - "inspect input buffer" - (() (if ((object) 'input?) - (down ((object) 'input-buffer) #f) - (show "not an input port")))] -)) - -(define tlc-dispatch-table - (make-dispatch-table - - ["keyval" - "inspect keyval field" - (() (down ((object) 'keyval) #f))] - - ["ht" - "inspect ht field" - (() (down ((object) 'ht) #f))] - - ["next" - "inspect next field" - (() (down ((object) 'next) #f))] - - [("ref" . "r") - "inspect named field" - ((x) - (down ((object) - (case x - [(keyval) 'keyval] - [(ht) 'ht] - [(next) 'next] - [else (invalid-command)])) - x))] - - [("show" . "s") - "show fields of tlc" - (() - (name-line-display ((object) 'keyval) "keyval") - (name-line-display ((object) 'ht) "ht") - (name-line-display ((object) 'next) "next"))] -)) - -(set! inspect - (lambda (x) - (let ([t (set-timer 0)]) - (call/cc - (lambda (k) - (fluid-let ([current-state (make-state (inspect/object x))] - [marks (make-eq-hashtable)] - [source-files '()]) - (parameterize ([outer-reset-handler (reset-handler)] - [exit-handler k] - [$interrupt reset]) - (put-mark default-mark) - (dynamic-wind - void - (lambda () (inspector '("?"))) - (lambda () (for-each close-source-file source-files))))))) - (set-timer t)) - (void))) - -) - -(define inspect/object - (lambda (x) - (define compute-size - (let ([size-ht #f]) - (lambda (x g) - (unless (or (and (fixnum? g) (fx<= 0 g (collect-maximum-generation))) (eq? g 'static)) - ($oops 'inspector-object "invalid generation ~s" g)) - ; using a common size-ht for a single inspect/object call means: - ; (inspect (let ([x (list 1 2)]) (set-car! x x) (set-car! (cdr x) x) (set-cdr! (cdr x) x) x)) - ; size => 16 - ; cdr, size => 8 - ; might be what we want, might not be - (unless size-ht (set! size-ht (make-eq-hashtable))) - ($compute-size x (if (eq? g 'static) (constant static-generation) g) size-ht)))) - - (define-syntax make-object-maker - (lambda (x) - (syntax-case x () - [(_ object-name inits [method args e1 e2 ...] ...) - (andmap identifier? #'(object-name method ...)) - #'(lambda inits - (let ([method (lambda args e1 e2 ...)] ...) - (lambda (m . rest) - (case m - [(type) 'object-name] - [(make-me-a-child) (make-object (car rest))] - [(method) (#2%apply method rest)] - ... - [else ($oops 'inspector-object - "invalid message ~s to object type ~s" - m - 'object-name)]))))]))) - - (define frame-eval - (lambda (vars expr) - (define frame-name - (let ((ls '(%0 %1 %2 %3 %4 %5 %6 %7))) - (let ((n (length ls))) - (lambda (i) - (if (< i n) - (list-ref ls i) - (string->symbol (format "%~d" i))))))) - (define ->nongensym - (lambda (name) - (if (gensym? name) - (string->symbol (symbol->string name)) - name))) - (let ((n (vector-length vars))) - (eval (let f ((i 0)) - (if (= i n) - expr - (let ([var (vector-ref vars i)] - [body (f (+ i 1))]) - (let ([raw-val (var 'raw-value)] - [name (var 'name)] - [fv (frame-name i)] - [t (gensym)]) - `(let ([,t (quote ,raw-val)]) - (let-syntax ([,fv ,(if (assignable? raw-val) - `(identifier-syntax [id (car ,t)] [(set! id e) (set-car! ,t e)]) - `(identifier-syntax - [id ,t] - [(set! id e) - (syntax-error #'id "cannot set non-assigned variable")]))]) - ,(if name `(begin (alias ,(->nongensym name) ,fv) ,body) body))))))))))) - - (define make-pair-object - (make-object-maker pair (x) - [value () x] - [car () (make-object (car x))] - [cdr () (make-object (cdr x))] - [length () - (let ([ht (make-eq-hashtable)]) - (let length ([x x] [n 0]) - (cond - [(null? x) `(proper ,n)] - [(not (pair? x)) `(improper ,n)] - [else - (let ([a (eq-hashtable-cell ht x #f)]) - (if (cdr a) - `(circular ,n) - (begin (set-cdr! a #t) - (length (cdr x) (+ n 1)))))])))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-box-object - (make-object-maker box (x) - [value () x] - [unbox () (make-object (unbox x))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-tlc-object - (make-object-maker tlc (x) - [value () x] - [keyval () (make-object ($tlc-keyval x))] - [ht () (make-object ($tlc-ht x))] - [next () (make-object ($tlc-next x))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-vector-object - (make-object-maker vector (x) - [value () x] - [length () (vector-length x)] - [ref (i) - (unless (and (fixnum? i) (fx< -1 i (vector-length x))) - ($oops 'vector-object "invalid index ~s" i)) - (make-object (vector-ref x i))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-fxvector-object - (make-object-maker fxvector (x) - [value () x] - [length () (fxvector-length x)] - [ref (i) - (unless (and (fixnum? i) (fx< -1 i (fxvector-length x))) - ($oops 'fxvector-object "invalid index ~s" i)) - (make-object (fxvector-ref x i))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-bytevector-object - (make-object-maker bytevector (x) - [value () x] - [length () (bytevector-length x)] - [ref (i) - (unless (and (fixnum? i) (fx< -1 i (bytevector-length x))) - ($oops 'bytevector-object "invalid index ~s" i)) - (make-object (bytevector-u8-ref x i))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-ftype-pointer-object - (lambda (x) - (define (unrecognized-ux ux) - ($oops 'ftype-pointer-object "unrecognized ftype-pointer type ~s" x)) - (define (invalid-field-specifier f) - ($oops 'ftype-pointer-object "invalid field specifier ~s" f)) - (define (invalid-index f) - ($oops 'ftype-pointer-object "invalid index ~s" f)) - (define (get-field f field*) - (cond - [(assq f field*) => cdr] - [(and (fixnum? f) (#%$fxu< f (length field*))) - (cdr (list-ref field* f))] - [else (invalid-field-specifier f)])) - (define (deref x) - (let ([ux ($unwrap-ftype-pointer x)]) - (record-case ux - [(struct union array * bits) ignore (make-object x)] - [(base) (type getter setter) (make-object (getter))] - [else (unrecognized-ux ux)]))) - (define (deset! who x v) - (let ([ux ($unwrap-ftype-pointer x)]) - (record-case ux - [(struct union array bits) ignore ($oops who "cannot assign struct, union, or array")] - [(*) (get-fptr set-fptr!) (set-fptr! who v)] - [(base) (type getter setter) (setter v)] - [else (unrecognized-ux ux)]))) - (let ([ux ($unwrap-ftype-pointer x)]) - (record-case ux - [(struct) field* - ((make-object-maker ftype-struct (x) - [value () x] - [ftype () (make-object (ftype-pointer-ftype x))] - [fields () (make-object (map (lambda (x) (or (car x) '_)) field*))] - [length () (length field*)] - [ref (f) (deref (get-field f field*))] - [set! (f v) (deset! 'ftype-struct-object (get-field f field*) v)] - [size (g) (compute-size x g)] - [write (p) (write `(ftype struct ...) p)] - [print (p) (pretty-print (ftype-pointer->sexpr x) p)]) - x)] - [(union) field* - ((make-object-maker ftype-union (x) - [value () x] - [ftype () (make-object (ftype-pointer-ftype x))] - [fields () (make-object (map (lambda (x) (or (car x) '_)) field*))] - [length () (length field*)] - [ref (f) (deref (get-field f field*))] - [set! (f v) (deset! 'ftype-union-object (get-field f field*) v)] - [size (g) (compute-size x g)] - [write (p) (write `(ftype union ...) p)] - [print (p) (pretty-print (ftype-pointer->sexpr x) p)]) - x)] - [(array) (n get-fptr) - ((make-object-maker ftype-array (x) - [value () x] - [ftype () (make-object (ftype-pointer-ftype x))] - [length () n] - [ref (f) - (unless (and (integer? f) (exact? f) (#%$fxu< f n)) - (invalid-index f)) - (deref (get-fptr f))] - [set! (f v) - (unless (and (integer? f) (exact? f) (#%$fxu< f n)) - (invalid-index f)) - (deset! 'ftype-array-object (get-fptr f) v)] - [size (g) (compute-size x g)] - [write (p) (write `(ftype array ...) p)] - [print (p) (pretty-print (ftype-pointer->sexpr x) p)]) - x)] - [(*) (get-fptr set-fptr!) - ((make-object-maker ftype-* (x) - [value () x] - [ftype () (make-object (ftype-pointer-ftype x))] - [ref () (deref (get-fptr))] - [set! (v) (deset! 'ftype-*-object (get-fptr) v)] - [size (g) (compute-size x g)] - [write (p) (write `(ftype * ...) p)] - [print (p) (pretty-print (ftype-pointer->sexpr x) p)]) - x)] - [(bits) field* - ((make-object-maker ftype-bits (x) - [value () x] - [ftype () (make-object (ftype-pointer-ftype x))] - [fields () (make-object (map (lambda (x) (or (car x) '_)) field*))] - [length () (length field*)] - [ref (f) (apply (lambda (getter setter) (make-object (getter))) - (get-field f field*))] - [set! (f v) (apply (lambda (getter setter) (make-object (setter v))) - (get-field f field*))] - [size (g) (compute-size x g)] - [write (p) (write `(ftype bits ...) p)] - [print (p) (pretty-print (ftype-pointer->sexpr x) p)]) - x)] - [(base) (type getter setter) - ((make-object-maker ftype-base (x) - [value () x] - [ftype () (make-object (ftype-pointer-ftype x))] - [ref () (make-object (getter))] - [set! (v) (setter v)] - [size (g) (compute-size x g)] - [write (p) (write `(ftype ,type ...) p)] - [print (p) (pretty-print (ftype-pointer->sexpr x) p)]) - x)] - [(function) (name) - ((make-object-maker ftype-function (x) - [value () x] - [ftype () (make-object (ftype-pointer-ftype x))] - [address () (make-object (ftype-pointer-address x))] - [name () (make-object name)] - [size (g) (compute-size x g)] - [write (p) (write `(ftype function ...) p)] - [print (p) (pretty-print (ftype-pointer->sexpr x) p)]) - x)] - [else (unrecognized-ux ux)])))) - - (define make-record-object - (lambda (x) - (let* ((rtd ($record-type-descriptor x)) - (fields (csv7:record-type-field-names rtd))) - (define check-field - (lambda (f) - (unless (or (and (symbol? f) (memq f fields)) - (and (fixnum? f) (fx>= f 0) (fx< f (length fields)))) - ($oops 'record-object "invalid field specifier ~s" f)))) - ((make-object-maker record (x) - [value () x] - [length () (length fields)] - [fields () (make-object fields)] - [accessible? (f) - (check-field f) - (csv7:record-field-accessible? rtd f)] - [mutable? (f) - (check-field f) - (csv7:record-field-mutable? rtd f)] - [name () (make-object (csv7:record-type-name rtd))] - [rtd () (make-object rtd)] - [ref (f) - (check-field f) - (unless (csv7:record-field-accessible? rtd f) - ($oops 'record-object "field ~s is inaccessible" f)) - (make-object ((csv7:record-field-accessor rtd f) x))] - [set! (f v) - (check-field f) - (unless (csv7:record-field-mutable? rtd f) - ($oops 'record-object "field ~s is immutable" f)) - ((csv7:record-field-mutator rtd f) x v)] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)]) - x)))) - - (define make-string-object - (make-object-maker string (x) - [value () x] - [length () (string-length x)] - [ref (i) - (unless (and (fixnum? i) (< -1 i (string-length x))) - ($oops 'string-object "invalid index ~s" i)) - (make-object (string-ref x i))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-simple-object - (make-object-maker simple (x) - [value () x] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-unbound-object - (make-object-maker unbound (x) - [value () x] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-procedure-object - (lambda (x) - (real-make-procedure-object x (list->vector (make-procedure-vars x))))) - - (define real-make-procedure-object - (make-object-maker procedure (x vars) - [value () x] - [length () (vector-length vars)] - [ref (i) - (unless (and (fixnum? i) (fx< -1 i (vector-length vars))) - ($oops 'procedure-object "invalid index ~s" i)) - (vector-ref vars i)] - [eval (x) (frame-eval vars x)] - [code () (make-object ($closure-code x))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-procedure-vars - (lambda (x) - (include "types.ss") - (let ([code ($closure-code x)]) - (let ([info ($code-info code)] - [len ($code-free-count code)]) - (let ([free (and (code-info? info) (code-info-free info))]) - (unless (or (not free) (fx= (vector-length free) len)) - ($oops 'inspector "invalid info structure ~s" info)) - (let vars ([i 0]) - (if (= i len) - '() - (cons (make-variable-object - ($closure-ref x i) - (and free (vector-ref free i))) - (vars (+ i 1)))))))))) - - (define assignable? - (lambda (raw-val) - (and (pair? raw-val) ($unbound-object? (cdr raw-val))))) - - (define make-variable-object - (make-object-maker variable (x name) - [name () name] - [assignable? () (assignable? x)] - [raw-value () x] - [ref () (make-object - (if (assignable? x) - (car x) - x))] - [set! (v) (make-object - (if (assignable? x) - (set-car! x v) - ($oops 'variable-object "unassignable variable")))] - [size (g) - (if (assignable? x) - (fx+ (constant size-pair) (compute-size (car x) g)) - (compute-size x g))] - [write (p) (display "#" p)] - [print (p) (display "#" p) (newline p)])) - - (define get-reloc-objs - (foreign-procedure "(cs)s_get_reloc" - (scheme-object) scheme-object)) - - (module (get-code-src get-code-sexpr) - (include "types.ss") - (define get-code-src - (lambda (x) - (let ([info ($code-info x)]) - (and (code-info? info) (code-info-src info))))) - (define get-code-sexpr - (lambda (x) - (let ([info ($code-info x)]) - (and (code-info? info) (code-info-sexpr info)))))) - - (define make-code-object - (make-object-maker code (x) - [value () x] - [name () ($code-name x)] - [info () (make-object ($code-info x))] - [free-count () ($code-free-count x)] - [source () - (cond - [(get-code-sexpr x) => make-object] - [else #f])] - [source-path () (return-source (get-code-src x))] - [source-object () (get-code-src x)] - [reloc () (make-object (get-reloc-objs x))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define return-source - (lambda (src) - (include "types.ss") - (if src - (call-with-values - (lambda () ((current-locate-source-object-source) src #t #f)) - (case-lambda - [() (let ([sfd (source-sfd src)] [fp (source-bfp src)]) - (values (source-file-descriptor-name sfd) fp))] - [(path line char) (values path line char)])) - (values)))) - - (define-who make-continuation-object - (lambda (x pos) - (include "types.ss") - (define find-rpi - (lambda (offset rpis) - (let f ([start 0] [end (fx1- (vector-length rpis))]) - (if (fx< end start) - #f - (let* ([curr (fx+ (fx/ (fx- end start) 2) start)] - [rpi (vector-ref rpis curr)] - [rpi-offset (rp-info-offset rpi)]) - (cond - [(fx= offset rpi-offset) rpi] - [(fx< offset rpi-offset) (f start (fx1- curr))] - [else (f (fx1+ curr) end)])))))) - ($split-continuation x 0) - (let ([info ($code-info ($continuation-return-code x))] - [offset ($continuation-return-offset x)] - [len ($continuation-stack-length x)] - [lpm ($continuation-return-livemask x)]) - (cond - [(and (code-info? info) (code-info-rpis info) (find-rpi offset (code-info-rpis info))) => - (lambda (rpi) - (let ([cookie '(chocolate . chip)]) - (let ([vals (make-vector len cookie)] [vars (make-vector len '())] [live (code-info-live info)]) - ; fill vals based on live-pointer mask - (let f ([i 1] [lpm lpm]) - (unless (>= i len) - (when (odd? lpm) - (vector-set! vals (fx1- i) ($continuation-stack-ref x i))) - (f (fx1+ i) (ash lpm -1)))) - ; fill vars based on code-info variable mask - (let f ([i 0] [mask (rp-info-mask rpi)]) - (unless (eqv? mask 0) - (when (odd? mask) - (let ([p (vector-ref live i)]) - (let ([index (fx1- (cdr p))]) - (vector-set! vars index (cons (car p) (vector-ref vars index)))))) - (f (+ i 1) (ash mask -1)))) - ; create return vector - (with-values - (let f ([i 0] [count 0] [cp #f] [cpvar* '()]) - (if (fx= i len) - (if cp - (let ([v (let f ([count count] [cpvar* cpvar*]) - (if (null? cpvar*) - (make-vector count) - (let ([v (f (fx+ count 1) (cdr cpvar*))]) - (vector-set! v count (car cpvar*)) - v)))]) - (values v count cp)) - (values (make-vector count) count cp)) - (let ([obj (vector-ref vals i)] [var* (vector-ref vars i)]) - (cond - [(eq? obj cookie) - (unless (null? var*) ($oops who "expected value for ~s but it was not in lpm" (car var*))) - (f (fx1+ i) count cp cpvar*)] - [(null? var*) - (let-values ([(v frame-count cp) (f (fx1+ i) (fx1+ count) cp cpvar*)]) - (vector-set! v count (make-variable-object obj #f)) - (values v frame-count cp))] - [else - (let g ([var* var*] [count count] [cp cp] [cpvar* cpvar*]) - (if (null? var*) - (f (fx1+ i) count cp cpvar*) - (let ([var (car var*)]) - (if (eq? var cpsymbol) - (g (cdr var*) count obj (if (procedure? obj) (make-procedure-vars obj) '())) - (cond - [(pair? var) ; closure environment represented as a pair - (unless (pair? obj) - ($oops who "expected pair value for paired environment, not ~s" obj)) - (g (cdr var*) count obj (list - (make-variable-object (car obj) (car var)) - (make-variable-object (cdr obj) (cdr var))))] - [(vector? var) ; closure environment represented as a vector - (unless (vector? obj) - ($oops who "expected vector value for vector environment, not ~s" obj)) - (g (cdr var*) count obj (map (lambda (obj var) (make-variable-object obj var)) - (vector->list obj) - (vector->list var)))] - [else - (let-values ([(v frame-count cp) (g (cdr var*) (fx1+ count) cp cpvar*)]) - (vector-set! v count (make-variable-object obj var)) - (values v frame-count cp))])))))])))) - (lambda (v frame-count cp) - (real-make-continuation-object x (rp-info-src rpi) (rp-info-sexpr rpi) cp v frame-count pos))))))] - [else - (let ([v (list->vector - (let f ([i 1] [lpm lpm]) - (cond - [(>= i len) '()] - [(odd? lpm) - (cons (make-variable-object ($continuation-stack-ref x i) #f) - (f (fx1+ i) (ash lpm -1)))] - [else (f (fx1+ i) (ash lpm -1))])))]) - (real-make-continuation-object x #f #f #f v (vector-length v) pos))])))) - - (define real-make-continuation-object - (let ((continuation-depth - (foreign-procedure "(cs)continuation_depth" (scheme-object) - iptr))) - (make-object-maker continuation (x src sexpr cp vars frame-count pos) - [value () x] - [length () (vector-length vars)] - [closure () (and cp (make-object cp))] - [frame-length () frame-count] - [depth () (continuation-depth x)] - [ref (i) - (unless (and (fixnum? i) (fx< -1 i (vector-length vars))) - ($oops 'continuation-object "invalid index ~s" i)) - (vector-ref vars i)] - [pos () pos] - [reposition (pos) - (let ((k (and (fixnum? pos) (fx> pos 0) ($split-continuation x pos)))) - (unless k ($oops 'continuation-object "invalid position ~s" pos)) - (make-continuation-object k pos))] - [link () (make-object ($continuation-link x))] - [link* (i) - (let ((k (and (fixnum? i) (fx>= i 0) ($split-continuation x i)))) - (unless k ($oops 'continuation-object "invalid link* depth ~s" i)) - (make-object k))] - [eval (x) (frame-eval vars x)] - [code () (make-object ($continuation-return-code x))] - [source () (and sexpr (make-object sexpr))] - [source-object () src] - [source-path () (return-source src)] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)]))) - - (define make-port-object - (make-object-maker port (x) - [value () x] - [input? () (input-port? x)] - [output? () (output-port? x)] - [binary? () (binary-port? x)] - [closed? () (port-closed? x)] - [handler () (make-object ($port-handler x))] - [output-buffer () (and (output-port? x) - (make-object - (if (textual-port? x) - (textual-port-output-buffer x) - (binary-port-output-buffer x))))] - [output-size () (and (output-port? x) - (if (textual-port? x) - (textual-port-output-size x) - (binary-port-output-size x)))] - [output-index () (and (output-port? x) - (if (textual-port? x) - (textual-port-output-index x) - (binary-port-output-index x)))] - [input-buffer () (and (input-port? x) - (make-object - (if (textual-port? x) - (textual-port-input-buffer x) - (binary-port-input-buffer x))))] - [input-size () (and (input-port? x) - (if (textual-port? x) - (textual-port-input-size x) - (binary-port-input-size x)))] - [input-index () (and (input-port? x) - (if (textual-port? x) - (textual-port-input-index x) - (binary-port-input-index x)))] - [info () (make-object ($port-info x))] - [name () (make-object (port-name x))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-symbol-object - (make-object-maker symbol (x) - [value () x] - [gensym? () (gensym? x)] - [top-level-value () - (if (top-level-bound? x) - (make-object (top-level-value x)) - (make-object ($unbound-object)))] - [$top-level-value () - (if ($top-level-bound? x) - (make-object ($top-level-value x)) - (make-object ($unbound-object)))] - [system-property-list () (make-object ($system-property-list x))] - [symbol-hash () (make-object ($symbol-hash x))] - [name () (make-object (symbol->string x))] - [property-list () (make-object ($symbol-property-list x))] - [size (g) (compute-size x g)] - [write (p) (write x p)] - [print (p) (pretty-print x p)])) - - (define make-object - (lambda (x) - (cond - [(pair? x) (make-pair-object x)] - [(symbol? x) (make-symbol-object x)] - [(vector? x) (make-vector-object x)] - [(fxvector? x) (make-fxvector-object x)] - [(bytevector? x) (make-bytevector-object x)] - ; ftype-pointer? test must come before record? test - [($ftype-pointer? x) (make-ftype-pointer-object x)] - [(or (record? x) (and (eq? (subset-mode) 'system) ($record? x))) - (make-record-object x)] - [(string? x) (make-string-object x)] - [(box? x) (make-box-object x)] - [(procedure? x) - (if ($continuation? x) - (if (= ($continuation-stack-length x) - (constant unscaled-shot-1-shot-flag)) - (make-simple-object x) - (make-continuation-object x 0)) - (make-procedure-object x))] - [($code? x) (make-code-object x)] - [(port? x) (make-port-object x)] - [($unbound-object? x) (make-unbound-object x)] - [($tlc? x) (make-tlc-object x)] - [else (make-simple-object x)]))) - - (make-object x))) - -(let () - (define rtd-size (csv7:record-field-accessor #!base-rtd 'size)) - (define rtd-flds (csv7:record-field-accessor #!base-rtd 'flds)) - (define $generation (foreign-procedure "(cs)generation" (ptr) ptr)) - (define $get-code-obj (foreign-procedure "(cs)get_code_obj" (int ptr iptr iptr) ptr)) - (define $code-reloc-size - (lambda (x) - (let ([reloc-table ($object-ref 'scheme-object x (constant code-reloc-disp))]) - (if (eqv? reloc-table 0) - 0 - ($object-ref 'iptr reloc-table (constant reloc-table-size-disp)))))) - (define $code-length - (lambda (x) - ($object-ref 'iptr x (constant code-length-disp)))) - (define $get-reloc - (lambda (x i) - (let ([reloc-table ($object-ref 'scheme-object x (constant code-reloc-disp))]) - (and (not (eqv? reloc-table 0)) - ($object-ref 'uptr reloc-table - (fx+ (constant reloc-table-data-disp) - (fx* i (constant ptr-bytes)))))))) - (define-syntax tc-ptr-offsets - (lambda (x) - #`'#,(datum->syntax #'* - (fold-left - (lambda (ls fld) - (apply (lambda (name type disp len) - (if (eq? type 'ptr) - (if len - (do ([len len (fx- len 1)] - [disp disp (fx+ disp (constant ptr-bytes))] - [ls ls (cons disp ls)]) - ((fx= len 0) ls)) - (cons disp ls)) - ls)) - fld)) - '() - (or (getprop 'tc '*fields* #f) ($oops 'tc-ptr-offsets "missing fields for tc")))))) - (define align - (lambda (n) - (fxlogand (fx+ n (fx- (constant byte-alignment) 1)) (fx- (constant byte-alignment))))) - - (set-who! $compute-size - (rec $compute-size - (case-lambda - [(x maxgen) ($compute-size x maxgen (make-eq-hashtable))] - [(x maxgen size-ht) - (define cookie (cons 'date 'nut)) ; recreate on each call to $compute-size - (define compute-size - (lambda (x) - (if (or ($immediate? x) - (let ([g ($generation x)]) - (or (not g) (fx> g maxgen)))) - 0 - (let ([a (eq-hashtable-cell size-ht x #f)]) - (cond - [(cdr a) => - (lambda (p) - ; if we find our cookie, return 0 to avoid counting shared structure twice. - ; otherwise, (car p) must be a cookie from an earlier call to $compute-size, - ; so return the recorded size - (if (eq? (car p) cookie) - 0 - (begin - (set-car! p cookie) - (cdr p))))] - [else - (let ([p (cons cookie 0)]) - (set-cdr! a p) - (let ([size (really-compute-size x)]) - (set-cdr! p size) - size))]))))) - (define really-compute-size - (lambda (x) - (cond - [(pair? x) (fx+ (constant size-pair) (compute-size (car x)) (compute-size (cdr x)))] - [(symbol? x) - (fx+ (constant size-symbol) - (compute-size (#3%$top-level-value x)) - (compute-size (property-list x)) - (compute-size ($system-property-list x)) - (compute-size ($symbol-name x)))] - [(vector? x) - (let ([n (vector-length x)]) - (do ([i 0 (fx+ i 1)] - [size (align (fx+ (constant header-size-vector) (fx* (vector-length x) (constant ptr-bytes)))) - (fx+ size (compute-size (vector-ref x i)))]) - ((fx= i n) size)))] - [(fxvector? x) (align (fx+ (constant header-size-fxvector) (fx* (fxvector-length x) (constant ptr-bytes))))] - [(bytevector? x) (align (fx+ (constant header-size-bytevector) (bytevector-length x)))] - [($record? x) - (let ([rtd ($record-type-descriptor x)]) - (fold-left (lambda (size fld) - (if (eq? (fld-type fld) 'scheme-object) - (fx+ size (compute-size ($object-ref 'scheme-object x (fld-byte fld)))) - size)) - (fx+ (align (rtd-size rtd)) (compute-size rtd)) - (rtd-flds rtd)))] - [(string? x) (align (fx+ (constant header-size-string) (fx* (string-length x) (constant string-char-bytes))))] - [(box? x) (fx+ (constant size-box) (compute-size (unbox x)))] - [(flonum? x) (constant size-flonum)] - [(bignum? x) (align (fx+ (constant header-size-bignum) (fx* ($bignum-length x) (constant bigit-bytes))))] - [(ratnum? x) (fx+ (constant size-ratnum) (compute-size ($ratio-numerator x)) (compute-size ($ratio-denominator x)))] - [($exactnum? x) (fx+ (constant size-exactnum) (compute-size ($exactnum-real-part x)) (compute-size ($exactnum-imag-part x)))] - [($inexactnum? x) (constant size-inexactnum)] - [(procedure? x) - (if ($continuation? x) - (if (or (eq? x $null-continuation) (= ($continuation-stack-length x) (constant unscaled-shot-1-shot-flag))) - (constant size-continuation) - (begin - ; NB: rather not do this...splitting creates new continuation objects and gives an inaccurate - ; NB: picture of the size prior to splitting. will add overhead to eventual invocation of - ; NB: the continuation as well - ($split-continuation x 0) - ; not following RA slot at base of the frame, but this should always hold dounderflow, - ; which will be in the static generation and therefore ignored anyway after compact heap - (let ([len ($continuation-stack-length x)]) - (let loop ([i 1] - [lpm ($continuation-return-livemask x)] - [size (fx+ (constant size-continuation) - (align (fx* len (constant ptr-bytes))) - (compute-size ($continuation-return-code x)) - (compute-size ($closure-code x)) - (compute-size ($continuation-link x)) - (compute-size ($continuation-winders x)))]) - (if (fx>= i len) - size - (loop (fx+ i 1) (ash lpm -1) (if (odd? lpm) (fx+ size (compute-size ($continuation-stack-ref x i))) size))))))) - (let ([n ($closure-length x)]) - (do ([i 0 (fx+ i 1)] - [size (fx+ (align (fx+ (constant header-size-closure) (fx* n (constant ptr-bytes)))) (compute-size ($closure-code x))) - (fx+ size (compute-size ($closure-ref x i)))]) - ((fx= i n) size))))] - [($code? x) - (fx+ (align (fx+ (constant header-size-code) ($code-length x))) - (let ([n ($code-reloc-size x)]) - (let loop ([i 0] [size (align (fx+ (constant header-size-reloc-table) (fx* n (constant ptr-bytes))))] [addr 0]) - (if (fx= i n) - size - (let ([r ($get-reloc x i)]) - (and r - (let ([type (logand (bitwise-arithmetic-shift-right r (constant reloc-type-offset)) (constant reloc-type-mask))]) - (if (logtest r (constant reloc-extended-format)) - (let ([addr (fx+ addr ($get-reloc x (fx+ i 2)))]) - (loop (fx+ i 3) - (fx+ size - (compute-size - ($get-code-obj type x addr ($get-reloc x (fx+ i 1))))) - addr)) - (let ([addr (fx+ addr (logand (bitwise-arithmetic-shift-right r (constant reloc-code-offset-offset)) (constant reloc-code-offset-mask)))]) - (loop (fx+ i 1) - (fx+ size - (compute-size - ($get-code-obj type x addr - (logand (bitwise-arithmetic-shift-right r (constant reloc-item-offset-offset)) (constant reloc-item-offset-mask))))) - addr))))))))) - (compute-size ($code-name x)) - (compute-size ($code-info x)) - (compute-size ($code-pinfo* x)))] - [(port? x) - (fx+ (constant size-port) - (compute-size ($port-handler x)) - (if (input-port? x) (compute-size (port-input-buffer x)) 0) - (if (output-port? x) (compute-size (port-output-buffer x)) 0) - (compute-size ($port-info x)) - (compute-size (port-name x)))] - [(thread? x) - (let ([tc ($object-ref 'scheme-object x (constant thread-tc-disp))]) - (fold-left - (lambda (size disp) - (fx+ size (compute-size ($object-ref 'scheme-object tc disp)))) - (constant size-thread) - tc-ptr-offsets))] - [($tlc? x) - (fx+ (constant size-tlc) - (compute-size ($tlc-ht x)) - (compute-size ($tlc-keyval x)) - (compute-size ($tlc-next x)))] - [($rtd-counts? x) (constant size-rtd-counts)] - [else ($oops who "missing case for ~s" x)]))) - ; ensure size-ht isn't counted in the size of any object - (eq-hashtable-set! size-ht size-ht (cons cookie 0)) - (compute-size x)]))) - - (set-who! $compute-composition - (lambda (x maxgen) - (define cookie (cons 'oatmeal 'raisin)) - (define seen-ht (make-eq-hashtable)) - (define rtd-ht (make-eq-hashtable)) - (define-syntax define-counters - (lambda (x) - (syntax-case x () - [(_ (name-vec count-vec incr!) type ...) - (with-syntax ([(i ...) (enumerate #'(type ...))]) - #'(begin - (define name-vec (vector 'type ...)) - (define count-vec (make-vector (length #'(type ...)) #f)) - (define-syntax incr! - (syntax-rules (type ...) - [(_ type size) - (let ([p (vector-ref count-vec i)]) - (if p - (begin - (set-car! p (fx+ (car p) 1)) - (set-cdr! p (fx+ (cdr p) size))) - (vector-set! count-vec i (cons 1 size))))] - ...))))]))) - (define-counters (type-names type-counts incr!) - pair symbol vector fxvector bytevector string box flonum bignum ratnum exactnum - inexactnum continuation stack procedure code-object reloc-table port thread tlc - rtd-counts) - (define compute-composition! - (lambda (x) - (unless (or ($immediate? x) - (let ([g ($generation x)]) - (or (not g) (fx> g maxgen)))) - (let ([a (eq-hashtable-cell seen-ht x #f)]) - (unless (cdr a) - (set-cdr! a #t) - (really-compute-composition! x)))))) - (define really-compute-composition! - (lambda (x) - (cond - [(pair? x) - (incr! pair (constant size-pair)) - (compute-composition! (car x)) - (compute-composition! (cdr x))] - [(symbol? x) - (incr! symbol (constant size-symbol)) - (compute-composition! (#3%$top-level-value x)) - (compute-composition! (property-list x)) - (compute-composition! ($system-property-list x)) - (compute-composition! ($symbol-name x))] - [(vector? x) - (incr! vector (align (fx+ (constant header-size-vector) (fx* (vector-length x) (constant ptr-bytes))))) - (vector-for-each compute-composition! x)] - [(fxvector? x) (incr! fxvector (align (fx+ (constant header-size-fxvector) (fx* (fxvector-length x) (constant ptr-bytes)))))] - [(bytevector? x) (incr! bytevector (align (fx+ (constant header-size-bytevector) (bytevector-length x))))] - [($record? x) - (let ([rtd ($record-type-descriptor x)]) - (let ([p (eq-hashtable-ref rtd-ht rtd #f)] [size (align (rtd-size rtd))]) - (if p - (begin - (set-car! p (fx+ (car p) 1)) - (set-cdr! p (fx+ (cdr p) size))) - (eq-hashtable-set! rtd-ht rtd (cons 1 size)))) - (compute-composition! rtd) - (for-each (lambda (fld) - (when (eq? (fld-type fld) 'scheme-object) - (compute-composition! ($object-ref 'scheme-object x (fld-byte fld))))) - (rtd-flds rtd)))] - [(string? x) (incr! string (align (fx+ (constant header-size-string) (fx* (string-length x) (constant string-char-bytes)))))] - [(box? x) - (incr! box (constant size-box)) - (compute-composition! (unbox x))] - [(flonum? x) (incr! flonum (constant size-flonum))] - [(bignum? x) (incr! bignum (align (fx+ (constant header-size-bignum) (fx* ($bignum-length x) (constant bigit-bytes)))))] - [(ratnum? x) - (incr! ratnum (constant size-ratnum)) - (compute-composition! ($ratio-numerator x)) - (compute-composition! ($ratio-denominator x))] - [($exactnum? x) - (incr! exactnum (constant size-exactnum)) - (compute-composition! ($exactnum-real-part x)) - (compute-composition! ($exactnum-imag-part x))] - [($inexactnum? x) (incr! inexactnum (constant size-inexactnum))] - [(procedure? x) - (if ($continuation? x) - (begin - (incr! continuation (constant size-continuation)) - (unless (or (eq? x $null-continuation) (= ($continuation-stack-length x) (constant unscaled-shot-1-shot-flag))) - ; NB: rather not do this...splitting creates new continuation objects and gives an inaccurate - ; NB: picture of the continuation counts & sizes prior to splitting. will add overhead to eventual invocation of - ; NB: the continuation as well - ($split-continuation x 0) - (compute-composition! ($continuation-return-code x)) - (compute-composition! ($closure-code x)) - (compute-composition! ($continuation-link x)) - (compute-composition! ($continuation-winders x)) - (let ([len ($continuation-stack-length x)]) - (incr! stack (align (fx* len (constant ptr-bytes)))) - (let loop ([i 1] [lpm ($continuation-return-livemask x)]) - (unless (fx>= i len) - (when (odd? lpm) (compute-composition! ($continuation-stack-ref x i))) - (loop (fx+ i 1) (ash lpm -1))))))) - (begin - (compute-composition! ($closure-code x)) - (let ([n ($closure-length x)]) - (incr! procedure (align (fx+ (constant header-size-closure) (fx* n (constant ptr-bytes))))) - (do ([i 0 (fx+ i 1)]) - ((fx= i n)) - (compute-composition! ($closure-ref x i))))))] - [($code? x) - (incr! code-object (align (fx+ (constant header-size-code) ($code-length x)))) - (let ([n ($code-reloc-size x)]) - (incr! reloc-table (align (fx+ (constant header-size-reloc-table) (fx* n (constant ptr-bytes))))) - (let loop ([i 0] [addr 0]) - (unless (fx= i n) - (let ([r ($get-reloc x i)]) - (and r - (let ([type (logand (bitwise-arithmetic-shift-right r (constant reloc-type-offset)) (constant reloc-type-mask))]) - (if (logtest r (constant reloc-extended-format)) - (let ([addr (fx+ addr ($get-reloc x (fx+ i 2)))]) - (compute-composition! ($get-code-obj type x addr ($get-reloc x (fx+ i 1)))) - (loop (fx+ i 3) addr)) - (let ([addr (fx+ addr (logand (bitwise-arithmetic-shift-right r (constant reloc-code-offset-offset)) (constant reloc-code-offset-mask)))]) - (compute-composition! - ($get-code-obj type x addr - (logand (bitwise-arithmetic-shift-right r (constant reloc-item-offset-offset)) (constant reloc-item-offset-mask)))) - (loop (fx+ i 1) addr))))))))) - (compute-composition! ($code-name x)) - (compute-composition! ($code-info x)) - (compute-composition! ($code-pinfo* x))] - [(port? x) - (incr! port (constant size-port)) - (compute-composition! ($port-handler x)) - (if (input-port? x) (compute-composition! (port-input-buffer x)) 0) - (if (output-port? x) (compute-composition! (port-output-buffer x)) 0) - (compute-composition! ($port-info x)) - (compute-composition! (port-name x))] - [(thread? x) - (incr! thread (constant size-thread)) - (let ([tc ($object-ref 'scheme-object x (constant thread-tc-disp))]) - (for-each (lambda (disp) (compute-composition! ($object-ref 'scheme-object tc disp))) tc-ptr-offsets))] - [($tlc? x) - (incr! tlc (constant size-tlc)) - (compute-composition! ($tlc-ht x)) - (compute-composition! ($tlc-keyval x)) - (compute-composition! ($tlc-next x))] - [($rtd-counts? x) (incr! rtd-counts (constant size-rtd-counts))] - [else ($oops who "missing case for ~s" x)]))) - ; ensure hashtables aren't counted - (eq-hashtable-set! seen-ht seen-ht #t) - (eq-hashtable-set! seen-ht rtd-ht #t) - (compute-composition! x) - (append - (filter cdr (vector->list (vector-map cons type-names type-counts))) - (vector->list - (let-values ([(keys vals) (hashtable-entries rtd-ht)]) - (vector-map cons keys vals)))))) - - (set-who! $make-object-finder - ; pred object maxgen => object-finder procedure that returns - ; next object satisfying pred - ; or #f, if no object found - (lambda (pred x maxgen) - (let ([seen-ht (make-eq-hashtable)]) - (define saved-next-proc - (lambda () - (find! x '() (lambda () #f)))) - (define find! - (lambda (x path next-proc) - (let ([path (cons x path)]) - (cond - [(or ($immediate? x) (let ([g ($generation x)]) (or (not g) (fx> g maxgen)))) - (if (pred x) - (begin (set! saved-next-proc next-proc) path) - (next-proc))] - [else - (if (eq-hashtable-ref seen-ht x #f) - (next-proc) ; detected a loop, so backtrack and keep looking - (begin - (eq-hashtable-set! seen-ht x #t) ; mark this node as visited - (really-find! x path next-proc)))])))) - ; We're visiting this node for the first time - (define really-find! - (lambda (x path next-proc) - (define-syntax construct-proc - (syntax-rules () - [(_ ?next-proc) ?next-proc] - [(_ ?e ?e* ... ?next-proc) - (lambda () (find! ?e path (construct-proc ?e* ... ?next-proc)))])) - (let ([next-proc - (cond - [(pair? x) (construct-proc (car x) (cdr x) next-proc)] - [(symbol? x) - (construct-proc - (#3%$top-level-value x) - (property-list x) - ($system-property-list x) - ($symbol-name x) next-proc)] - [(vector? x) - (let ([n (vector-length x)]) - (let f ([i 0]) - (if (fx= i n) - next-proc - (construct-proc (vector-ref x i) (f (fx+ i 1))))))] - [($record? x) - (let ([rtd ($record-type-descriptor x)]) - (construct-proc rtd - (let f ([flds (rtd-flds rtd)]) - (if (null? flds) - next-proc - (let ([fld (car flds)]) - (if (eq? (fld-type fld) 'scheme-object) - (construct-proc ($object-ref 'scheme-object x (fld-byte fld)) (f (cdr flds))) - (f (cdr flds))))))))] - [(or (fxvector? x) (bytevector? x) (string? x) (flonum? x) (bignum? x) - ($inexactnum? x) ($rtd-counts? x)) - next-proc] - [(box? x) (construct-proc (unbox x) next-proc)] - [(ratnum? x) (construct-proc ($ratio-numerator x) ($ratio-denominator x) next-proc)] - [($exactnum? x) (construct-proc ($exactnum-real-part x) ($exactnum-imag-part x) next-proc)] - [(procedure? x) - (if ($continuation? x) - (if (or (eq? x $null-continuation) (= ($continuation-stack-length x) (constant unscaled-shot-1-shot-flag))) - next-proc - (begin - ; NB: rather not do this...splitting creates new continuation objects and gives an inaccurate - ; NB: picture of the size prior to splitting. will add overhead to eventual invocation of - ; NB: the continuation as well - ($split-continuation x 0) - ; not following RA slot at base of the frame, but this should always hold dounderflow, - ; which will be in the static generation and therefore ignored anyway after compact heap - (let ([len ($continuation-stack-length x)]) - (let loop ([i 1] [lpm ($continuation-return-livemask x)]) - (if (fx>= i len) - (construct-proc ($continuation-return-code x) ($closure-code x) ($continuation-link x) ($continuation-winders x) next-proc) - (if (odd? lpm) - (construct-proc ($continuation-stack-ref x i) (loop (fx+ i 1) (ash lpm -1))) - (loop (fx+ i 1) (ash lpm -1)))))))) - (construct-proc ($closure-code x) - (let ([n ($closure-length x)]) - (let f ([i 0]) - (if (fx= i n) - next-proc - (construct-proc ($closure-ref x i) (f (fx+ i 1))))))))] - [($code? x) - (construct-proc ($code-name x) ($code-info x) ($code-pinfo* x) - (let ([n ($code-reloc-size x)]) - (let loop ([i 0] [addr 0]) - (if (fx= i n) - next-proc - (let ([r ($get-reloc x i)]) - (if (not r) - next-proc - (let ([type (logand (bitwise-arithmetic-shift-right r (constant reloc-type-offset)) (constant reloc-type-mask))]) - (if (logtest r (constant reloc-extended-format)) - (let ([addr (fx+ addr ($get-reloc x (fx+ i 2)))]) - (construct-proc ($get-code-obj type x addr ($get-reloc x (fx+ i 1))) - (loop (fx+ i 3) addr))) - (let ([addr (fx+ addr (logand (bitwise-arithmetic-shift-right r (constant reloc-code-offset-offset)) (constant reloc-code-offset-mask)))]) - (construct-proc - ($get-code-obj type x addr - (logand (bitwise-arithmetic-shift-right r (constant reloc-item-offset-offset)) (constant reloc-item-offset-mask))) - (loop (fx+ i 1) addr)))))))))))] - [(port? x) - (construct-proc ($port-handler x) ($port-info x) (port-name x) - (let ([th (lambda () (if (output-port? x) (construct-proc (port-output-buffer x) next-proc) next-proc))]) - (if (input-port? x) (construct-proc (port-input-buffer x) (th)) (th))))] - [(thread? x) - (let ([tc ($object-ref 'scheme-object x (constant thread-tc-disp))]) - (let f ([disp-list tc-ptr-offsets]) - (if (null? disp-list) - next-proc - (construct-proc ($object-ref 'scheme-object tc (car disp-list)) (f (cdr tc-ptr-offsets))))))] - [($tlc? x) (construct-proc ($tlc-ht x) ($tlc-keyval x) ($tlc-next x) next-proc)] - [else ($oops who "missing case for ~s" x)])]) - ; check if this node is what we're looking for - (if (pred x) - (begin (set! saved-next-proc next-proc) path) - (next-proc))))) - (rec find-next (lambda () (saved-next-proc))))))) - -(let () - (define filter-generation - (lambda (who g) - (unless (or (and (fixnum? g) (fx<= 0 g (collect-maximum-generation))) (eq? g 'static)) - ($oops who "invalid generation ~s" g)) - (if (eq? g 'static) (constant static-generation) g))) - - (set-who! make-object-finder - (case-lambda - [(pred) - (unless (procedure? pred) ($oops who "~s is not a procedure" pred)) - ($make-object-finder pred (oblist) (collect-maximum-generation))] - [(pred x) - (unless (procedure? pred) ($oops who "~s is not a procedure" pred)) - ($make-object-finder pred x (collect-maximum-generation))] - [(pred x g) - (unless (procedure? pred) ($oops who "~s is not a procedure" pred)) - ($make-object-finder pred x (filter-generation who g))])) - - (set-who! compute-size - (case-lambda - [(x) ($compute-size x (collect-maximum-generation))] - [(x g) ($compute-size x (filter-generation who g))])) - - (set-who! compute-composition - (case-lambda - [(x) ($compute-composition x (collect-maximum-generation))] - [(x g) ($compute-composition x (filter-generation who g))]))) - -(define object-counts (foreign-procedure "(cs)object_counts" () ptr)) -) diff --git a/ta6ob/s/inspect.ta6ob b/ta6ob/s/inspect.ta6ob deleted file mode 100644 index f251398..0000000 Binary files a/ta6ob/s/inspect.ta6ob and /dev/null differ diff --git a/ta6ob/s/interpret.ss b/ta6ob/s/interpret.ss deleted file mode 100644 index dff7977..0000000 --- a/ta6ob/s/interpret.ss +++ /dev/null @@ -1,713 +0,0 @@ -;;; interpret.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; TODO -;;; - recognize direct close calls in ip2 to avoid creation of closure -;;; (but not closure pointer) and overhead of call -;;; - handle let & letrec better -;;; - use arg regs when available -;;; - wire up letrec closures, then treat like let (good luck) -;;; - optimize direct calls when no free vars -;;; - since closure is just code in this case, can wire it in directly - -(let () -(import (nanopass)) -(include "base-lang.ss") -(include "expand-lang.ss") - -(define-record-type c-var - (fields (immutable id) (immutable parent) (mutable index) (mutable loc)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (id parent) - (new id parent #f #f))))) - -(define list-of-c-var? - (lambda (x) - (and (list? x) (andmap c-var? x)))) - -(define-language Linterp - (extends Lsrc) - (terminals - (- ($prelex (x))) - (+ (c-var (x)) - (list-of-c-var (free)))) - (Expr (e body rtd-expr) - (- (case-lambda preinfo cl ...) - (call preinfo e0 e1 ...) - (moi) - (pariah) - (ref maybe-src x) - (set! maybe-src x e) - (profile src)) - (+ x - (close free cl ...) - (call e e* ...) - (set! x e)))) - -(define ip1 -(let () -(define-record-type c-env - (fields (immutable prev) (mutable vars)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (prev) - (new prev '()))))) - -(define-pass ip1 : Lsrc (ir) -> Linterp () - (definitions - (define ip1-lambda - (lambda (clauses env) - (let ([env (make-c-env env)]) - (let ([bodies - (map (lambda (clause) - (nanopass-case (Lsrc CaseLambdaClause) clause - [(clause (,x* ...) ,interface ,body) - (with-vars (vars x* env) - (with-output-language (Linterp CaseLambdaClause) - (let ([body (Expr body env)]) - `(clause (,vars ...) ,interface ,body))))] - [else (errorf 'ip1-lambda "found something unexpected ~s\n" clause)])) - clauses)]) - (with-output-language (Linterp Expr) - `(close ,(ip1-free env) ,bodies ...)))))) - (define ip1-letrec - (lambda (ids vals body env) - (with-output-language (Lsrc Expr) - (define build-let - (lambda (ids vals body) - (if (null? ids) - body - `(call ,(make-preinfo) - (case-lambda ,(make-preinfo-lambda) - (clause (,ids ...) ,(length ids) ,body)) - ,vals ...)))) - (Expr (if (null? ids) - body - (build-let ids (map (lambda (x) `(quote ,(void))) ids) - (fold-left (lambda (body id val) - (set-prelex-assigned! id #t) - `(seq (set! #f ,id ,val) ,body)) - body ids vals))) - env))))) - (Expr : Expr (ir [env #f]) -> Expr () - [(ref ,maybe-src ,x) (ip1-lookup-lexical x env)] - [(case-lambda ,preinfo ,cl* ...) (ip1-lambda cl* env)] - [(call ,preinfo ,[e] ,[e*] ...) `(call ,e ,e* ...)] - [(set! ,maybe-src ,x ,[e]) `(set! ,(ip1-lookup-lexical x env) ,e)] - [(letrec ([,x* ,e*] ...) ,body) (ip1-letrec x* e* body env)] - [(seq ,[e1] ,[e2]) - (nanopass-case (Linterp Expr) e1 - [(quote ,d) e2] - [else `(seq ,e1 ,e2)])] - [(moi) `(quote #f)] - [(pariah) `(quote ,(void))] - [(profile ,src) `(quote ,(void))])) - -;;; When we create a lex from a prelex, we replace the name field of -;;; the prelex id with an initial mapping from environment to the lex -;;; var corresponding to the prelex in the environment. This mapping is -;;; augmented by lookup-lexical (for references through rebind-free -;;; environments) and trimmed by maybe-free. - -(define-syntax with-var - (syntax-rules () - ((_ (var idexp env) e1 e2 ...) - (let ((id idexp)) - (let ((name (prelex-name id))) - (let ((var (make-c-var id #f))) - (prelex-name-set! id (list (cons env var))) - (let ((tmp (begin e1 e2 ...))) - ; restore name to leave prelex undamaged; this is necessary at - ; present because syntax objects may contain the same prelexes - ; that arrive here as bound variables - (prelex-name-set! id name) - tmp))))))) - -(define-syntax with-vars - (syntax-rules () - ((_ (vars idsexp env) e1 e2 ...) - (let f ((ids (reverse idsexp)) (vars '())) - (if (null? ids) - (begin e1 e2 ...) - (with-var (var (car ids) env) - (f (cdr ids) (cons var vars)))))))) - -(define ip1-free - (lambda (e) - (map (lambda (id) - (let ((ls (prelex-name id))) - (prelex-name-set! id (cdr ls)) - (cdar ls))) - (c-env-vars e)))) - -(define ip1-lookup-lexical - (lambda (id e) - (let ((ls (prelex-name id))) - (if (eq? (caar ls) e) - (cdar ls) - (let ((y (ip1-lookup-lexical id (c-env-prev e)))) - (let ([z (make-c-var id y)]) - (c-env-vars-set! e (cons id (c-env-vars e))) - (prelex-name-set! id (cons (cons e z) (prelex-name id))) - z)))))) - -(lambda (x) (ip1 x)))) - -(define-syntactic-monad $rt a0 a1 fp cp) - -(module (ip2) -(define unexpected-loc - (lambda (loc) - ($oops 'interpret-internal "unexpected loc ~s" loc))) - -(define ip2 - (lambda (x) - (define unexpected-record - (lambda (x) - ($oops 'interpret-internal "unexpected record ~s" x))) - (define non-procedure - (lambda (x) - ($oops #f "attempt to apply non-procedure ~s" x))) - (define unbound-or-non-procedure - (lambda (sym x) - (if ($unbound-object? x) - ($oops #f "variable ~:s is not bound" sym) - (non-procedure x)))) - (define-syntax docall-sym - (lambda (x) - (syntax-case x () - [(_ sym e1 ...) - (with-syntax ([(t0 t1 ...) (generate-temporaries #'(e0 e1 ...))]) - #'($rt lambda () - (let ([t0 (#3%$top-level-value sym)] [t1 ($rt e1)] ...) - (unless (procedure? t0) (unbound-or-non-procedure sym t0)) - (t0 t1 ...))))]))) - (define-syntax docall - (lambda (x) - (syntax-case x () - [(_ e0 e1 ...) - (with-syntax ([(t0 t1 ...) (generate-temporaries #'(e0 e1 ...))]) - #'($rt lambda () - (let ([t0 e0] [t1 ($rt e1)] ...) - (unless (procedure? t0) (non-procedure t0)) - (t0 t1 ...))))]))) - (define-syntax docallx - (lambda (x) - (syntax-case x () - [(_ e0 e1 ...) - (with-syntax ([(t0 t1 ...) (generate-temporaries #'(e0 e1 ...))]) - #'($rt lambda () - (let ([t0 ($rt e0)] [t1 ($rt e1)] ...) - (unless (procedure? t0) (non-procedure t0)) - (t0 t1 ...))))]))) - (define ip2-fat-call - (lambda (fun args) - (let ((args (reverse args))) - ($rt lambda () - (let ((fun ($rt fun))) - (let loop ([args args] [vals '()]) - (if (null? args) - (begin - (unless (procedure? fun) (non-procedure fun)) - (apply fun vals)) - (loop (cdr args) (cons ($rt (car args)) vals))))))))) - (nanopass-case (Linterp Expr) x - [,x - (let ((loc (c-var-loc x)) (i (c-var-index x))) - (if (prelex-assigned (c-var-id x)) - (case loc - [(a0) ($rt lambda () (car a0))] - [(a1) ($rt lambda () (car a1))] - [(fp) ($rt lambda () (car fp))] - [(cp) ($rt lambda () (car cp))] - [(frame) ($rt lambda () (car (list-ref fp i)))] - [(frame-rest) ($rt lambda () (car (list-tail fp i)))] - [(closure) ($rt lambda () (car (vector-ref cp i)))] - [else (unexpected-loc loc)]) - (case loc - [(a0) ($rt lambda () a0)] - [(a1) ($rt lambda () a1)] - [(fp) ($rt lambda () fp)] - [(cp) ($rt lambda () cp)] - [(frame) ($rt lambda () (list-ref fp i))] - [(frame-rest) ($rt lambda () (list-tail fp i))] - [(closure) ($rt lambda () (vector-ref cp i))] - [else (unexpected-loc loc)])))] - [,pr (let ((fun ($top-level-value (primref-name pr)))) - ($rt lambda () fun))] - [(quote ,d) ($rt lambda () d)] - [(close ,free ,cl* ...) - (unless (null? free) - (if (null? (cdr free)) - (c-var-loc-set! (car free) 'cp) - (let loop ((free free) (i 0)) - (unless (null? free) - (c-var-loc-set! (car free) 'closure) - (c-var-index-set! (car free) i) - (loop (cdr free) (fx+ i 1)))))) - (or (and (not (null? cl*)) - (null? (cdr cl*)) - (nanopass-case (Linterp CaseLambdaClause) (car cl*) - [(clause (,x* ...) ,interface ,body) - (if (null? free) - (case interface - [(0) - (let ((body (ip2-body body x* '(a0 a1 fp cp) #f))) - ($rt lambda () - (lambda () - ($rt body ([a0 0] [a1 0] [fp 0] [cp 0])))))] - [(1) - (let ((body (ip2-body body x* '(a0 a1 fp cp) #f))) - ($rt lambda () - (lambda (a0) - ($rt body ([a1 0] [fp 0] [cp 0])))))] - [(2) - (let ((body (ip2-body body x* '(a0 a1 fp cp) #f))) - ($rt lambda () - (lambda (a0 a1) - ($rt body ([fp 0] [cp 0])))))] - [(3) - (let ((body (ip2-body body x* '(a0 a1 fp cp) #f))) - ($rt lambda () - (lambda (a0 a1 fp) - ($rt body ([cp 0])))))] - [(4) - (let ((body (ip2-body body x* '(a0 a1 fp cp) #f))) - ($rt lambda () - (lambda (a0 a1 fp cp) - ($rt body))))] - [else #f]) - (case interface - [(0) - (ip2-closure free - (let ((body (ip2-body body x* '(a0 a1 fp) #f))) - ($rt lambda () - (lambda () - ($rt body ([a0 0] [a1 0] [fp 0]))))))] - [(1) - (ip2-closure free - (let ((body (ip2-body body x* '(a0 a1 fp) #f))) - ($rt lambda () - (lambda (a0) - ($rt body ([a1 0] [fp 0]))))))] - [(2) - (ip2-closure free - (let ((body (ip2-body body x* '(a0 a1 fp) #f))) - ($rt lambda () - (lambda (a0 a1) - ($rt body ([fp 0]))))))] - [(3) - (ip2-closure free - (let ((body (ip2-body body x* '(a0 a1 fp) #f))) - ($rt lambda () - (lambda (a0 a1 fp) - ($rt body)))))] - [else #f]))])) - ; we could use cp if no closure; we could use fp if max interface - ; is small enough. we don't bother with either presently. - (let ((m (let min? ((cl* cl*) (m (length '(a0 a1)))) - (if (null? cl*) - m - (nanopass-case (Linterp CaseLambdaClause) (car cl*) - [(clause (,x* ...) ,interface ,body) - (min? (cdr cl*) - (min (if (fx< interface 0) - (fx- -1 interface) - interface) - m))]))))) - (define adjust-interface - (lambda (x) - (if (fx< x 0) - (fx+ x m) - (fx- x m)))) - (let ((body (let f ((cl* cl*)) - (if (null? cl*) - ($rt lambda (args nargs) - ($oops #f "incorrect number of arguments to #")) - (nanopass-case (Linterp CaseLambdaClause) (car cl*) - [(clause (,x* ...) ,interface ,body) - (ip2-prelude - (ip2-body body x* '(a0 a1) - (fx< interface 0)) - (list-tail x* m) - (list-tail '(a0 a1) m) - (adjust-interface interface) - (f (cdr cl*)))]))))) - (case m - [(0) - (ip2-closure free - ($rt lambda () - (lambda args - ($rt body ([a0 0] [a1 0] [fp 0]) args (length args)))))] - [(1) - (ip2-closure free - ($rt lambda () - (lambda (a0 . args) - ($rt body ([a1 0] [fp 0]) args (length args)))))] - [(2) - (ip2-closure free - ($rt lambda () - (lambda (a0 a1 . args) - ($rt body ([fp 0]) args (length args)))))]))))] - [(set! ,x ,e) - (let ((e (ip2 e))) - (let ((loc (c-var-loc x)) (i (c-var-index x))) - (case loc - [(a0) ($rt lambda () (set-car! a0 ($rt e)))] - [(a1) ($rt lambda () (set-car! a1 ($rt e)))] - [(fp) ($rt lambda () (set-car! fp ($rt e)))] - [(cp) ($rt lambda () (set-car! cp ($rt e)))] - [(frame) ($rt lambda () (set-car! (list-ref fp i) ($rt e)))] - [(frame-rest) - ($rt lambda () (set-car! (list-tail fp i) ($rt e)))] - [(closure) ($rt lambda () (set-car! (vector-ref cp i) ($rt e)))] - [else (unexpected-loc loc)])))] - [(if ,e0 ,e1 ,e2) - (let ((e0 (ip2 e0)) (e1 (ip2 e1)) (e2 (ip2 e2))) - ($rt lambda () - ($rt (if ($rt e0) e1 e2))))] - [(call ,e ,e* ...) - (let ((e* (map (lambda (x) (ip2 x)) e*))) - (or (nanopass-case (Linterp Expr) e - [,pr - (case (length e*) - [(0) - (let ((e ($top-level-value (primref-name pr)))) - ($rt lambda () (e)))] - [(1) - (apply - (lambda (x1) - (let ((e ($top-level-value (primref-name pr)))) - ($rt lambda () (e ($rt x1))))) - e*)] - [(2) - (apply - (lambda (x1 x2) - (let ((e ($top-level-value (primref-name pr)))) - ($rt lambda () (e ($rt x1) ($rt x2))))) - e*)] - [(3) - (apply - (lambda (x1 x2 x3) - (let ((e ($top-level-value (primref-name pr)))) - ($rt lambda () - (e ($rt x1) ($rt x2) ($rt x3))))) - e*)] - [else #f])] - [(call ,e1 ,e1* ...) - (nanopass-case (Linterp Expr) e1 - [,pr (and (eq? (primref-name pr) '$top-level-value) - (fx= (length e*) 1) - (nanopass-case (Linterp Expr) (car e1*) - [(quote ,d) - (and (symbol? d) - (case (length e*) - [(0) (docall-sym d)] - [(1) - (apply - (lambda (x1) - (docall-sym d x1)) - e*)] - [(2) - (apply - (lambda (x1 x2) - (docall-sym d x1 x2)) - e*)] - [(3) - (apply - (lambda (x1 x2 x3) - (docall-sym d x1 x2 x3)) - e*)] - [else #f]))] - [else #f]))] - [else #f])] - [else #f]) - (let ((e (ip2 e))) - (case (length e*) - [(0) (docallx e)] - [(1) - (apply - (lambda (x1) (docallx e x1)) - e*)] - [(2) - (apply - (lambda (x1 x2) (docallx e x1 x2)) - e*)] - [(3) - (apply - (lambda (x1 x2 x3) (docallx e x1 x2 x3)) - e*)] - [else (ip2-fat-call e e*)]))))] - [(seq ,e1 ,e2) - (let ((e1 (ip2 e1)) (e2 (ip2 e2))) - ($rt lambda () ($rt e1) ($rt e2)))] - [(foreign (,conv* ...) ,name ,e (,arg-type* ...) ,result-type) - (unless $compiler-is-loaded? - ($oops 'interpret "cannot compile foreign-procedure: compiler is not loaded")) - (let ([p ($compile-backend - (let ((t (make-prelex* 'tmp))) - (set-prelex-referenced! t #t) - (with-output-language (Lsrc Expr) - `(case-lambda ,(make-preinfo-lambda) - (clause (,t) 1 - (foreign (,conv* ...) ,name (ref #f ,t) - (,arg-type* ...) ,result-type))))))]) - (let ([e (ip2 e)]) - ($rt lambda () ((p) ($rt e)))))] - [(fcallable (,conv* ...) ,e (,arg-type* ...) ,result-type) - (unless $compiler-is-loaded? - ($oops 'interpret "cannot compile foreign-callable: compiler is not loaded")) - (let ([p ($compile-backend - (let ((t (make-prelex* 'tmp))) - (set-prelex-referenced! t #t) - (with-output-language (Lsrc Expr) - `(case-lambda ,(make-preinfo-lambda) - (clause (,t) 1 - (fcallable (,conv* ...) (ref #f ,t) (,arg-type* ...) ,result-type))))))]) - (let ([e (ip2 e)]) - ($rt lambda () ((p) ($rt e)))))] - [else (unexpected-record x)]))) - -(define ip2-prelude - (lambda (body vars regs i next) - (define set-args - (lambda (vars regs body rest?) - (if (null? regs) - ($rt lambda (args) ($rt body ([fp args]))) - (let ((reg (car regs))) - (if (null? (cdr vars)) - (if rest? - (case reg - [(a0) ($rt lambda (args) ($rt body ([a0 args])))] - [(a1) ($rt lambda (args) ($rt body ([a1 args])))] - [(fp) ($rt lambda (args) ($rt body ([fp args])))] - [(cp) ($rt lambda (args) ($rt body ([cp args])))] - [else (unexpected-loc reg)]) - (case reg - [(a0) ($rt lambda (args) ($rt body ([a0 (car args)])))] - [(a1) ($rt lambda (args) ($rt body ([a1 (car args)])))] - [(fp) ($rt lambda (args) ($rt body ([fp (car args)])))] - [(cp) ($rt lambda (args) ($rt body ([cp (car args)])))] - [else (unexpected-loc reg)])) - (let ((body (set-args (cdr vars) (cdr regs) body rest?))) - (case reg - [(a0) ($rt lambda (args) - ($rt body ([a0 (car args)]) (cdr args)))] - [(a1) ($rt lambda (args) - ($rt body ([a1 (car args)]) (cdr args)))] - [(fp) ($rt lambda (args) - ($rt body ([fp (car args)]) (cdr args)))] - [(cp) ($rt lambda (args) - ($rt body ([cp (car args)]) (cdr args)))] - [else (unexpected-loc reg)]))))))) - (if (fx>= i 0) - (if (fx= i 0) - ($rt lambda (args nargs) - (if (fx= nargs 0) - ($rt body) - ($rt next () args nargs))) - (let ((body (set-args vars regs body #f))) - ($rt lambda (args nargs) - (if (fx= nargs i) - ($rt body () args) - ($rt next () args nargs))))) - (let ((body (set-args vars regs body #t))) - (if (fx= i -1) - ($rt lambda (args nargs) ($rt body () args)) - (let ((i (fx- -1 i))) - ($rt lambda (args nargs) - (if (fx>= nargs i) - ($rt body () args) - ($rt next () args nargs))))))))) - -(define ip2-closure - (lambda (free code) - (let ([free (map (lambda (var) - (let* ((var (c-var-parent var)) - (loc (c-var-loc var)) - (i (c-var-index var))) - (case loc - [(a0) ($rt lambda () a0)] - [(a1) ($rt lambda () a1)] - [(fp) ($rt lambda () fp)] - [(cp) ($rt lambda () cp)] - [(frame) ($rt lambda () (list-ref fp i))] - [(frame-rest) ($rt lambda () (list-tail fp i))] - [(closure) ($rt lambda () (vector-ref cp i))] - [else (unexpected-loc loc)]))) - free)]) - (let ((nfree (length free))) - (case nfree - [(0) ($rt lambda () ($rt code ([cp 0])))] - [(1) - (apply - (lambda (x1) - ($rt lambda () ($rt code ([cp ($rt x1)])))) - free)] - [(2) - (apply - (lambda (x1 x2) - ($rt lambda () - ($rt code ([cp (vector ($rt x1) ($rt x2))])))) - free)] - [(3) - (apply - (lambda (x1 x2 x3) - ($rt lambda () - ($rt code ([cp (vector ($rt x1) ($rt x2) ($rt x3))])))) - free)] - [(4) - (apply - (lambda (x1 x2 x3 x4) - ($rt lambda () - ($rt code ([cp (vector ($rt x1) ($rt x2) ($rt x3) ($rt x4))])))) - free)] - [else - ($rt lambda () - (let ((v (make-vector nfree ($rt (car free))))) - (do ((i 1 (fx+ i 1)) (free (cdr free) (cdr free))) - ((null? free)) - (vector-set! v i ($rt (car free)))) - ($rt code ([cp v]))))]))))) - -(define ip2-body - (lambda (body invars regs rest?) - ; set locations - (let loop ((vars invars) (regs regs) (i 0)) - (cond - [(null? vars) - ; process the body and wrap in consers for assigned variables - (do ((vars invars (cdr vars)) - (body (ip2 body) - (let ((var (car vars))) - (if (prelex-assigned (c-var-id var)) - (case (c-var-loc var) - [(a0) - ($rt lambda () - ($rt body ([a0 (cons a0 (void))])))] - [(a1) - ($rt lambda () - ($rt body ([a1 (cons a1 (void))])))] - [(fp) - ($rt lambda () - ($rt body ([fp (cons fp (void))])))] - [(cp) - ($rt lambda () - ($rt body ([cp (cons cp (void))])))] - [(frame) - (let ((i (c-var-index var))) - ($rt lambda () - (let ((ls (list-tail fp i))) - (set-car! ls (cons (car ls) (void)))) - ($rt body)))] - [(frame-rest) - (let ((i (fx- (c-var-index var) 1))) - ($rt lambda () - (let ((ls (list-tail fp i))) - (set-cdr! ls (cons (cdr ls) (void)))) - ($rt body)))]) - body)))) - ((null? vars) body))] - [(not (null? regs)) - (c-var-loc-set! (car vars) (car regs)) - (loop (cdr vars) (cdr regs) i)] - [(and rest? (null? (cdr vars))) - (cond - [(fx= i 0) - ; using fp here instead of the equivalent frame-rest[0] - ; eliminates need for special-casing frame-rest[0] elsewhere. - (c-var-loc-set! (car vars) 'fp) - (loop (cdr vars) regs i)] - [else - (c-var-loc-set! (car vars) 'frame-rest) - (c-var-index-set! (car vars) i) - (loop (cdr vars) regs (fx+ i 1))])] - [else - (c-var-loc-set! (car vars) 'frame) - (c-var-index-set! (car vars) i) - (loop (cdr vars) regs (fx+ i 1))]))))) - -(define-pass interpret-Lexpand : Lexpand (ir situation for-import? importer ofn eoo) -> * (val) - (definitions - (define (ibeval x1) - ($rt (parameterize ([$target-machine (machine-type)] [$sfd #f]) - (let* ([x2 ($pass-time 'cpvalid (lambda () ($cpvalid x1)))] - [x2a (let ([cpletrec-ran? #f]) - (let ([x ((run-cp0) - (lambda (x) - (set! cpletrec-ran? #t) - (let ([x ($pass-time 'cp0 (lambda () ($cp0 x #f)))]) - ($pass-time 'cpletrec - (lambda () ($cpletrec x))))) - x2)]) - (if cpletrec-ran? x ($pass-time 'cpletrec (lambda () ($cpletrec x))))))] - [x2b ($pass-time 'cpcheck (lambda () ($cpcheck x2a)))] - [x2b ($pass-time 'cpcommonize (lambda () ($cpcommonize x2b)))]) - (when eoo (pretty-print ($uncprep x2b) eoo)) - (let ([x ($pass-time 'ip1 (lambda () (ip1 x2b)))]) - ($pass-time 'ip2 (lambda () (ip2 x)))))) - ([a0 0] [a1 0] [fp 0] [cp 0])))) - (Inner : Inner (ir) -> * (val) - [,lsrc (ibeval lsrc)] - [(program ,uid ,body) - (ibeval ($build-invoke-program uid body))] - [(library/ct ,uid (,export-id* ...) ,import-code ,visit-code) - (ibeval ($build-install-library/ct-code uid export-id* import-code visit-code))] - [(library/rt ,uid (,dl* ...) (,db* ...) (,dv* ...) (,de* ...) ,body) - (ibeval ($build-install-library/rt-code uid dl* db* dv* de* body))] - [(library/rt-info ,linfo/rt) ($install-library/rt-desc linfo/rt for-import? importer ofn)] - [(library/ct-info ,linfo/ct) ($install-library/ct-desc linfo/ct for-import? importer ofn)] - [(program-info ,pinfo) ($install-program-desc pinfo)] - [else (sorry! who "unexpected language form ~s" ir)]) - (Outer : Outer (ir) -> * (val) - ; can't use cata since (Outer outer1) might return 0 or more than one value - [(group ,outer1 ,outer2) (Outer outer1) (Outer outer2)] - [(visit-only ,inner) (unless (eq? situation 'revisit) (Inner inner))] - [(revisit-only ,inner) (unless (eq? situation 'visit) (Inner inner))] - [(recompile-info ,rcinfo) (void)] - [,inner (Inner inner)] - [else (sorry! who "unexpected language form ~s" ir)]) - (Outer ir)) - -(set! interpret - (rec interpret - (case-lambda - [(x) - (interpret x - (if (eq? (subset-mode) 'system) - ($system-environment) - (interaction-environment)))] - [(x0 env-spec) - (unless (environment? env-spec) ($oops 'interpret "~s is not an environment" env-spec)) - (let ([x1 ($pass-time 'expand - (lambda () - (parameterize ([$target-machine (machine-type)] [$sfd #f]) - (expand x0 env-spec #t))))]) - ($uncprep x1 #t) ; populate preinfo sexpr fields - (when (and (expand-output) (not ($noexpand? x0))) - (pretty-print ($uncprep x1) (expand-output))) - (interpret-Lexpand x1 'load #f #f #f (and (not ($noexpand? x0)) (expand/optimize-output))))]))) - -(set! $interpret-backend - (lambda (x situation for-import? importer ofn) - (interpret-Lexpand x situation for-import? importer ofn (expand/optimize-output)))) -(current-eval interpret) -) - diff --git a/ta6ob/s/interpret.ta6ob b/ta6ob/s/interpret.ta6ob deleted file mode 100644 index 7f5da01..0000000 Binary files a/ta6ob/s/interpret.ta6ob and /dev/null differ diff --git a/ta6ob/s/io-types.ss b/ta6ob/s/io-types.ss deleted file mode 100644 index b384cdf..0000000 --- a/ta6ob/s/io-types.ss +++ /dev/null @@ -1,185 +0,0 @@ -;;; io-types.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -#| -In order to be thread safe, size must be zero and the handler procedures -must obtain the tc-mutex or use some other mechanism to guarantee mutual -exclusion while manipulating the buffer. - -The built-in handlers for binary file output ports are thread-safe iff -the buffer mode is none. The handlers for input ports are not thread-safe, -since the buffer size may be non-zero to handle lookahead and ungetting. - -In order to be safe for continuation-based multitasking, the buffer must -be manipulated only by inline code (which runs between interrupt traps) or -within a critical section. The built-in file handlers are task-safe, but -the handlers for custom ports and for bytevector ports are not. - -In general caller will check immutable properties of inputs but the -handler must check mutable properties of inputs because other threads may -change those properties. For example, handlers need not check the types -of most input values (e.g., ports, octets, bytevectors) but do have to -check for closed ports. (Position and length arguments are an exception, -since they may vary by kind of port.) Furthermore, handlers, including put -and get, should not expect the buffer to be full or empty when they are -called, since in general this cannot be guaranteed if multiple tasks or -threads are running. On the other hand, handlers generally won't be -called for every operation on a port, since data is usually inserted into -or taken from the buffer when appropriate. - -To indicate an input buffer containing an #!eof object, handlers should -set the input size empty and set the port-eof-flag. - -Handler fields for unsupported operations should be set to #f. The others -must be procedures. All port handlers must supply a procedure for -close-port. Input port handlers must supply procedures for ready?, -lookahead, unget, get, and get-some. Output port handlers must supply -procedures for put, put-some, and flush. - -For port-position, set-port-position!, port-nonblocking?, -set-port-nonblocking!, port-length, and set-port-length!, the -corresponding "port-has" predicate will return true iff a procedure is -supplied. These procedures must take into account input and output -buffers as appropriate. Positions must be byte counts for binary ports -(see R6RS). For output ports handler must flush the port on "set" (see -R6RS), and for input port handler must clear the buffer on "set" if -needed. - -The get-some and put-some procedures should not block on nonblocking -ports, but should instead return 0 to indicate that no data was written or -read. Exception: if a textual output port is line-buffered and the -string passed to put-some contains an eol character, put-some must -flush at least to the last eol character. - -The close-port procedure must flush the output buffer as appropriate, set -the buffer size(s) to zero, clear the port-eof flag, and mark the port -closed. -|# - -(define-syntax define-port-handler - (lambda (x) - (syntax-case x (->) - [(_ (?record-name ?constructor-name ?pred-name) uid - (?field ?param ... -> ?result) ...) - (or (not (datum uid)) (identifier? #'uid)) - #`(begin - (define-record-type (?record-name mph ?pred-name) - #,(if (datum uid) #'(nongenerative uid) #'(nongenerative)) - (opaque #t) - (sealed #t) - (fields (immutable ?field) ...)) - (define-syntax ?constructor-name - (lambda (x) - (syntax-case x () - [(_ [?name ?expr] (... ...)) - (begin - (let loop ([field* '(?field ...)] [name* #'(?name (... ...))]) - (if (null? field*) - (unless (null? name*) - (syntax-error (car name*) "unexpected")) - (if (null? name*) - (syntax-error x (format "missing ~s" (car field*))) - (if (eq? (syntax->datum (car name*)) (car field*)) - (loop (cdr field*) (cdr name*)) - (syntax-error (car name*) "unexpected"))))) - (for-each - (lambda (name p expr) - (unless (p expr) - (syntax-error expr (format "invalid ~s ~s rhs syntax" (datum ?constructor-name) (syntax->datum name))))) - #'(?name (... ...)) - (list - (lambda (expr) - (syntax-case expr (lambda) - [(lambda (?param ...) . body) #t] - [(lambda . rest) #f] - [_ #t])) - ...) - #'(?expr (... ...))) - #'(mph ?expr (... ...)))]))))]))) - -;; The following input types are guaranteed upon reaching a handler: -;; who: symbol -;; bool: any object -;; p: input, output, or input/output port as appropriate -;; elt (binary port): exact nonnegative integer <= 255 -;; elt (textual port): character -;; elt/eof: elt or #!eof -;; bv: bytevector -;; start, count: exact nonnegative integer -;; -;; Also: start + count <= length(bv). -;; -;; The types of pos and len are port-specific and must be checked by -;; the handler - -;; Handlers are responsible for returning appropriate values: -;; bool: any object -;; elt (binary port): exact nonnegative integer <= 255 -;; elt (textual port): character -;; elt/eof: elt or eof -;; count: exact nonnegative integer -;; count/eof: count or eof -;; pos (binary port): exact nonnegative integer -;; pos (textual port): any object -;; len (binary port): exact nonnegative integer -;; len (textual port): any object -;; -;; Also: output count must be less than or equal to input count. - -; exporting all but port-handler, since it conflicts with the -; primtiive named port-handler -(module (make-port-handler port-handler? port-handler-ready? - port-handler-lookahead port-handler-unget - port-handler-get port-handler-get-some - port-handler-clear-input port-handler-put - port-handler-put-some port-handler-flush - port-handler-clear-output port-handler-close-port - port-handler-port-position - port-handler-set-port-position! - port-handler-port-length - port-handler-set-port-length! - port-handler-port-nonblocking? - port-handler-set-port-nonblocking!) - (define-port-handler (port-handler make-port-handler port-handler?) #{port-handler cx3umjhy9nkkuqku-a} - ; input: - (ready? who p -> bool) - (lookahead who p -> elt/eof) - (unget who p elt/eof -> void) - (get who p -> elt/eof) - (get-some who p bv start count -> count/eof) - (clear-input who p -> void) - - ; output: - (put who p elt -> void) - (put-some who p bv start count -> count) - (flush who p -> void) - (clear-output who p -> void) - - ; all: - (close-port who p -> void) - - ; optional: - (port-position who p -> pos) - (set-port-position! who p pos -> void) - (port-length who p -> len) - (set-port-length! who p len -> void) - (port-nonblocking? who p -> bool) - (set-port-nonblocking! who p bool -> void))) - -;;; max-*-copy is the maximum amount a bytevector put operation will copy -;;; from the supplied bytevector to the port's buffer. beyond this amount -;;; it will get/send contents directly from/to the underlying source/sink. -(define max-put-copy 256) -(define max-get-copy 256) diff --git a/ta6ob/s/io.ss b/ta6ob/s/io.ss deleted file mode 100644 index acfe0a7..0000000 --- a/ta6ob/s/io.ss +++ /dev/null @@ -1,6310 +0,0 @@ -;;; io.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; possible extensions: -;;; - mechanism for overriding default #o666 mode -;;; - user-defined handler records -;;; - say user-supplied handler procedures "should" return appropriate -;;; values (e.g., octet/eof for get on binary port), wrap procedures -;;; in return-value checkers, or allow user to choose whether -;;; procedures are wrapped in return-value checkers - -;;; r6rs custom ports are fubar: -;;; - binary and textual output ports: no known problems -;;; - binary input ports: no problem except just after a -;;; lookahead-u8 returns #!eof or just after unget-u8 of #!eof, -;;; at which point port position is ill-defined. -;;; - binary input/output ports: can't work without working -;;; get-position and set-position! procedures to switch between -;;; input and output mode -;;; - textual input ports: no way to implement port-position, -;;; since get-position returns an arbitrary object, no way to adjust for -;;; amount we've buffered, and we must buffer at least one character to -;;; support lookahead-char. also same problem as custom binary input -;;; ports with #!eof. -;;; - textual input/output ports: no way to switch between input -;;; and output modes, since we cannot implement port-position. -;;; -;;; all problems derive from need to buffer at least one element to -;;; support lookahead-u8 and lookahead-char. -;;; -;;; our workarounds: -;;; - custom binary and textual output ports: -;;; - none -;;; - custom binary input ports: -;;; - treat eof as zero width -;;; - assume sequential indices from get-position to compute port-position -;;; with adjustment for buffered characters -;;; - custom textual input ports: -;;; - treat eof as zero width -;;; - port-position undefined after read -;;; - no warning for port-position if: -;;; - no reads (including lookahead and port-eof?) have been done -;;; - a set-port-position! occurred after last read -;;; - buffer-mode is none and last read operation was not a lookahead, -;;; port-eof?, or unget -;;; - custom binary or textual input/output ports: -;;; - position for write undefined after read -;;; - port-position undefined after read -;;; - no warning for write or port-position if: -;;; - no reads (including lookahead and port-eof?) have been done -;;; - a write or set-port-position occurred after last read -;;; - buffer-mode is none and last read operation was not a lookahead, -;;; port-eof?, or unget (efficient input can be had with buffer-mode -;;; none if only get-bytevector operations are used. sequence of -;;; gets will relatively slow with buffer-mode none.) -;;; - exception: we use supplied get-position and -;;; set-position! on a custom binary input/output port to sync -;;; position and avoid issuing warnings under assumption that -;;; get-position indices are sequential - -#| -implementation notes: - - for binary input/output file ports, we can always distinguish input - mode from output mode by the fact that output-size is zero iff port is - in input mode. this does not work for textual ports, because - output-size can be zero even in output mode for line-buffered ports. - so we instead use an input-mode flag in the port header. -|# - -(begin -(set-who! file-buffer-size - ($make-thread-parameter $c-bufsiz - (lambda (x) - (unless (and (fixnum? x) (fx> x 0)) - ($oops who "~s is not a positive fixnum" x)) - x))) - -(set-who! custom-port-buffer-size - ($make-thread-parameter 128 - (lambda (x) - (unless (and (fixnum? x) (fx> x 0)) - ($oops who "~s is not a positive fixnum" x)) - x))) - -(let () - ; choose whether to issue warnings when custom-port implementation - ; cannot determine position for port-position or write operation - #;(define position-warning warning) - (define (position-warning who msg . args) (void)) - - (include "io-types.ss") - - (define-syntax call-port-handler - (lambda (x) - (syntax-case x () - [(_ msg who ?p arg ...) - (identifier? #'msg) - (with-syntax ([port-handler-msg (construct-name #'msg "port-handler-" #'msg)]) - #'(let ([p ?p]) ((port-handler-msg ($port-handler p)) who p arg ...)))]))) - - (define-port-handler (codec make-codec codec?) #f - (name -> string) - (make-info who tx bp bv -> codec-info)) - - ; ioffsets is an fxvector mapping character positions in a port's input buffer - ; to byte offsets from the starting byte position for the buffer. ibytes - ; is the byte offset of the character just beyond the end of the buffer, - ; which is also the length in bytes of the data represented by the characters - ; in the buffer. ioffsets and ibytes together allow port positions to be - ; reported in bytes. ioffsets and ibytes are not consulted when a port's - ; input buffer is empty, so there is no harm in modifying them when reading - ; into a different string. since ioffsets might not have as many elements - ; as the different string, however, a codec should usually avoid modifying - ; ioffsets to prevent writes beyond the end of the vector. a codec's encode - ; procedure is always called with start = 0 when string to fill is the port's - ; input buffer, so ibytes should also start at 0. - - (define-record-type codec-info - (nongenerative) - (opaque #t) - (fields - (immutable tx) ; transcoder - (mutable bp) ; binary port (clone) - (immutable bv) ; bytevector buffer (input or output, one at a time) - (mutable next) ; next pointer into buffer - (mutable iend) ; end of data (input only) - (immutable ioffsets) ; byte offset each char in port's buffer, relative to first (input only) - (mutable ibytes) ; byte offset of first char beyond port's buffer (input only) - (mutable icr) ; #\return seen when eol style is not none (input only) - (mutable bom) ; looking for byte-order-mark on input, or ready to write it on output - (mutable zbom) ; bom found or placed at position zero - (mutable big) ; big endian? - (immutable decode) ; input decoder - (immutable encode) ; output encoder - (immutable close))) - - ; keep make-fd in sync with types.h MAKE_FD - (define (make-fd intfd) intfd) - - (define (port-oops who p msg) - ($oops/c who - (make-i/o-port-error p) - "failed on ~s: ~(~a~)" p msg)) - - (define (read-oops who p msg) - ($oops/c who - (condition (make-i/o-read-error) (make-i/o-port-error p)) - "failed on ~s: ~(~a~)" p msg)) - - (define (write-oops who p msg) - ($oops/c who - (condition (make-i/o-write-error) (make-i/o-port-error p)) - "failed on ~s: ~(~a~)" p msg)) - - (define (position-oops who p pos msg) - ($oops/c who - (condition - (make-i/o-invalid-position-error pos) - (make-i/o-port-error p)) - "failed for position ~s on ~s: ~(~a~)" pos p msg)) - - (define (open-oops who filename file-options err.msg) - ($oops/c who - (let ([err (car err.msg)]) - (cond - [(eqv? err (constant OPEN-ERROR-PROTECTION)) - (make-i/o-file-protection-error filename)] - [(eqv? err (constant OPEN-ERROR-EXISTS)) - (make-i/o-file-already-exists-error filename)] - [(eqv? err (constant OPEN-ERROR-EXISTSNOT)) - (make-i/o-file-does-not-exist-error filename)] - [else (make-i/o-filename-error filename)])) - "failed for ~a: ~(~a~)" - filename - (cdr err.msg))) - - (define (unget-error who p x) - ($oops who "cannot unget ~s on ~s" x p)) - - (define eol-char? - (lambda (c) - (memv c '(#\newline #\return #\nel #\ls)))) - - (define-syntax port-gz-mode - (syntax-rules () - [(_ port) ($port-flags-set? port (constant port-flag-compressed))])) - (define-syntax port-flag-eof-set? - (syntax-rules () - [(_ port) ($port-flags-set? port (constant port-flag-eof))])) - (define-syntax assert-not-closed - (syntax-rules () - [(_ who port) - (when (port-closed? port) - ($oops who "not permitted on closed port ~s" port))])) - - (define-syntax file-options-list - (syntax-rules () - [(_) - '(no-create no-fail no-truncate compressed replace exclusive append - perm-set-user-id perm-set-group-id perm-sticky - perm-no-user-read perm-no-user-write perm-user-execute - perm-no-group-read perm-no-group-write perm-group-execute - perm-no-other-read perm-no-other-write perm-other-execute)])) - - (define-syntax eol-style-list - (syntax-rules () - [(_) '(lf cr crlf nel crnel ls none)])) - - (define-syntax error-handling-mode-list - (syntax-rules () - [(_) '(ignore raise replace)])) - - (define ($textual-port-bol? p) - (let ([index (textual-port-output-index p)]) - (if (fx= index 0) - ($port-flags-set? p (constant port-flag-bol)) - (eol-char? (string-ref (textual-port-output-buffer p) (fx- index 1)))))) - - (define-record-type (transcoder $make-transcoder $transcoder?) - (nongenerative) - (opaque #t) - (sealed #t) - (fields - (immutable codec $transcoder-codec) - (immutable eol-style $transcoder-eol-style) - (immutable error-handling-mode $transcoder-error-handling-mode))) - - ;; minimum-file-buffer-length is not 0 because of lookahead-u8 and - ;; unget-u8 and to simplify the logic for setting size and index based - ;; on length. the single byte will never be used for output ports. - (define minimum-file-buffer-length 1) - (define bytevector-buffer-length 128) - (define string-buffer-length 16) - (define buffered-transcoded-port-buffer-length 1024) - (define unbuffered-transcoded-port-buffer-length 1) - (define codec-buffer-length 1024) - - (define check-option ; for Chez Scheme list-based file open options - (lambda (who x y) - (when (and x (not (eq? x y))) - ($oops who "incompatible options ~s and ~s" x y)))) - - ;; Foreign calls to file system - ;; use critical-section to increment/decrement disable count. - ;; once we arrive in C code (e.g., bytevector-write) allow deactivation if - ;; disable-count == 1. this makes our port operations multitasking - ;; safe (within a single posix thread if threaded). - (define $open-input-fd - (foreign-procedure "(cs)new_open_input_fd" - (string boolean) scheme-object)) - (define $open-output-fd - (foreign-procedure "(cs)new_open_output_fd" - (string int - boolean boolean boolean - boolean boolean boolean boolean) - scheme-object)) - (define $open-input/output-fd - (foreign-procedure "(cs)new_open_input_output_fd" - (string int - boolean boolean boolean - boolean boolean boolean boolean) - scheme-object)) - (define $close-fd - (foreign-procedure "(cs)close_fd" - (scheme-object boolean) scheme-object)) - (define $bytevector-read - (foreign-procedure "(cs)bytevector_read" - (scheme-object scheme-object iptr iptr boolean) scheme-object)) - (define $bytevector-read-nb - (foreign-procedure "(cs)bytevector_read_nb" - (scheme-object scheme-object iptr iptr boolean) scheme-object)) - (define $bytevector-write - (foreign-procedure "(cs)bytevector_write" - (scheme-object scheme-object iptr iptr boolean) scheme-object)) - (define $put-byte - (foreign-procedure "(cs)put_byte" - (scheme-object int boolean) scheme-object)) - (define $set-fd-pos - (foreign-procedure "(cs)set_fd_pos" - (scheme-object scheme-object boolean) scheme-object)) - (define $get-fd-pos - (foreign-procedure "(cs)get_fd_pos" - (scheme-object boolean) scheme-object)) - (define $get-fd-nonblocking - (foreign-procedure "(cs)get_fd_non_blocking" - (scheme-object boolean) scheme-object)) - (define $set-fd-nonblocking - (foreign-procedure "(cs)set_fd_non_blocking" - (scheme-object boolean boolean) scheme-object)) - (define $get-fd-length - (foreign-procedure "(cs)get_fd_length" - (scheme-object boolean) scheme-object)) - (define $set-fd-length - (foreign-procedure "(cs)set_fd_length" - (scheme-object scheme-object boolean) scheme-object)) - (define $fd-regular? - (foreign-procedure "(cs)fd_regularp" (int) boolean)) - (define $compress-input-fd - (foreign-procedure "(cs)compress_input_fd" (int integer-64) scheme-object)) - (define $compress-output-fd - (foreign-procedure "(cs)compress_output_fd" (int) scheme-object)) - (module (clear-open-files register-open-file registered-open-file? unregister-open-file) - (define open-files #f) - (define file-guardian) - (define clear-open-files - ; called from single-threaded $scheme-init - (lambda () - (set! open-files (make-weak-eq-hashtable)) - (set! file-guardian (make-guardian)))) - ; should register only ports with known system handlers/transcoders - ; we don't want to get into arbitrary user code when automatically - ; closing. when files are closed, we close text ports first, then - ; binary ports, so it won't generally work to register a text port that - ; depends on another text port being open or a binary port that - ; depends on another binary port being open. - (define register-open-file - (lambda (p) - (when open-files - (with-tc-mutex - (eq-hashtable-set! open-files p #t) - (file-guardian p))))) - (define registered-open-file? - (lambda (p) - (and open-files - (with-tc-mutex - (eq-hashtable-contains? open-files p))))) - (define unregister-open-file - (lambda (p) - (when open-files - (with-tc-mutex - (eq-hashtable-delete! open-files p))))) - (define silent-close - (lambda (pvec) - ; do textual ports first, since they may encapsulate a binary port - (vector-for-each - (lambda (x) - (when (textual-port? x) - (guard (c [#t (void)]) (close-port x)))) - pvec) - ; now do binary ports - (vector-for-each - (lambda (x) - (when (binary-port? x) - (guard (c [#t (void)]) (close-port x)))) - pvec))) - (set! $close-resurrected-files - ; called from single-threaded docollect - (lambda () - (when open-files - (silent-close - (let f ([i 0]) - (let ([p (file-guardian)]) - (if p - (let ([v (f (fx+ i 1))]) (vector-set! v i p) v) - (make-vector i)))))))) - (set! $close-files - ; called from Sscheme_deinit - (lambda () - (with-tc-mutex - ; don't attempt to close ports if other threads are still running, since the other threads might be - ; using one or more of the ports up to the bitter end, and port operations are not thread-safe when - ; two threads operate on the same port. in particular, trying to close a compressed port here and - ; in one of the other threads concurrently can result in a double free in gzclose. - (when (and open-files (if-feature pthreads (= (length ($thread-list)) 1) #t)) - (silent-close (hashtable-keys open-files))))))) - - ;; Helpers for binary-file-ports - (define (extract-permission-mask options) - (fxlogor - (if (enum-set-subset? (file-options perm-set-user-id) options) #o4000 0) - (if (enum-set-subset? (file-options perm-set-group-id) options) #o2000 0) - (if (enum-set-subset? (file-options perm-sticky) options) #o1000 0) - (if (enum-set-subset? (file-options perm-no-user-read) options) 0 #o400) - (if (enum-set-subset? (file-options perm-no-user-write) options) 0 #o200) - (if (enum-set-subset? (file-options perm-user-execute) options) #o100 0) - (if (enum-set-subset? (file-options perm-no-group-read) options) 0 #o40) - (if (enum-set-subset? (file-options perm-no-group-write) options) 0 #o20) - (if (enum-set-subset? (file-options perm-group-execute) options) #o10 0) - (if (enum-set-subset? (file-options perm-no-other-read) options) 0 #o4) - (if (enum-set-subset? (file-options perm-no-other-write) options) 0 #o2) - (if (enum-set-subset? (file-options perm-other-execute) options) #o1 0))) - - (define-syntax do-read - (syntax-rules () - [(_ read p_) - (let ([p p_]) - (do-read read p - (binary-port-input-buffer p) - 0 (bytevector-length (binary-port-input-buffer p))))] - [(_ read p_ buffer start count) - (let ([p p_]) - (read ($port-info p) buffer start count (port-gz-mode p)))])) - (define-syntax bytevector-read - (syntax-rules () - [(_ args ...) (do-read $bytevector-read args ...)])) - (define-syntax bytevector-read-nb - (syntax-rules () - [(_ args ...) (do-read $bytevector-read-nb args ...)])) - - (define bytevector-write - (lambda (who p buffer start count) - (let ([n ($bytevector-write ($port-info p) buffer start count (port-gz-mode p))]) - (unless (fixnum? n) (write-oops who p n)) - n))) - - (define bytevector-flush - (lambda (who p buffer start count) - (let ([fd ($port-info p)] [gz (port-gz-mode p)]) - (let loop ([start start] [count count]) - (unless (eq? 0 count) - (let ([n ($bytevector-write fd buffer start count gz)]) - (unless (fixnum? n) (write-oops who p n)) - (loop (fx+ start n) (fx- count n)))))))) - - (define binary-file-port-flush - (lambda (who p) - (bytevector-flush who p (binary-port-output-buffer p) 0 - (binary-port-output-index p)) - (set-binary-port-output-index! p 0))) - - (define binary-file-port-ready? - (lambda (who p) - (or (not (port-input-empty? p)) - (port-flag-eof-set? p) - (let ([n (bytevector-read-nb p)]) - (cond - [(fixnum? n) (set-binary-port-input-size! p n) (not (eq? n 0))] - [(eof-object? n) (set-port-eof! p #t) #t] - [(equal? n "interrupt") 'interrupt] - [else (read-oops who p n)]))))) - - (define binary-file-port-lookahead - (lambda (who p) - (cond - [(not (port-input-empty? p)) - (bytevector-u8-ref (binary-port-input-buffer p) - (binary-port-input-index p))] - [(port-flag-eof-set? p) (eof-object)] - [else (let loop () - (let ([n (bytevector-read p)]) - (cond - [(eq? 0 n) (loop)] - [(fixnum? n) - (set-binary-port-input-size! p n) - (bytevector-u8-ref (binary-port-input-buffer p) 0)] - [(eof-object? n) (set-port-eof! p #t) n] - [(equal? n "interrupt") 'interrupt] - [else (read-oops who p n)])))]))) - - (define binary-file-port-unget - (lambda (who p x) - (when (port-flag-eof-set? p) (unget-error who p x)) - (if (eof-object? x) - (let () - (unless (port-input-empty? p) (unget-error who p x)) - (set-port-eof! p #t)) - (let ([index (binary-port-input-index p)]) - (when (eq? 0 index) (unget-error who p x)) - (set-binary-port-input-index! p (fx1- index)))))) - - (define binary-file-port-get - (lambda (who p) - (cond - [(not (port-input-empty? p)) - (let ([index (binary-port-input-index p)]) - (set-binary-port-input-index! p (fx1+ index)) - (bytevector-u8-ref (binary-port-input-buffer p) index))] - [(port-flag-eof-set? p) (set-port-eof! p #f) (eof-object)] - [else (let loop () - (let ([n (bytevector-read p)]) - (cond - [(eq? 0 n) (loop)] - [(fixnum? n) - (set-binary-port-input-size! p n) - (set-binary-port-input-index! p 1) - (bytevector-u8-ref (binary-port-input-buffer p) 0)] - [(eof-object? n) n] - [(equal? n "interrupt") 'interrupt] - [else (read-oops who p n)])))]))) - - (define binary-file-port-get-some - (lambda (who p bv start count) - (let ([port-count (binary-port-input-count p)]) - (cond - [(not (eq? 0 port-count)) - (let ([count (fxmin count port-count)] - [index (binary-port-input-index p)]) - (bytevector-copy! (binary-port-input-buffer p) index bv start count) - (set-binary-port-input-index! p (fx+ index count)) - count)] - [(port-flag-eof-set? p) (set-port-eof! p #f) (eof-object)] - [(and (fx<= count max-get-copy) (fx<= count (bytevector-length (binary-port-input-buffer p)))) - (let ([n (bytevector-read p)]) - (cond - [(fixnum? n) - (let ([count (fxmin n count)]) - (set-binary-port-input-size! p n) - (set-binary-port-input-index! p count) - (bytevector-copy! (binary-port-input-buffer p) 0 bv start count) - count)] - [(eof-object? n) n] - [(equal? n "interrupt") 'interrupt] - [else (read-oops who p n)]))] - [else (let ([n (bytevector-read p bv start count)]) - (cond - [(fixnum? n) n] - [(eof-object? n) n] - [(equal? n "interrupt") 'interrupt] - [else (read-oops who p n)]))])))) - - (define binary-file-port-clear-input - (lambda (who p) - (set-binary-port-input-size! p 0))) - - (define binary-file-port-put - (lambda (who p x) - (let ([index (binary-port-output-index p)] - [buffer (binary-port-output-buffer p)]) - (cond - [(not (port-output-full? p)) - (bytevector-u8-set! buffer index x) - (set-binary-port-output-index! p (fx1+ index))] - [(fx= index 0) ; since full, => size is 0 => unbuffered - (let loop () - (let ([n ($put-byte ($port-info p) x (port-gz-mode p))]) - (unless (fixnum? n) (write-oops who p n)) - (when (fx= n 0) (loop))))] - [else - (bytevector-u8-set! buffer index x) - (bytevector-flush who p buffer 0 (fx1+ index)) - (set-binary-port-output-index! p 0)])))) - - ;; The following diagram shows the control flow of put-some. - ;; It is complicated because it must handle nonblocking ports - ;; while also trying to minimize the number of operating system calls and - ;; being smart about when to buffer. - ;; - ;; Arrows marked with "@" are guarded with a try-fill that - ;; will try to exit the function early by copying the new bytevector - ;; into the old bytevector. Arrows marked with "@@" are the same - ;; but in future versions might be willing to partially copy - ;; the old buffer where as the "@" lines will only copy if - ;; the entire new data fits in the old buffer. - ;; - ;; old is the port's buffer - ;; new is the byte vector being passed in - ;; - ;; len(x)=0 tests whether x is empty and returns #t or #f - ;; write(x) writes the old buffer to the operating system and - ;; returns either ALL if all data was written or PARTIAL if - ;; one part of the data was written - ;; shift(old) bytevector copies to the front of old - ;; the part of old that wasn't written - - #| - --@-> len(old)=0 --(#f)--> write(old) --(PARTIAL)--> shift(old) --@@--> DONE - | | - | | - (#t) <---@---(ALL)---+ - | - V - len(new)=0 --(#f)--> write(new) --(PARTIAL)-----------------@@--> DONE - | | - | | - (#t) (ALL) - | | - V V - DONE DONE - |# - - (define binary-file-port-put-some - (lambda (who p bv start count) - ;; from-start: where to fill from - ;; from-count: how much to fill from (i.e. how much we want to put) - ;; to-start: where to fill to - ;; to-count: how much to fill to (i.e. how much room we have) - ;; body: what to do if not filling - (define-syntax try-fill - (syntax-rules () - [(_ from-start from-count to-start to-count body) - (if (and (fx<= from-count max-put-copy) - (fx<= from-count to-count)) - (begin - (bytevector-copy! bv from-start - (binary-port-output-buffer p) to-start - from-count) - (set-binary-port-output-index! p (fx+ to-start from-count)) - (fx+ (fx- from-start start) from-count)) - body)])) - - ;; buffer: what to write from - ;; start: where to write from - ;; count: how much to write from - ;; (n): var to bind to how many written - ;; zero: what to do if count is zero - ;; normal: what to do if all count written - ;; interrupted: what to do not all count written - (define-syntax try-write - (syntax-rules () - [(_ buffer start count (n) zero normal partial) - (if (eq? 0 count) - zero - (let ([n (bytevector-write who p buffer start count)]) - (if (eq? n count) - normal - partial)))])) - - ;; On entry: old buffer has been completely written - ;; and we need to write the new buffer - (define (write-new) - (try-write bv start count (n) 0 count - (try-fill (fx+ start n) (fx- count n) 0 (binary-port-output-size p) n))) - - (let ([port-index (binary-port-output-index p)] - [port-count (binary-port-output-count p)] - [port-size (binary-port-output-size p)] - [port-buffer (binary-port-output-buffer p)]) - (try-fill start count port-index port-count - (try-write port-buffer 0 port-index (n) - (write-new) - (try-fill start count 0 port-size - (begin - (set-binary-port-output-index! p 0) ;; may be reset by try-fill - (write-new))) - (let ([new-index (fx- port-index n)]) - (bytevector-copy! port-buffer n port-buffer 0 new-index) - (set-binary-port-output-index! p new-index) - (try-fill start count new-index (fx- port-size new-index) 0))))))) - - (define binary-file-port-clear-output - (lambda (who p) - (set-binary-port-output-index! p 0))) - - (define binary-file-port-close-port - (lambda (who p) - (when (input-port? p) - (set-port-eof! p #f) - (set-binary-port-input-size! p 0)) - (when (output-port? p) (set-binary-port-output-size! p 0)) - (unregister-open-file p) - ; mark port closed before closing fd. if an interrupt occurs, we'd prefer - ; that the fd's resources never be freed than to have an open port floating - ; around with fd resources that have already been freed. - (mark-port-closed! p) - (let ([msg ($close-fd ($port-info p) (port-gz-mode p))]) - (unless (eq? #t msg) (port-oops who p msg))))) - - (define-syntax binary-file-port-port-position - (syntax-rules () - [(_ mode who ?p) - (member (datum mode) '(in out in/out)) - (let ([p ?p]) - (let ([n ($get-fd-pos ($port-info p) (port-gz-mode p))]) - (unless (or (fixnum? n) (bignum? n)) (port-oops who p n)) - (- (+ n (if (eq? 'mode 'in) 0 (binary-port-output-index p))) - (if (eq? 'mode 'out) 0 (binary-port-input-count p)))))])) - - (define binary-file-port-set-port-position! - (lambda (who p x) - (unless (and (integer? x) (exact? x) (<= 0 x (- (expt 2 63) 1))) - ($oops who "~s is not a valid position" x)) - (let ([n ($set-fd-pos ($port-info p) x (port-gz-mode p))]) - (unless (eq? n #t) (position-oops who p x n))))) - - (define binary-file-port-port-nonblocking? - (lambda (who p) - (let ([n ($get-fd-nonblocking ($port-info p) (port-gz-mode p))]) - (unless (boolean? n) (port-oops who p n)) - n))) - - (define binary-file-port-set-port-nonblocking! - (lambda (who p x) - (let ([n ($set-fd-nonblocking ($port-info p) x (port-gz-mode p))]) - (unless (eq? n #t) (port-oops who p n))))) - - (define binary-file-port-port-length - (lambda (who p) - (let ([n ($get-fd-length ($port-info p) (port-gz-mode p))]) - (unless (or (fixnum? n) (bignum? n)) (port-oops who p n)) - n))) - - (define binary-file-port-set-port-length! - (lambda (who p x) - (unless (and (integer? x) (exact? x) (<= 0 x (- (expt 2 63) 1))) - ($oops who "~s is not a valid length" x)) - (let ([n ($set-fd-length ($port-info p) x (port-gz-mode p))]) - (unless (eq? n #t) (port-oops who p n))))) - - ;; Helpers for binary-custom-ports - (define (bv-read! who p read! bv start count) - (let ([n (read! bv start count)]) - (unless (and (fixnum? n) (fx<= 0 n count)) - ($oops who "invalid result ~s from read! on ~s" n p)) - n)) - - (define (binary-port-read! who p read!) - (let ([bv (binary-port-input-buffer p)]) - (let ([n (bv-read! who p read! bv 0 (bytevector-length bv))]) - (if (eq? 0 n) - (eof-object) - (begin - (set-binary-port-input-size! p n) - (bytevector-u8-ref bv 0)))))) - - (define bv-write! ;; loops until count written - (lambda (who p write! bv start count) - (let loop ([start start] - [count count]) - (unless (eq? 0 count) - (let ([result (write! bv start count)]) - (unless (and (fixnum? result) (fx<= 0 result count)) - ($oops who "invalid result ~s from write! on ~s" result p)) - (loop (fx+ start result) (fx- count result))))))) - - (define binary-custom-port-lookahead - (lambda (who p read!) - (cond - [(not (port-input-empty? p)) - (bytevector-u8-ref (binary-port-input-buffer p) - (binary-port-input-index p))] - [(port-flag-eof-set? p) (eof-object)] - [else (let ([x (binary-port-read! who p read!)]) - (when (eof-object? x) - (set-port-eof! p #t)) - x)]))) - - (define binary-custom-port-unget - (lambda (who p x) - (when (port-flag-eof-set? p) (unget-error who p x)) - (if (eof-object? x) - (let () - (unless (port-input-empty? p) (unget-error who p x)) - (set-port-eof! p #t)) - (let ([index (binary-port-input-index p)]) - (when (eq? 0 index) (unget-error who p x)) - (set-binary-port-input-index! p (fx1- index)))))) - - (define binary-custom-port-get - (lambda (who p read!) - (cond - [(not (port-input-empty? p)) - (let ([index (binary-port-input-index p)]) - (set-binary-port-input-index! p (fx1+ index)) - (bytevector-u8-ref (binary-port-input-buffer p) index))] - [(port-flag-eof-set? p) (set-port-eof! p #f) (eof-object)] - [else (let ([x (binary-port-read! who p read!)]) - (unless (eof-object? x) - (set-binary-port-input-index! p 1)) - x)]))) - - (define binary-custom-port-get-some - (lambda (who p read! bv start count) - (let ([port-count (binary-port-input-count p)]) - (cond - [(not (eq? 0 port-count)) - (let ([count (fxmin count port-count)] - [index (binary-port-input-index p)]) - (bytevector-copy! (binary-port-input-buffer p) index bv start count) - (set-binary-port-input-index! p (fx+ index count)) - count)] - [(port-flag-eof-set? p) (set-port-eof! p #f) (eof-object)] - [else (let ([n (bv-read! who p read! bv start count)]) - (if (eq? 0 n) - (eof-object) - n))])))) - - (define binary-custom-port-clear-input - (lambda (who p) - (set-binary-port-input-size! p 0))) - - (define binary-custom-port-put - (lambda (who p write! x) - (let ([buffer (binary-port-output-buffer p)] - [index (binary-port-output-index p)]) - (bytevector-u8-set! buffer index x) - (let ([new-index (fx1+ index)]) - (if (port-output-full? p) - (begin - (bv-write! who p write! buffer 0 new-index) - (set-binary-port-output-index! p 0)) - (set-binary-port-output-index! p new-index)))))) - - (define binary-custom-port-put-some - (lambda (who p write! bv start count) - (if (and (fx<= count max-put-copy) (fx<= count (binary-port-output-count p))) - (begin - (let ([index (binary-port-output-index p)]) - (bytevector-copy! bv start - (binary-port-output-buffer p) index - count) - (set-binary-port-output-index! p (fx+ index count)) - count)) - (begin - (bv-write! who p write! (binary-port-output-buffer p) - 0 (binary-port-output-index p)) - (bv-write! who p write! bv start count) - (set-binary-port-output-index! p 0) - count)))) - - (define-syntax binary-custom-port-flush - (syntax-rules () - [(_ who p_ write!) - (let ([p p_]) - (bv-write! who p write! (binary-port-output-buffer p) - 0 (binary-port-output-index p)) - (set-binary-port-output-index! p 0))])) - - (define binary-custom-port-clear-output - (lambda (who p) - (set-binary-port-output-index! p 0))) - - (define binary-custom-port-close-port - (lambda (who p close) - (when close (close)) - (mark-port-closed! p) - (when (input-port? p) - (set-port-eof! p #f) - (set-binary-port-input-size! p 0)) - (when (output-port? p) (set-binary-port-output-size! p 0)))) - - (define-syntax binary-custom-port-port-position - (syntax-rules () - [(_ mode who ?p get-position) - (member (datum mode) '(in out in/out)) - (let ([p ?p]) - (let ([n (get-position)]) - (unless (or (and (fixnum? n) (fx>= n 0)) (and (bignum? n) (>= n 0))) - ($oops who "invalid result ~s from get-position on ~s" n p)) - (- (+ n (if (eq? 'mode 'in) 0 (binary-port-output-index p))) - (if (eq? 'mode 'out) 0 (binary-port-input-count p)))))])) - - ;; Helpers for textual-custom-ports - (define (str-read! who p read! str start count) - (let ([n (read! str start count)]) - (unless (and (fixnum? n) (fx<= 0 n count)) - ($oops who "invalid result ~s from read! on ~s" n p)) - n)) - - (define (textual-port-read! who p read!) - (let ([str (textual-port-input-buffer p)]) - (let ([n (str-read! who p read! str 0 (string-length str))]) - (if (fx= n 0) - (eof-object) - (begin - (set-textual-port-input-size! p n) - (string-ref str 0)))))) - - (define str-write! ;; loops until count written - (lambda (who p write! str start count) - (let loop ([start start] [count count]) - (unless (fx= count 0) - (let ([result (write! str start count)]) - (unless (and (fixnum? result) (fx<= 0 result count)) - ($oops who "invalid result ~s from write! on ~s" result p)) - (loop (fx+ start result) (fx- count result))))))) - - (define textual-custom-port-lookahead - (lambda (who p read!) - (cond - [(not (port-input-empty? p)) - (string-ref - (textual-port-input-buffer p) - (textual-port-input-index p))] - [(port-flag-eof-set? p) (eof-object)] - [else - (let ([x (textual-port-read! who p read!)]) - (when (eof-object? x) (set-port-eof! p #t)) - x)]))) - - (define textual-custom-port-unget - (lambda (who p x) - (when (port-flag-eof-set? p) (unget-error who p x)) - (if (eof-object? x) - (let () - (unless (port-input-empty? p) (unget-error who p x)) - (set-port-eof! p #t)) - (let ([index (textual-port-input-index p)]) - (when (eq? 0 index) (unget-error who p x)) - (set-textual-port-input-index! p (fx1- index)))))) - - (define textual-custom-port-get - (lambda (who p read!) - (cond - [(not (port-input-empty? p)) - (let ([index (textual-port-input-index p)]) - (set-textual-port-input-index! p (fx1+ index)) - (string-ref (textual-port-input-buffer p) index))] - [(port-flag-eof-set? p) (set-port-eof! p #f) (eof-object)] - [else (let ([x (textual-port-read! who p read!)]) - (unless (eof-object? x) - (set-textual-port-input-index! p 1)) - x)]))) - - (define textual-custom-port-get-some - (lambda (who p read! str start count) - (let ([port-count (textual-port-input-count p)]) - (cond - [(not (fx= port-count 0)) - (let ([count (fxmin count port-count)] - [index (textual-port-input-index p)]) - (string-copy! (textual-port-input-buffer p) index str start count) - (set-textual-port-input-index! p (fx+ index count)) - count)] - [(port-flag-eof-set? p) (set-port-eof! p #f) (eof-object)] - [else (let ([n (str-read! who p read! str start count)]) - (if (eq? 0 n) - (eof-object) - n))])))) - - (define textual-custom-port-clear-input - (lambda (who p) - (set-textual-port-input-size! p 0))) - - (define textual-custom-port-put - (lambda (who p write! x) - (let ([buffer (textual-port-output-buffer p)] - [index (textual-port-output-index p)]) - (string-set! buffer index x) - (let ([new-index (fx1+ index)]) - (if (port-output-full? p) - (begin - (str-write! who p write! buffer 0 new-index) - (set-port-bol! p (eol-char? (string-ref buffer index))) - (set-textual-port-output-index! p 0)) - (set-textual-port-output-index! p new-index)))))) - - (define textual-custom-port-put-some - (lambda (who p write! str start count) - (if (and (fx<= count max-put-copy) (fx<= count (textual-port-output-count p))) - (begin - (let ([index (textual-port-output-index p)]) - (string-copy! str start - (textual-port-output-buffer p) index - count) - (set-textual-port-output-index! p (fx+ index count)) - count)) - (begin - (str-write! who p write! (textual-port-output-buffer p) - 0 (textual-port-output-index p)) - (str-write! who p write! str start count) - (set-textual-port-output-index! p 0) - (set-port-bol! p (eol-char? (string-ref str (fx- (fx+ start count) 1)))) - count)))) - - (define textual-custom-port-flush - (lambda (who p write!) - (let ([n (textual-port-output-index p)]) - (unless (fx= n 0) - (let ([buffer (textual-port-output-buffer p)]) - (str-write! who p write! buffer 0 n) - (set-port-bol! p (eol-char? (string-ref buffer (fx- n 1)))) - (set-textual-port-output-index! p 0)))))) - - (define textual-custom-port-clear-output - (lambda (who p) - (set-textual-port-output-index! p 0))) - - (define textual-custom-port-close-port - (lambda (who p close) - (when close (close)) - (mark-port-closed! p) - (when (input-port? p) - (set-port-eof! p #f) - (set-textual-port-input-size! p 0)) - (when (output-port? p) (set-textual-port-output-size! p 0)))) - - (define-syntax check-interrupt - (syntax-rules () - [(_ e) - (let loop () - (let ([x e]) - (if (eq? x 'interrupt) - (begin ($event) (loop)) - x)))])) - - (module (open-binary-fd-input-port) - ;; NOTE: port-info stores the file descriptor number or gzFile object - (define (make-binary-file-input-handler regular?) - (make-port-handler - [ready? - (lambda (who p) - (check-interrupt - (critical-section - (assert-not-closed who p) - (binary-file-port-ready? who p))))] - [lookahead - (lambda (who p) - (check-interrupt - (critical-section - (assert-not-closed who p) - (binary-file-port-lookahead who p))))] - [unget - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (binary-file-port-unget who p x)))] - [get - (lambda (who p) - (check-interrupt - (critical-section - (assert-not-closed who p) - (binary-file-port-get who p))))] - [get-some - (lambda (who p bv start count) - (check-interrupt - (critical-section - (assert-not-closed who p) - (binary-file-port-get-some who p bv start count))))] - [clear-input - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-clear-input who p)))] - [put #f] - [put-some #f] - [flush #f] - [clear-output #f] - [close-port - (lambda (who p) - (critical-section - (unless (port-closed? p) - (binary-file-port-close-port who p))))] - [port-position - (and regular? - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-port-position in who p))))] - [set-port-position! - (and regular? - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (binary-file-port-set-port-position! who p x) - (set-binary-port-input-size! p 0) ;; junk the buffer data - (set-port-eof! p #f))))] - [port-length - (and regular? - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-port-length who p))))] - [set-port-length! #f] - [port-nonblocking? - (if-feature windows #f - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-port-nonblocking? who p))))] - [set-port-nonblocking! - (if-feature windows #f - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (binary-file-port-set-port-nonblocking! who p x))))])) - - (define open-binary-fd-input-port - (lambda (who name fd regular? mode gzflag) - (let ([buffer-length (if (eq? mode (buffer-mode none)) - minimum-file-buffer-length - (file-buffer-size))]) - (let ([p ($make-binary-input-port - name ;; name - (make-binary-file-input-handler regular?) ;; handler - (make-bytevector buffer-length) ;; buffer - fd)]) ;; info - (if (eq? mode (buffer-mode block)) - ($set-port-flags! p (constant port-flag-block-buffered)) - (when (eq? mode (buffer-mode line)) - ($set-port-flags! p (constant port-flag-line-buffered)))) - ($set-port-flags! p (constant port-flag-file)) - (when gzflag - ($set-port-flags! p (constant port-flag-compressed))) - ;; size is set by $make-binary-input-port, but - ;; we want it to trip the handler the first time so - ;; re-set the size to zero - (set-binary-port-input-size! p 0) - (register-open-file p) - p))))) - - (module (open-binary-fd-output-port) - ;; NOTE: output-size is one less than actual buffer size so - ;; we always have a place to put data before calling write - (define (make-binary-file-output-handler regular?) - (make-port-handler - [ready? #f] - [lookahead #f] - [unget #f] - [get #f] - [get-some #f] - [clear-input #f] - [put - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (binary-file-port-put who p x)))] - [put-some - (lambda (who p bv start count) - (critical-section - (assert-not-closed who p) - (binary-file-port-put-some who p bv start count)))] - [flush - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-flush who p)))] - [clear-output - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-clear-output who p)))] - [close-port - (lambda (who p) - (critical-section - (unless (port-closed? p) - (binary-file-port-flush who p) - (binary-file-port-close-port who p))))] - [port-position - (and regular? - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-port-position out who p))))] - [set-port-position! - (and regular? - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (binary-file-port-flush who p) - (binary-file-port-set-port-position! who p x))))] - [port-length - (and regular? - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-flush who p) - (binary-file-port-port-length who p))))] - [set-port-length! - (and regular? - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (binary-file-port-flush who p) - (binary-file-port-set-port-length! who p x))))] - [port-nonblocking? - (if-feature windows #f - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-port-nonblocking? who p))))] - [set-port-nonblocking! - (if-feature windows #f - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (binary-file-port-set-port-nonblocking! who p x))))])) - - (define open-binary-fd-output-port - (lambda (who name fd regular? b-mode lock compressed) - (let ([buffer-length (if (eq? b-mode (buffer-mode none)) - minimum-file-buffer-length - (file-buffer-size))]) - (let ([p ($make-binary-output-port - name ;; name - (make-binary-file-output-handler regular?) ;; handler - (make-bytevector buffer-length) ;; buffer - fd)]) ;; info - (if (eq? b-mode (buffer-mode block)) - ($set-port-flags! p (constant port-flag-block-buffered)) - (when (eq? b-mode (buffer-mode line)) - ($set-port-flags! p (constant port-flag-line-buffered)))) - ($set-port-flags! p (constant port-flag-file)) - (when compressed - ($set-port-flags! p (constant port-flag-compressed))) - (when lock - ($set-port-flags! p (constant port-flag-exclusive))) - (set-binary-port-output-size! p (fx1- buffer-length)) ;; leave room for put to work - (register-open-file p) - p))))) - - (module (open-binary-fd-input/output-port) - ;; Two modes: ready-for-input and ready-for-output - ;; - ;; ready-for-input: output-size == 0 - ;; ready-for-output: output-size == length-1 and input-size == 0 - ;; - ;; unbuffered port (ports with length 1 buffers) may be both - ;; ready-for-input and ready-for-output simultaneously, - ;; but it is never the case that both - ;; output-size != 0 and input-size != 0 - ;; - ;; for our purposes having the eof flag set is the same as input-size != 0 - - (define-syntax make-ready-for-input - (syntax-rules () - [(_ who p_) - (let ([p p_]) - (unless (eq? 0 (binary-port-output-size p)) - (binary-file-port-flush who p) - ;; don't set input-size; it is set only after a read - (set-binary-port-output-size! p 0)))])) - - (module ((make-ready-for-output $make-ready-for-output)) - (define $make-ready-for-output - (lambda (who p) - (unless (eq? (binary-port-input-size p) 0) - (unless (port-input-empty? p) - (binary-file-port-set-port-position! who p - (binary-file-port-port-position in/out who p))) - (set-binary-port-input-size! p 0)) - (set-port-eof! p #f) - (set-binary-port-output-size! p - (fx1- (bytevector-length (binary-port-output-buffer p)))))) - - (define-syntax make-ready-for-output - (syntax-rules () - [(_ ?who ?p) - (let ([p ?p]) - (when (eq? (binary-port-output-size p) 0) - ($make-ready-for-output ?who p)))]))) - - (define (make-binary-file-input/output-handler regular?) - (make-port-handler - [ready? - (lambda (who p) - (check-interrupt - (critical-section - (assert-not-closed who p) - (make-ready-for-input who p) - (binary-file-port-ready? who p))))] - [lookahead - (lambda (who p) - (check-interrupt - (critical-section - (assert-not-closed who p) - (make-ready-for-input who p) - (binary-file-port-lookahead who p))))] - [unget - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (make-ready-for-input who p) - (binary-file-port-unget who p x)))] - [get - (lambda (who p) - (check-interrupt - (critical-section - (assert-not-closed who p) - (make-ready-for-input who p) - (binary-file-port-get who p))))] - [get-some - (lambda (who p bv start count) - (check-interrupt - (critical-section - (assert-not-closed who p) - (make-ready-for-input who p) - (binary-file-port-get-some who p bv start count))))] - [clear-input - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-clear-input who p)))] - [put - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (make-ready-for-output who p) - (binary-file-port-put who p x)))] - [put-some - (lambda (who p bv start count) - (critical-section - (assert-not-closed who p) - (make-ready-for-output who p) - (binary-file-port-put-some who p bv start count)))] - [flush - (lambda (who p) - (critical-section - (assert-not-closed who p) - (make-ready-for-output who p) - (binary-file-port-flush who p)))] - [clear-output - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-clear-output who p)))] - [close-port - (lambda (who p) - (critical-section - (unless (port-closed? p) - (binary-file-port-flush who p) - (binary-file-port-close-port who p))))] - [port-position - (and regular? - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-port-position in/out who p))))] - [set-port-position! - (and regular? - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (binary-file-port-flush who p) - (binary-file-port-set-port-position! who p x) - (set-binary-port-input-size! p 0) ;; junk the buffer data - (set-port-eof! p #f))))] - [port-length - (and regular? - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-flush who p) - (binary-file-port-port-length who p))))] - [set-port-length! - (and regular? - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (cond - [(and (fx= (binary-port-input-size p) 0) (not (port-flag-eof-set? p))) - (binary-file-port-flush who p) - (binary-file-port-set-port-length! who p x)] - [else - (let ([pos (binary-file-port-port-position in/out who p)]) - (set-binary-port-input-size! p 0) ;; junk the buffer data - (set-port-eof! p #f) - (binary-file-port-set-port-length! who p x) - (binary-file-port-set-port-position! who p pos))]))))] - [port-nonblocking? - (if-feature windows #f - (lambda (who p) - (critical-section - (assert-not-closed who p) - (binary-file-port-port-nonblocking? who p))))] - [set-port-nonblocking! - (if-feature windows #f - (lambda (who p x) - (critical-section - (assert-not-closed who p) - (binary-file-port-set-port-nonblocking! who p x))))])) - - (define open-binary-fd-input/output-port - (lambda (who name fd regular? b-mode lock compressed) - (let ([buffer-length (if (eq? b-mode (buffer-mode none)) - minimum-file-buffer-length - (file-buffer-size))]) - (let ([p ($make-binary-input/output-port - name ;; name - (make-binary-file-input/output-handler regular?) ;; handler - (make-bytevector buffer-length) ;; input buffer - (make-bytevector buffer-length) ;; output buffer - fd)]) ;; info - (if (eq? b-mode (buffer-mode block)) - ($set-port-flags! p (constant port-flag-block-buffered)) - (when (eq? b-mode (buffer-mode line)) - ($set-port-flags! p (constant port-flag-line-buffered)))) - ($set-port-flags! p (constant port-flag-file)) - (when compressed - ($set-port-flags! p (constant port-flag-compressed))) - (when lock - ($set-port-flags! p (constant port-flag-exclusive))) - ;; size is set by $make-binary-input/output-port, but - ;; we want it to trip the handler the first time so - ;; re-set the size to zero - (set-binary-port-input-size! p 0) - (set-binary-port-output-size! p (fx1- buffer-length)) ;; leave room for put to work - (register-open-file p) - p))))) - -;;;; Public functions - ;; All section numbers are from ``R6RS -- Standard Libraries'' - -;;;; 8.1 Condition types (in exceptions.ss) - -;;;; 8.2 Port I/O: (rnrs io ports (6)) -;;;; 8.2.1 Filenames -;;;; 8.2.2 File options - ;; file-options in syntax.ss - (set-who! $file-options (make-enumeration (file-options-list))) - (set-who! $make-file-options (enum-set-constructor $file-options)) - -;;;; 8.2.3 Buffer modes - ;; buffer-mode in syntax.ss - (set-who! buffer-mode? - (lambda (mode) (and (memq mode '(none line block)) #t))) - -;;;; 8.2.4 Transcoders - (let () - (define (encode-oops who tp c) - ($oops/c who - (make-i/o-encoding-error tp c) - (parameterize ([print-unicode #f]) - (let* ([tx (codec-info-tx ($port-info tp))] - [name (codec-name ($transcoder-codec tx))]) - (if (and (eqv? c #\newline) (not (memq ($transcoder-eol-style tx) '(none lf)))) - (format "~a codec cannot encode ~s with eol-style ~s" - name c ($transcoder-eol-style tx)) - (format "~a codec cannot encode ~s" name c)))))) - - (define (decode-oops who tp msg . args) - (apply $oops/c who - (make-i/o-decoding-error tp) - msg args)) - - (define (flush-buffer who bp bv i k) - (if (fx= k 0) - 0 - (let ([n (call-port-handler put-some who bp bv i k)]) - (if (fx= n 0) - (begin - (unless (fx= i 0) (bytevector-copy! bv i bv 0 k)) - k) - (flush-buffer who bp bv (fx+ i n) (fx- k n)))))) - - (define get-some-maybe-nb - ; get some from binary port bp. if ifready? is true, don't block if port - ; isn't ready, even if port has not been set nonblocking - (lambda (who bp bv start ifready?) - (let ([h ($port-handler bp)]) - ; port-handler-ready? may raise an exception, but that's okay because ifready? - ; is true only if this is called from transcoded-port's port-handler-ready?. - (if (or (not ifready?) ((port-handler-ready? h) who bp)) - ((port-handler-get-some h) who bp bv start (fx- codec-buffer-length start)) - 0)))) - - (let () - (define latin-1-decode - (let () - (define (return ans i iend cr? bytes info) - (codec-info-next-set! info i) - (codec-info-iend-set! info iend) - (codec-info-ibytes-set! info bytes) - (codec-info-icr-set! info cr?) - ans) - (lambda (who tp str start count ifready?) - (let ([info ($port-info tp)]) - (let ([bp (codec-info-bp info)] - [ioffsets (and (eq? str (textual-port-input-buffer tp)) (codec-info-ioffsets info))] - [bv (codec-info-bv info)] - [jend (fx+ start count)]) - (let loop ([j start] - [i (codec-info-next info)] - [iend (codec-info-iend info)] - [cr? (codec-info-icr info)] - [bytes 0]) - (cond - [(fx= j jend) (return count i iend cr? bytes info)] - [(fx= i iend) - (if (fx= j start) - (let ([n (get-some-maybe-nb who bp bv 0 ifready?)]) - (cond - [(eof-object? n) (return #!eof i iend #f bytes info)] - [(fx= n 0) (return 0 i iend cr? bytes info)] - [else (loop j 0 n cr? bytes)])) - ; don't try to read in this case to avoid dealing with eof - (return (fx- j start) i iend cr? bytes info))] - [else - (let ([b (bytevector-u8-ref bv i)]) - (cond - [(fx= b #x0d) - (cond - [(eq? ($transcoder-eol-style (codec-info-tx info)) 'none) - (string-set! str j #\return) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 1) iend cr? (fx+ bytes 1))] - [else - (string-set! str j #\newline) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 1) iend #t (fx+ bytes 1))])] - [(fx= b #x0a) - (cond - [cr? (loop j (fx+ i 1) iend #f (fx+ bytes 1))] - [else - (string-set! str j #\newline) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 1) iend cr? (fx+ bytes 1))])] - [(fx= b #x85) ; NEL - (cond - [cr? (loop j (fx+ i 1) iend #f (fx+ bytes 1))] - [else - (string-set! str j - (if (eq? ($transcoder-eol-style (codec-info-tx info)) 'none) - (integer->char #x85) - #\newline)) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 1) iend cr? (fx+ bytes 1))])] - [else - (string-set! str j (integer->char b)) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 1) iend #f (fx+ bytes 1))]))]))))))) - - (define latin-1-encode - (let () - (define (return ans o info) - (codec-info-next-set! info o) - ans) - (lambda (who tp str start count) - (let ([info ($port-info tp)]) - (let ([bp (codec-info-bp info)] - [bv (codec-info-bv info)] - [jend (fx+ start count)]) - (let loop ([j start] [o (codec-info-next info)]) - (cond - [(fx= j jend) (return count o info)] - [(fx= o codec-buffer-length) - (let ([o (flush-buffer who bp bv 0 o)]) - (if (fx= o codec-buffer-length) - (return (fx- j start) o info) - (loop j o)))] - [else - (let ([int (char->integer (string-ref str j))]) - (cond - [(fx= int #x0a) - (let ([eol-style ($transcoder-eol-style (codec-info-tx info))]) - (case eol-style - [(lf none) - (bytevector-u8-set! bv o #x0a) - (loop (fx+ j 1) (fx+ o 1))] - [(cr) - (bytevector-u8-set! bv o #x0d) - (loop (fx+ j 1) (fx+ o 1))] - [(nel) - (bytevector-u8-set! bv o #x85) - (loop (fx+ j 1) (fx+ o 1))] - [(crlf crnel) - (let f ([o o]) - (if (fx< o (fx- codec-buffer-length 1)) - (begin - (bytevector-u8-set! bv o #x0d) - (bytevector-u8-set! bv (fx+ o 1) (if (eq? eol-style 'crlf) #x0a #x85)) - (loop (fx+ j 1) (fx+ o 2))) - (let ([new-o (flush-buffer who bp bv 0 o)]) - (if (fx= new-o o) - (return (fx- j start) o info) - (f new-o)))))] - [(ls) - (let ([error-mode ($transcoder-error-handling-mode (codec-info-tx info))]) - (case error-mode - [(ignore) (loop (fx+ j 1) o)] - [(replace) - (bytevector-u8-set! bv o (char->integer #\?)) - (loop (fx+ j 1) (fx+ o 1))] - [(raise) (encode-oops who tp #\newline)] - [else ($oops who "unknown error handling mode ~s" error-mode)]))] - [else ($oops who "unrecognized eol style ~s" eol-style)]))] - [(fx<= int 255) - (bytevector-u8-set! bv o int) - (loop (fx+ j 1) (fx+ o 1))] - [else - (let ([error-mode ($transcoder-error-handling-mode (codec-info-tx info))]) - (case ($transcoder-error-handling-mode (codec-info-tx info)) - [(ignore) (loop (fx+ j 1) o)] - [(replace) - (bytevector-u8-set! bv o (char->integer #\?)) - (loop (fx+ j 1) (fx+ o 1))] - [(raise) (encode-oops who tp (string-ref str j))] - [else ($oops who "unknown error handling mode ~s" error-mode)]))]))]))))))) - - (set-who! latin-1-codec - (let () - (define codec - (make-codec - [name "latin-1"] - [make-info - (lambda (who tx bp bv) - (make-codec-info tx bp bv 0 0 - (and (input-port? bp) (make-fxvector (bytevector-length bv))) - 0 #f #f #f #f - latin-1-decode latin-1-encode (lambda (info) #f)))])) - (lambda () codec)))) - - (let () - (define utf-8-decode - (let () - (define (err who tp info i iend bytes b . b*) - (codec-info-bom-set! info #f) - (codec-info-next-set! info i) - (codec-info-iend-set! info iend) - (codec-info-ibytes-set! info (fx+ bytes 1 (length b*))) - (codec-info-icr-set! info #f) - (decode-oops who tp "invalid utf-8 encoding #x~2,'0x~{, ~a~}" b - (map (lambda (b) (if (eof-object? b) "#!eof" (format "#x~2,'0x" b))) b*))) - (define (eof-err who tp info i iend bytes) - (unless (fx= bytes 0) (codec-info-bom-set! info #f)) - (codec-info-next-set! info iend) - (codec-info-iend-set! info iend) - (codec-info-ibytes-set! info (fx+ bytes (fx- iend i))) - (codec-info-icr-set! info #f) - (decode-oops who tp "unexpected end-of-file reading multibyte utf-8 encoding")) - (define (return ans i iend cr? bytes info) - (unless (fx= bytes 0) (codec-info-bom-set! info #f)) - (codec-info-next-set! info i) - (codec-info-iend-set! info iend) - (codec-info-ibytes-set! info bytes) - (codec-info-icr-set! info cr?) - ans) - (lambda (who tp str start count ifready?) - (let ([info ($port-info tp)]) - (let ([bp (codec-info-bp info)] - [ioffsets (and (eq? str (textual-port-input-buffer tp)) (codec-info-ioffsets info))] - [bv (codec-info-bv info)] - [jend (fx+ start count)]) - (define-syntax decode-error - (syntax-rules () - [(_ j i iend bytes b1 b2 ...) - (case ($transcoder-error-handling-mode (codec-info-tx info)) - [(ignore) j] - [(replace) - (string-set! str j #\xfffd) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (fx+ j 1)] - [else (err who tp info i iend bytes b1 b2 ...)])])) - (define-syntax decode-eof-error - (syntax-rules () - [(_ j i iend bytes) - (case ($transcoder-error-handling-mode (codec-info-tx info)) - [(ignore) (return #!eof iend iend #f (fx+ bytes (fx- iend i)) info)] - [(replace) - (string-set! str j #\xfffd) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (return (fx- (fx+ j 1) start) iend iend #f (fx+ bytes (fx- iend i)) info)] - [else (eof-err who tp info i iend bytes)])])) - (let loop ([j start] - [i (codec-info-next info)] - [iend (codec-info-iend info)] - [cr? (codec-info-icr info)] - [bytes 0]) - (cond - [(fx= j jend) (pariah (return count i iend cr? bytes info))] - [(fx= i iend) - (pariah - (if (fx= j start) - (let ([n (get-some-maybe-nb who bp bv 0 ifready?)]) - (cond - [(eof-object? n) (return #!eof 0 0 #f bytes info)] - [(fx= n 0) (return 0 0 0 cr? bytes info)] - [else (loop j 0 n cr? bytes)])) - ; don't try to read in this case to avoid dealing with eof - (return (fx- j start) i iend cr? bytes info)))] - [else - (let ([b1 (bytevector-u8-ref bv i)]) - (cond - [(fx<= b1 #x7f) ; one-byte encoding - (cond - [(fx= b1 #x0d) - (pariah - (cond - [(eq? ($transcoder-eol-style (codec-info-tx info)) 'none) - (string-set! str j #\return) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 1) iend cr? (fx+ bytes 1))] - [else - (string-set! str j #\newline) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 1) iend #t (fx+ bytes 1))]))] - [(fx= b1 #x0a) - (pariah - (cond - [cr? (loop j (fx+ i 1) iend #f (fx+ bytes 1))] - [else - (string-set! str j #\newline) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 1) iend cr? (fx+ bytes 1))]))] - [else - (string-set! str j (integer->char b1)) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 1) iend #f (fx+ bytes 1))])] - [else - (pariah - (cond - [(fx<= #xc2 b1 #xdf) ; two-byte encoding - (let f ([i i] [iend iend]) - (if (fx< (fx+ i 1) iend) ; have at least two bytes? - (let ([b2 (bytevector-u8-ref bv (fx+ i 1))]) - (if (fx= (fxsrl b2 6) #b10) ; second byte a continuation byte? - (let ([x (fxlogor (fxsll (fxlogand b1 #b11111) 6) (fxlogand b2 #b111111))] - [i (fx+ i 2)]) - (cond - [(fx= x #x85) ; NEL - (cond - [cr? (loop j i iend #f (fx+ bytes 2))] - [else - (string-set! str j - (if (eq? ($transcoder-eol-style (codec-info-tx info)) 'none) - (integer->char #x85) - #\newline)) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) i iend cr? (fx+ bytes 2))])] - [else - (string-set! str j (integer->char x)) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) i iend #f (fx+ bytes 2))])) - ; second byte is not a continuation byte - (let ([j (decode-error j (fx+ i 1) iend bytes b1)]) - (loop j (fx+ i 1) iend #f (fx+ bytes 1))))) - ; have only one byte - (begin - (bytevector-u8-set! bv 0 b1) - (let ([i 0] [iend 1]) - (let ([n (get-some-maybe-nb who bp bv iend ifready?)]) - (cond - [(eof-object? n) (decode-eof-error j i iend bytes)] - [(fx= n 0) (return (fx- j start) i iend cr? bytes info)] - [else (f i (fx+ iend n))]))))))] - [(fx<= #xe0 b1 #xef) ; three-byte encoding - (let f ([i i] [iend iend]) - (if (fx< (fx+ i 1) iend) ; have at least two bytes? - (let ([b2 (bytevector-u8-ref bv (fx+ i 1))]) - (if (fx= (fxsrl b2 6) #b10) ; second byte a continuation byte? - (if (fx< (fx+ i 2) iend) ; have at least three bytes? - (let ([b3 (bytevector-u8-ref bv (fx+ i 2))]) - (if (fx= (fxsrl b3 6) #b10) ; third byte a continuation byte? - (let ([x (fxlogor - (fxsll (fxlogand b1 #b1111) 12) - (fxsll (fxlogand b2 #b111111) 6) - (fxlogand b3 #b111111))] - [i (fx+ i 3)]) - (cond - [(and (fx= x #xfeff) (fx= bytes 0) (codec-info-bom info)) - (loop j i iend #f (fx+ bytes 3))] - [(and (fx>= x #x800) (not (fx<= #xd800 x #xdfff))) - (string-set! str j - (if (and (fx= x #x2028) ; LS - (not (eq? ($transcoder-eol-style (codec-info-tx info)) 'none))) - #\newline - (integer->char x))) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) i iend #f (fx+ bytes 3))] - [else - (let ([j (decode-error j i iend bytes b1 b2 b3)]) - (loop j i iend #f (fx+ bytes 3)))])) - ; third byte is not a continuation byte - (let ([j (decode-error j (fx+ i 2) iend bytes b1 b2)]) - (loop j (fx+ i 2) iend #f (fx+ bytes 2))))) - ; have only two bytes - (begin - (bytevector-u8-set! bv 0 b1) - (bytevector-u8-set! bv 1 b2) - (let ([i 0] [iend 2]) - (let ([n (get-some-maybe-nb who bp bv iend ifready?)]) - (cond - [(eof-object? n) (decode-eof-error j i iend bytes)] - [(fx= n 0) (return (fx- j start) i iend cr? bytes info)] - [else (f i (fx+ iend n))]))))) - ; second byte is not a continuation byte - (let ([j (decode-error j (fx+ i 1) iend bytes b1)]) - (loop j (fx+ i 1) iend #f (fx+ bytes 1))))) - ; have only one byte - (begin - (bytevector-u8-set! bv 0 b1) - (let ([i 0] [iend 1]) - (let ([n (get-some-maybe-nb who bp bv iend ifready?)]) - (cond - [(eof-object? n) (decode-eof-error j i iend bytes)] - [(fx= n 0) (return (fx- j start) i iend cr? bytes info)] - [else (f i (fx+ iend n))]))))))] - [(fx<= #xf0 b1 #xf4) ; four-byte encoding - (let f ([i i] [iend iend]) - (if (fx< (fx+ i 1) iend) ; have at least two bytes? - (let ([b2 (bytevector-u8-ref bv (fx+ i 1))]) - (if (fx= (fxsrl b2 6) #b10) ; second byte a continuation byte? - (if (fx< (fx+ i 2) iend) ; have at least three bytes? - (let ([b3 (bytevector-u8-ref bv (fx+ i 2))]) - (if (fx= (fxsrl b3 6) #b10) ; third byte a continuation byte? - (if (fx< (fx+ i 3) iend) ; have at least four bytes? - (let ([b4 (bytevector-u8-ref bv (fx+ i 3))]) - (if (fx= (fxsrl b4 6) #b10) ; fourth byte a continuation byte? - (let ([x (fxlogor - (fxsll (fxlogand b1 #b111) 18) - (fxsll (fxlogand b2 #b111111) 12) - (fxsll (fxlogand b3 #b111111) 6) - (fxlogand b4 #b111111))] - [i (fx+ i 4)]) - (cond - [(fx<= #x10000 x #x10ffff) - (string-set! str j (integer->char x)) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) i iend #f (fx+ bytes 4))] - [else - (let ([j (decode-error j i iend bytes b1 b2 b3)]) - (loop j i iend #f (fx+ bytes 3)))])) - ; fourth byte is not a continuation byte - (let ([j (decode-error j (fx+ i 3) iend bytes b1 b2 b3)]) - (loop j (fx+ i 3) iend #f (fx+ bytes 3))))) - ; have only three bytes - (begin - (bytevector-u8-set! bv 0 b1) - (bytevector-u8-set! bv 1 b2) - (bytevector-u8-set! bv 2 b3) - (let ([i 0] [iend 3]) - (let ([n (get-some-maybe-nb who bp bv iend ifready?)]) - (cond - [(eof-object? n) (decode-eof-error j i iend bytes)] - [(fx= n 0) (return (fx- j start) i iend cr? bytes info)] - [else (f i (fx+ iend n))]))))) - ; third byte is not a continuation byte - (let ([j (decode-error j (fx+ i 2) iend bytes b1 b2)]) - (loop j (fx+ i 2) iend #f (fx+ bytes 2))))) - ; have only two bytes - (begin - (bytevector-u8-set! bv 0 b1) - (bytevector-u8-set! bv 1 b2) - (let ([i 0] [iend 2]) - (let ([n (get-some-maybe-nb who bp bv iend ifready?)]) - (cond - [(eof-object? n) (decode-eof-error j i iend bytes)] - [(fx= n 0) (return (fx- j start) i iend cr? bytes info)] - [else (f i (fx+ iend n))]))))) - ; second byte is not a continuation byte - (let ([j (decode-error j (fx+ i 1) iend bytes b1)]) - (loop j (fx+ i 1) iend #f (fx+ bytes 1))))) - ; have only one byte - (begin - (bytevector-u8-set! bv 0 b1) - (let ([i 0] [iend 1]) - (let ([n (get-some-maybe-nb who bp bv iend ifready?)]) - (cond - [(eof-object? n) (decode-eof-error j i iend bytes)] - [(fx= n 0) (return (fx- j start) i iend cr? bytes info)] - [else (f i (fx+ iend n))]))))))] - [else - (let ([j (decode-error j (fx+ i 1) iend bytes b1)]) - (loop j (fx+ i 1) iend #f (fx+ bytes 1)))]))]))]))))))) - - (define utf-8-encode - (let () - (define (return ans o info) - (codec-info-next-set! info o) - ans) - (define (write-two-byte bv o x) - (bytevector-u8-set! bv o (fxlogor #b11000000 (fxsrl x 6))) - (bytevector-u8-set! bv (fx+ o 1) (fxlogor #b10000000 (fxlogand x #b111111)))) - (define (write-three-byte bv o x) - (bytevector-u8-set! bv o (fxlogor #b11100000 (fxsrl x 12))) - (bytevector-u8-set! bv (fx+ o 1) (fxlogor #b10000000 (fxlogand (fxsrl x 6) #b111111))) - (bytevector-u8-set! bv (fx+ o 2) (fxlogor #b10000000 (fxlogand x #b111111)))) - (lambda (who tp str start count) - (let ([info ($port-info tp)]) - (codec-info-bom-set! info #f) - (let ([bp (codec-info-bp info)] - [bv (codec-info-bv info)] - [jend (fx+ start count)]) - (let loop ([j start] [o (codec-info-next info)]) - (cond - [(fx= j jend) (return count o info)] - [(fx= o codec-buffer-length) - (let ([o (flush-buffer who bp bv 0 o)]) - (if (fx= o codec-buffer-length) - (return (fx- j start) o info) - (loop j o)))] - [else - (let ([x (char->integer (string-ref str j))]) - (cond - [(fx= x #x0a) - (let ([eol-style ($transcoder-eol-style (codec-info-tx info))]) - (case eol-style - [(lf none) - (bytevector-u8-set! bv o #x0a) - (loop (fx+ j 1) (fx+ o 1))] - [(cr) - (bytevector-u8-set! bv o #x0d) - (loop (fx+ j 1) (fx+ o 1))] - [(crlf nel) - (let f ([o o]) - (if (fx< o (fx- codec-buffer-length 1)) - (begin - (case eol-style - [(crlf) - (bytevector-u8-set! bv o #x0d) - (bytevector-u8-set! bv (fx+ o 1) #x0a)] - [else (write-two-byte bv o #x85)]) - (loop (fx+ j 1) (fx+ o 2))) - (let ([new-o (flush-buffer who bp bv 0 o)]) - (if (fx= new-o o) - (return (fx- j start) o info) - (f new-o)))))] - [(crnel ls) - (let f ([o o]) - (if (fx< o (fx- codec-buffer-length 2)) - (begin - (case eol-style - [(crnel) - (bytevector-u8-set! bv o #x0d) - (write-two-byte bv (fx+ o 1) #x85)] - [else (write-three-byte bv o #x2028)]) - (loop (fx+ j 1) (fx+ o 3))) - (let ([new-o (flush-buffer who bp bv 0 o)]) - (if (fx= new-o o) - (return (fx- j start) o info) - (f new-o)))))] - [else ($oops who "unrecognized eol style ~s" eol-style)]))] - [(fx<= x #x7f) ; one-byte encoding - (bytevector-u8-set! bv o x) - (loop (fx+ j 1) (fx+ o 1))] - [(fx<= x #x7ff) ; two-byte encoding - (let f ([o o]) - (if (fx< o (fx- codec-buffer-length 1)) - (begin - (write-two-byte bv o x) - (loop (fx+ j 1) (fx+ o 2))) - (let ([new-o (flush-buffer who bp bv 0 o)]) - (if (fx= new-o o) - (return (fx- j start) o info) - (f new-o)))))] - [(fx<= x #xffff) ; three-byte encoding - (let f ([o o]) - (if (fx< o (fx- codec-buffer-length 2)) - (begin - (write-three-byte bv o x) - (loop (fx+ j 1) (fx+ o 3))) - (let ([new-o (flush-buffer who bp bv 0 o)]) - (if (fx= new-o o) - (return (fx- j start) o info) - (f new-o)))))] - [else ; four-byte encoding - (let f ([o o]) - (if (fx< o (fx- codec-buffer-length 3)) - (begin - (bytevector-u8-set! bv o (fxlogor #b11110000 (fxsrl x 18))) - (bytevector-u8-set! bv (fx+ o 1) (fxlogor #b10000000 (fxlogand (fxsrl x 12) #b111111))) - (bytevector-u8-set! bv (fx+ o 2) (fxlogor #b10000000 (fxlogand (fxsrl x 6) #b111111))) - (bytevector-u8-set! bv (fx+ o 3) (fxlogor #b10000000 (fxlogand x #b111111))) - (loop (fx+ j 1) (fx+ o 4))) - (let ([new-o (flush-buffer who bp bv 0 o)]) - (if (fx= new-o o) - (return (fx- j start) o info) - (f new-o)))))]))]))))))) - - (set-who! utf-8-codec - (let () - (define codec - (make-codec - [name "utf-8"] - [make-info - (lambda (who tx bp bv) - (make-codec-info tx bp bv 0 0 - (and (input-port? bp) (make-fxvector (bytevector-length bv))) - 0 #f #t #f #f - utf-8-decode utf-8-encode (lambda (info) #f)))])) - (lambda () codec)))) - - (let () - (define utf-16-decode - (let () - (define (err who tp info i iend bytes b . b*) - (codec-info-bom-set! info #f) - (codec-info-next-set! info i) - (codec-info-iend-set! info iend) - (codec-info-ibytes-set! info (fx+ bytes 1 (length b*))) - (codec-info-icr-set! info #f) - (decode-oops who tp "invalid utf-16 encoding #x~2,'0x~{, ~a~}" b - (map (lambda (b) (if (eof-object? b) "#!eof" (format "#x~2,'0x" b))) b*))) - (define (eof-err who tp info i iend bytes) - (unless (fx= bytes 0) (codec-info-bom-set! info #f)) - (codec-info-next-set! info iend) - (codec-info-iend-set! info iend) - (codec-info-ibytes-set! info (fx+ bytes (fx- iend i))) - (codec-info-icr-set! info #f) - (decode-oops who tp "unexpected end-of-file reading two-word utf-16 encoding")) - (define (return ans i iend cr? bytes info) - (unless (fx= bytes 0) (codec-info-bom-set! info #f)) - (codec-info-next-set! info i) - (codec-info-iend-set! info iend) - (codec-info-ibytes-set! info bytes) - (codec-info-icr-set! info cr?) - ans) - (lambda (who tp str start count ifready?) - (let ([info ($port-info tp)]) - (let ([bp (codec-info-bp info)] - [ioffsets (and (eq? str (textual-port-input-buffer tp)) (codec-info-ioffsets info))] - [bv (codec-info-bv info)] - [jend (fx+ start count)]) - (define-syntax decode-error - (syntax-rules () - [(_ j i iend bytes b1 b2 ...) - (case ($transcoder-error-handling-mode (codec-info-tx info)) - [(ignore) j] - [(replace) - (string-set! str j #\xfffd) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (fx+ j 1)] - [else (err who tp info i iend bytes b1 b2 ...)])])) - (define-syntax decode-eof-error - (syntax-rules () - [(_ j i iend bytes) - (case ($transcoder-error-handling-mode (codec-info-tx info)) - [(ignore) (return #!eof iend iend #f (fx+ bytes (fx- iend i)) info)] - [(replace) - (string-set! str j #\xfffd) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (return (fx- (fx+ j 1) start) iend iend #f (fx+ bytes (fx- iend i)) info)] - [else (eof-err who tp info i iend bytes)])])) - (let loop ([j start] - [i (codec-info-next info)] - [iend (codec-info-iend info)] - [cr? (codec-info-icr info)] - [bytes 0]) - (cond - [(fx= j jend) (return count i iend cr? bytes info)] - [(fx= i iend) - (if (fx= j start) - (let ([n (get-some-maybe-nb who bp bv 0 ifready?)]) - (cond - [(eof-object? n) (return #!eof 0 0 #f bytes info)] - [(fx= n 0) (return 0 0 0 cr? bytes info)] - [else (loop j 0 n cr? bytes)])) - ; don't try to read in this case to avoid dealing with eof - (return (fx- j start) i iend cr? bytes info))] - [(fx= i (fx- iend 1)) - (bytevector-u8-set! bv 0 (bytevector-u8-ref bv i)) - (let ([n (get-some-maybe-nb who bp bv 1 ifready?)]) - (cond - [(eof-object? n) (decode-eof-error j 0 1 bytes)] - [(fx= n 0) (return (fx- j start) 0 1 cr? bytes info)] - [else (loop j 0 (fx+ n 1) cr? bytes)]))] - [else - (let ([b1 (bytevector-u8-ref bv i)] - [b2 (bytevector-u8-ref bv (fx+ i 1))]) - (let ([w1 (if (codec-info-big info) - (fxlogor (fxsll b1 8) b2) - (fxlogor (fxsll b2 8) b1))]) - (cond - [(and (fx= w1 #xfeff) (fx= i 0) (codec-info-bom info)) - (when (and (port-has-port-position? bp) - (guard (c [#t #f]) - (let ([n (port-position bp)]) - (eq? (- n iend) 0)))) - (codec-info-zbom-set! info #t)) - (loop j (fx+ i 2) iend cr? (fx+ bytes 2))] - [(and (fx= w1 #xfffe) (fx= i 0) (codec-info-bom info)) - (when (and (port-has-port-position? bp) - (guard (c [#t #f]) - (let ([n (port-position bp)]) - (eq? (- n iend) 0)))) - (codec-info-zbom-set! info #t)) - (codec-info-big-set! info (not (codec-info-big info))) - (loop j (fx+ i 2) iend cr? (fx+ bytes 2))] - [(fx<= #xD800 w1 #xDBFF) ; two-word encoding - (cond - [(fx<= i (fx- iend 4)) - (let ([b3 (bytevector-u8-ref bv (fx+ i 2))] - [b4 (bytevector-u8-ref bv (fx+ i 3))]) - (let ([w2 (if (codec-info-big info) - (fxlogor (fxsll b3 8) b4) - (fxlogor (fxsll b4 8) b3))]) - (cond - [(fx<= #xDC00 w2 #xDFFF) ; valid encoding - (string-set! str j - (integer->char - (fx+ (fxlogor (fxsll (fx- w1 #xD800) 10) (fx- w2 #xDC00)) - #x10000))) - (loop (fx+ j 1) (fx+ i 4) iend #f (fx+ bytes 4))] - [else - (let ([i (fx+ i 4)]) - (let ([j (decode-error j i iend bytes b1 b2 b3 b4)]) - (loop j i iend #f (fx+ bytes 4))))])))] - [(fx= i (fx- iend 2)) - (bytevector-u8-set! bv 0 b1) - (bytevector-u8-set! bv 1 b2) - (let ([n (get-some-maybe-nb who bp bv 2 ifready?)]) - (cond - [(eof-object? n) (decode-eof-error j 0 2 bytes)] - [(fx= n 0) (return (fx- j start) 0 2 cr? bytes info)] - [else (loop j 0 (fx+ n 2) cr? bytes)]))] - [else ; must have three bytes of the four we need - (bytevector-u8-set! bv 0 b1) - (bytevector-u8-set! bv 1 b2) - (bytevector-u8-set! bv 2 (bytevector-u8-ref bv (fx+ i 2))) - (let ([n (get-some-maybe-nb who bp bv 3 ifready?)]) - (cond - [(eof-object? n) (decode-eof-error j 0 3 bytes)] - [(fx= n 0) (return (fx- j start) 0 3 cr? bytes info)] - [else (loop j 0 (fx+ n 3) cr? bytes)]))])] - [(fx<= #xDC00 w1 #xDFFF) ; bogus encoding - (let ([i (fx+ i 2)]) - (let ([j (decode-error j i iend bytes b1 b2)]) - (loop j i iend #f (fx+ bytes 2))))] - [(fx= w1 #x0d) - (cond - [(eq? ($transcoder-eol-style (codec-info-tx info)) 'none) - (string-set! str j #\return) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 2) iend cr? (fx+ bytes 2))] - [else - (string-set! str j #\newline) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 2) iend #t (fx+ bytes 2))])] - [(fx= w1 #x0a) ; LF - (cond - [cr? (loop j (fx+ i 2) iend #f (fx+ bytes 2))] - [else - (string-set! str j #\newline) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 2) iend cr? (fx+ bytes 2))])] - [(fx= w1 #x85) ; NEL - (cond - [cr? (loop j (fx+ i 2) iend #f (fx+ bytes 2))] - [else - (string-set! str j - (if (eq? ($transcoder-eol-style (codec-info-tx info)) 'none) - (integer->char w1) - #\newline)) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 2) iend cr? (fx+ bytes 2))])] - [(fx= w1 #x2028) ; LS - (string-set! str j - (if (eq? ($transcoder-eol-style (codec-info-tx info)) 'none) - (integer->char w1) - #\newline)) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 2) iend #f (fx+ bytes 2))] - [else - (string-set! str j (integer->char w1)) - (when ioffsets (fxvector-set! ioffsets j bytes)) - (loop (fx+ j 1) (fx+ i 2) iend #f (fx+ bytes 2))])))]))))))) - - (define utf-16-encode - (let () - (define (return ans o info) - (codec-info-next-set! info o) - ans) - (lambda (who tp str start count) - (let ([info ($port-info tp)]) - (let ([bp (codec-info-bp info)] - [bv (codec-info-bv info)] - [jend (fx+ start count)]) - (when (codec-info-bom info) - (codec-info-bom-set! info #f) - (when (and (port-has-port-position? bp) - (guard (c [#t #f]) - (eq? (port-position bp) 0))) - (codec-info-zbom-set! info #t)) - (call-port-handler put-some who bp - (if (codec-info-big info) #vu8(#xfe #xff) #vu8(#xff #xfe)) - 0 2)) - (let loop ([j start] [o (codec-info-next info)]) - (cond - [(fx= j jend) (return count o info)] - [(fx>= o (fx- codec-buffer-length 1)) - (let ([new-o (flush-buffer who bp bv 0 o)]) - (if (fx= new-o o) - (return (fx- j start) o info) - (loop j new-o)))] - [else - (let ([x (char->integer (string-ref str j))]) - (cond - [(fx= x #x0a) - (let ([eol-style ($transcoder-eol-style (codec-info-tx info))]) - (case eol-style - [(lf none) - (cond - [(codec-info-big info) - (bytevector-u8-set! bv o #x0) - (bytevector-u8-set! bv (fx+ o 1) #x0a)] - [else - (bytevector-u8-set! bv (fx+ o 1) #x0) - (bytevector-u8-set! bv o #x0a)]) - (loop (fx+ j 1) (fx+ o 2))] - [(cr) - (cond - [(codec-info-big info) - (bytevector-u8-set! bv o #x0) - (bytevector-u8-set! bv (fx+ o 1) #x0d)] - [else - (bytevector-u8-set! bv (fx+ o 1) #x0) - (bytevector-u8-set! bv o #x0d)]) - (loop (fx+ j 1) (fx+ o 2))] - [(nel) - (cond - [(codec-info-big info) - (bytevector-u8-set! bv o #x0) - (bytevector-u8-set! bv (fx+ o 1) #x85)] - [else - (bytevector-u8-set! bv (fx+ o 1) #x0) - (bytevector-u8-set! bv o #x85)]) - (loop (fx+ j 1) (fx+ o 2))] - [(ls) - (cond - [(codec-info-big info) - (bytevector-u8-set! bv o #x20) - (bytevector-u8-set! bv (fx+ o 1) #x28)] - [else - (bytevector-u8-set! bv (fx+ o 1) #x20) - (bytevector-u8-set! bv o #x28)]) - (loop (fx+ j 1) (fx+ o 2))] - [(crlf crnel) - (if (fx< o (fx- codec-buffer-length 3)) - (begin - (cond - [(codec-info-big info) - (bytevector-u8-set! bv o #x0) - (bytevector-u8-set! bv (fx+ o 1) #x0d) - (bytevector-u8-set! bv (fx+ o 2) #x0) - (bytevector-u8-set! bv (fx+ o 3) - (case eol-style [(crlf) #x0a] [(crnel) #x85]))] - [else - (bytevector-u8-set! bv (fx+ o 1) #x0) - (bytevector-u8-set! bv o #x0d) - (bytevector-u8-set! bv (fx+ o 3) #x0) - (bytevector-u8-set! bv (fx+ o 2) - (case eol-style [(crlf) #x0a] [(crnel) #x85]))]) - (loop (fx+ j 1) (fx+ o 4))) - (let ([new-o (flush-buffer who bp bv 0 o)]) - (if (fx= new-o o) - (return (fx- j start) o info) - (loop j new-o))))] - [else ($oops who "unrecognized eol style ~s" eol-style)]))] - [(fx<= x #xffff) ; two-byte encoding - (cond - [(codec-info-big info) - (bytevector-u8-set! bv o (fxsrl x 8)) - (bytevector-u8-set! bv (fx+ o 1) (fxand x #xff))] - [else - (bytevector-u8-set! bv (fx+ o 1) (fxsrl x 8)) - (bytevector-u8-set! bv o (fxand x #xff))]) - (loop (fx+ j 1) (fx+ o 2))] - [else ; four-byte encoding - (if (fx< o (fx- codec-buffer-length 3)) - (let ([x (fx- x #x10000)]) - (let ([w1 (fxior #xd800 (fxsrl x 10))] - [w2 (fxior #xdc00 (fxand x #x3ff))]) - (cond - [(codec-info-big info) - (bytevector-u8-set! bv o (fxsrl w1 8)) - (bytevector-u8-set! bv (fx+ o 1) (fxand w1 #xff)) - (bytevector-u8-set! bv (fx+ o 2) (fxsrl w2 8)) - (bytevector-u8-set! bv (fx+ o 3) (fxand w2 #xff))] - [else - (bytevector-u8-set! bv (fx+ o 1) (fxsrl w1 8)) - (bytevector-u8-set! bv o (fxand w1 #xff)) - (bytevector-u8-set! bv (fx+ o 3) (fxsrl w2 8)) - (bytevector-u8-set! bv (fx+ o 2) (fxand w2 #xff))]) - (loop (fx+ j 1) (fx+ o 4)))) - (let ([new-o (flush-buffer who bp bv 0 o)]) - (if (fx= new-o o) - (return (fx- j start) o info) - (loop j new-o))))]))]))))))) - - (define make-utf-16-codec - (lambda (bom big) - (make-codec - [name "utf-16"] - [make-info - (lambda (who tx bp bv) - (make-codec-info tx bp bv 0 0 - (and (input-port? bp) (make-fxvector (bytevector-length bv))) - 0 #f bom #f big - utf-16-decode utf-16-encode (lambda (info) #f)))]))) - - (let ([codec-bom-be (make-utf-16-codec #t #t)] - [codec-bom-le (make-utf-16-codec #t #f)]) - (set-who! #(r6rs: utf-16-codec) - (lambda () codec-bom-be)) - (set-who! utf-16-codec - (case-lambda - [() codec-bom-be] - [(eness) - (unless (memq eness '(big little)) ($oops who "invalid endianness ~s" eness)) - (if (eq? eness 'big) codec-bom-be codec-bom-le)]))) - - (set-who! utf-16le-codec - (let ([codec (make-utf-16-codec #f #f)]) - (lambda () codec))) - - (set-who! utf-16be-codec - (let ([codec (make-utf-16-codec #f #t)]) - (lambda () codec)))) - - (when-feature iconv - (let () - (define-record-type iconv-info - (parent codec-info) - (nongenerative) - (opaque #t) - (fields decode-desc encode-desc)) - - (define $iconv-open (foreign-procedure "(cs)s_iconv_open" (string string) ptr)) - (define $iconv-close (foreign-procedure "(cs)s_iconv_close" (uptr) void)) - (define $iconv-from-string (foreign-procedure "(cs)s_iconv_from_string" (uptr ptr uptr uptr ptr uptr uptr) ptr)) - (define $iconv-to-string (foreign-procedure "(cs)s_iconv_to_string" (uptr ptr uptr uptr ptr uptr uptr) ptr)) - - (define iconv-decode - (let () - (define (err who tp info i iend bv) - (codec-info-next-set! info i) - (codec-info-iend-set! info iend) - (codec-info-icr-set! info #f) - (let ([ls (let f ([k 4] [i i]) - (if (fx= k 0) - (list "etc") - (if (fx= i iend) - (list "#!eof") - (cons (format "#x~2,'0x" (bytevector-u8-ref bv i)) - (f (fx- k 1) (fx+ i 1))))))]) - (decode-oops who tp "decoding failed for byte sequence ~a~{, ~a~}" (car ls) (cdr ls)))) - (define (return-count str start count i iend info) - (let ([eol-style ($transcoder-eol-style (codec-info-tx info))]) - (if (eq? eol-style 'none) - (return count i iend info) - (let ([end (fx+ start count)]) - (let loop ([jold start] [jnew start] [cr? (codec-info-icr info)]) - (if (fx= jold end) - (return/cr (fx- jnew start) i iend cr? info) - (let ([c (string-ref str jold)]) - (case c - [(#\nel #\newline) - (if cr? - (loop (fx+ jold 1) jnew #f) - (begin - (string-set! str jnew #\newline) - (loop (fx+ jold 1) (fx+ jnew 1) #f)))] - [(#\return) - (string-set! str jnew #\newline) - (loop (fx+ jold 1) (fx+ jnew 1) #t)] - [(#\ls) - (string-set! str jnew #\newline) - (loop (fx+ jold 1) (fx+ jnew 1) #f)] - [else - (string-set! str jnew c) - (loop (fx+ jold 1) (fx+ jnew 1) #f)])))))))) - (define (return/cr ans i iend cr? info) - (codec-info-icr-set! info cr?) - (return ans i iend info)) - (define (return ans i iend info) - (codec-info-next-set! info i) - (codec-info-iend-set! info iend) - ans) - (lambda (who tp str start count ifready?) - (let ([info ($port-info tp)]) - (let ([bp (codec-info-bp info)] - [bv (codec-info-bv info)] - [jend (fx+ start count)]) - (let loop ([j start] - [i (codec-info-next info)] - [iend (codec-info-iend info)]) - (cond - [(fx= j jend) (return-count str start count i iend info)] - [(fx= i iend) - (if (fx= j start) - (let ([n (get-some-maybe-nb who bp bv 0 ifready?)]) - (cond - [(eof-object? n) (return/cr #!eof i iend #f info)] - [(fx= n 0) (return 0 i iend info)] - [else (loop j 0 n)])) - ; don't try to read in this case to avoid dealing with eof - (return-count str start (fx- j start) i iend info))] - [else - (let ([newi.newj ($iconv-to-string (iconv-info-decode-desc info) bv i iend str j jend)]) - (cond - [(pair? newi.newj) (loop (cdr newi.newj) (car newi.newj) iend)] - ; one of the following presumably happened: - ; - too few input bytes to make progress - ; - invalid input sequence found - ; assuming problem can't have been too little output space since - ; j != jend implies enough room for at least one character - [(or (eq? newi.newj (constant SICONV-INVALID)) - ; assuming bv is large enough to hold any valid encoding sequence - (and (eq? newi.newj (constant SICONV-DUNNO)) - (and (fx= i 0) (fx= iend (bytevector-length bv))))) - (case ($transcoder-error-handling-mode (codec-info-tx info)) - [(ignore) (loop j (fx+ i 1) iend)] - [(replace) - (string-set! str j #\xfffd) - (loop (fx+ j 1) (fx+ i 1) iend)] - [else (err who tp info i iend bv)])] - [else - ; try again with more bytes - (unless (fx= i 0) (bytevector-copy! bv i bv 0 (fx- iend i))) - (let ([i 0] [iend (fx- iend i)]) - (let ([n (get-some-maybe-nb who bp bv iend ifready?)]) - (cond - [(eof-object? n) - (set-port-eof! bp #t) - (case ($transcoder-error-handling-mode (codec-info-tx info)) - [(ignore) (loop j (fx+ i 1) iend)] - [(replace) - (string-set! str j #\xfffd) - (loop (fx+ j 1) (fx+ i 1) iend)] - [else (err who tp info i iend bv)])] - [(fx= n 0) (return 0 i iend info)] - [else (loop j 0 (fx+ iend n))])))]))]))))))) - - (define iconv-encode - (let () - (define (return ans o info) - (codec-info-next-set! info o) - ans) - (define (do-iconv who info str j jend bv o) - (let ([eol-style ($transcoder-eol-style (codec-info-tx info))] - [desc (iconv-info-encode-desc info)]) - (cond - [(memq eol-style '(none lf)) - ($iconv-from-string desc str j jend bv o codec-buffer-length)] - [(eqv? (string-ref str j) #\newline) - (let () - (define (iconv-newline s k) - (let ([newj.newo ($iconv-from-string desc s 0 k bv o codec-buffer-length)]) - (if (pair? newj.newo) - (if (fx= (car newj.newo) k) - (cons (fx+ j 1) (cdr newj.newo)) - (constant SICONV-NOROOM)) - newj.newo))) - (case eol-style - [(cr) (iconv-newline "\r" 1)] - [(nel) (iconv-newline "\x85;" 1)] - [(ls) (iconv-newline "\x2028;" 1)] - [(crlf) (iconv-newline "\r\n" 2)] - [(crnel) (iconv-newline "\r\x85;" 2)] - [else ($oops who "unrecognized eol style ~s" eol-style)]))] - [else - (do ([k (fx+ j 1) (fx+ k 1)]) - ((or (fx= k jend) (eqv? (string-ref str k) #\newline)) - ($iconv-from-string desc str j k bv o codec-buffer-length)))]))) - (lambda (who tp str start count) - (let ([info ($port-info tp)]) - (let ([bp (codec-info-bp info)] - [bv (codec-info-bv info)] - [jend (fx+ start count)]) - (let loop ([j start] [o (codec-info-next info)]) - (cond - [(fx= j jend) (return count o info)] - [(fx= o codec-buffer-length) - (let ([o (flush-buffer who bp bv 0 o)]) - (if (fx= o codec-buffer-length) - (return (fx- j start) o info) - (loop j o)))] - [else - (let ([newj.newo (do-iconv who info str j jend bv o)]) - (cond - [(pair? newj.newo) (loop (car newj.newo) (cdr newj.newo))] - ; one of the following presumably happened: - ; - unencodeable character found - ; - too little output space to make progress - [(fx= o 0) ; assuming bv is large enough to hold any valid encoding sequence - (case ($transcoder-error-handling-mode (codec-info-tx info)) - [(ignore) (loop (fx+ j 1) o)] - [(replace) - ; try to write the Unicode replacement character - (let ([newj.newo ($iconv-from-string (iconv-info-encode-desc info) "\xfffd;" 0 1 bv o codec-buffer-length)]) - (if (pair? newj.newo) - (loop (fx+ j 1) (cdr newj.newo)) - ; if that failed, try to write ? - (let ([newj.newo ($iconv-from-string (iconv-info-encode-desc info) "?" 0 1 bv o codec-buffer-length)]) - (if (pair? newj.newo) - (loop (fx+ j 1) (cdr newj.newo)) - ; if even that failed, just ignore - (loop (fx+ j 1) o)))))] - [else (encode-oops who tp (string-ref str j))])] - [else (let ([newo (flush-buffer who bp bv 0 o)]) - (if (fx= newo o) - (return (fx- j start) o info) - (loop j newo)))]))]))))))) - - (define iconv-close - (lambda (info) - (cond [(iconv-info-decode-desc info) => $iconv-close]) - (cond [(iconv-info-encode-desc info) => $iconv-close]))) - - (set-who! iconv-codec - (lambda (code) - (unless (string? code) ($oops who "~s is not a string" code)) - (make-codec - [name (format "iconv ~a" code)] - [make-info - (lambda (who tx bp bv) - (define UTF-32B/LE - (constant-case native-endianness - [(little) "UTF-32LE"] - [(big) "UTF-32BE"])) - (define (iconv-open to from) - (let ([desc ($iconv-open to from)]) - (when (string? desc) ($oops who "~a" desc)) - (unless desc ($oops who "unsupported encoding ~a" code)) - desc)) - (let ([decode-desc (and (input-port? bp) (iconv-open UTF-32B/LE code))] - [encode-desc (and (output-port? bp) (iconv-open code UTF-32B/LE))]) - (make-iconv-info tx bp bv 0 0 #f 0 #f #f #f #f - (if decode-desc - iconv-decode - (lambda args ($oops who "unexpected decode from non-input-port ~s" bp))) - (if encode-desc - iconv-encode - (lambda args ($oops who "unexpected encode to non-output-port ~s" bp))) - iconv-close decode-desc encode-desc)))])))))) - - ;; eol-style in syntax.ss - (set-who! $eol-style? - (lambda (style) (and (memq style (eol-style-list)) #t))) - - (set-who! native-eol-style - (lambda () - (eol-style none))) - - ;; &i/o-decoding in exceptions.ss - ;; make-i/o-decoding-error in exceptions.ss - ;; i/o-decoding-error? in exceptions.ss - ;; &i/o-encoding in exceptions.ss - ;; make-i/o-encoding-error in exceptions.ss - ;; i/o-encoding-error? in exceptions.ss - ;; i/o-encoding-error-char in exceptions.ss - - ;; error-handling-mode in syntax.ss - (set-who! $error-handling-mode? - (lambda (mode) (and (memq mode (error-handling-mode-list)) #t))) - - (set-who! make-transcoder - (rec make-transcoder - (case-lambda - [(codec) (make-transcoder codec (native-eol-style) (error-handling-mode replace))] - [(codec eol-style) (make-transcoder codec eol-style (error-handling-mode replace))] - [(codec eol-style handling-mode) - (unless (codec? codec) ($oops who "~s is not a codec" codec)) - (unless ($eol-style? eol-style) ($oops who "~s is not an eol-style" eol-style)) - (unless ($error-handling-mode? handling-mode) - ($oops who "~s is not an error-handling-mode" handling-mode)) - ($make-transcoder codec eol-style handling-mode)]))) - - (set-who! transcoder? (lambda (x) ($transcoder? x))) - - (let ([transcoder (make-transcoder (utf-8-codec))]) - (set-who! native-transcoder (lambda () transcoder)) - (set-who! current-transcoder - ($make-thread-parameter transcoder - (lambda (tx) - (unless ($transcoder? tx) ($oops who "~s is not a transcoder" tx)) - tx)))) - - ;; transcoder-codec, transcoder-eol-style, transcoder-error-handling-mode - (let () - (define-syntax define-accessor - (syntax-rules () - [(_ name $name) - (set-who! name - (lambda (transcoder) - (unless ($transcoder? transcoder) - ($oops who "~s is not a transcoder" transcoder)) - ($name transcoder)))])) - - (define-accessor transcoder-codec $transcoder-codec) - (define-accessor transcoder-eol-style $transcoder-eol-style) - (define-accessor transcoder-error-handling-mode $transcoder-error-handling-mode)) - -;;;; 8.2.5 End-of-file object - ;; eof-object in prims.ss - ;; eof-object? in prims.ss - -;;;; 8.2.6 Input and output ports - ;; port? in prims.ss - - (set-who! port-transcoder - (lambda (port) - (unless (port? port) - ($oops who "~s is not a port" port)) - (let ([info ($port-info port)]) - (and (codec-info? info) - (codec-info-tx info))))) - - ;; textual-port? in prims.ss - ;; binary-port? in prims.ss - - ;; transcoded-port - (let () - (module (make-transcoded-port-handler) - (define read-from-codec - (lambda (who tp str start count ifready?) - (when (eq? tp $console-input-port) - (guard (c [else (void)]) (flush-output-port $console-output-port)) - (unless (eq? $console-error-port $console-output-port) - (guard (c [else (void)]) (flush-output-port $console-error-port)))) - ((codec-info-decode ($port-info tp)) who tp str start count ifready?))) - (define fill-from-codec - (lambda (who tp ifready?) - (let ([buf (textual-port-input-buffer tp)]) - (let ([n (read-from-codec who tp buf 0 (string-length buf) ifready?)]) - (if (eof-object? n) - (begin - (set-textual-port-input-size! tp 0) - (set-port-eof! tp #t)) - (set-textual-port-input-size! tp n)) - n)))) - (define write-to-codec - (lambda (who tp str start count) - (let ([n ((codec-info-encode ($port-info tp)) who tp str start count)]) - (unless (fx= n 0) - (set-port-bol! tp (eol-char? (string-ref str (fx- (fx+ start n) 1))))) - n))) - (define flush-to-codec - (case-lambda - [(who tp) (flush-to-codec who tp (textual-port-output-index tp))] - [(who tp count) - (unless (fx= count 0) - ; push the chars from port's buffer into the codec's buffer - (let loop ([start 0] [count count]) - (let ([n (write-to-codec who tp (textual-port-output-buffer tp) start count)]) - (unless (fx= n count) (loop (fx+ start n) (fx- count n))))) - (if ($port-flags-set? tp (constant port-flag-line-buffered)) - (set-textual-port-output-size! tp 0) - (set-textual-port-output-index! tp 0)))])) - (define try-flush-to-codec - (lambda (who tp) - (let ([count (textual-port-output-index tp)]) - (or (fx= count 0) - (let ([buf (textual-port-output-buffer tp)]) - (let loop ([start 0] [count count]) - (let ([n (write-to-codec who tp buf start count)]) - (cond - [(fx= n count) - (if ($port-flags-set? tp (constant port-flag-line-buffered)) - (set-textual-port-output-size! tp 0) - (set-textual-port-output-index! tp 0)) - #t] - [(fx= n 0) - (unless (fx= start 0) - (string-copy! buf start buf 0 count) - (when ($port-flags-set? tp (constant port-flag-line-buffered)) - (set-textual-port-output-size! tp count)) - (set-textual-port-output-index! tp count)) - #f] - [else (loop (fx+ start n) (fx- count n))])))))))) - (define flush-from-codec - (lambda (who tp) - ; push the bytes from codec's buffer into the binary port - (let ([info ($port-info tp)]) - (let loop ([start 0] [count (codec-info-next info)]) - (unless (fx= count 0) - (let ([n (let ([bp (codec-info-bp info)]) - (call-port-handler put-some who bp (codec-info-bv info) start count))]) - (loop (fx+ start n) (fx- count n))))) - (codec-info-next-set! info 0)))) - (define flush-from-bp - (lambda (who tp) - (let ([bp (codec-info-bp ($port-info tp))]) - (call-port-handler flush who bp)))) - (module ((make-ready-for-input $make-ready-for-input)) - (define $make-ready-for-input - (lambda (who tp) - (flush-to-codec who tp) - (flush-from-codec who tp) - (set-textual-port-output-size! tp 0) - (let ([info ($port-info tp)]) - (codec-info-next-set! info 0) - (codec-info-iend-set! info 0) - (codec-info-icr-set! info #f)) - ($set-port-flags! tp (constant port-flag-input-mode)))) - (define-syntax make-ready-for-input - (syntax-rules () - [(_ who ?tp) - (let ([tp ?tp]) - (unless ($port-flags-set? tp (constant port-flag-input-mode)) - ($make-ready-for-input who tp)))]))) - (module ((make-ready-for-output $make-ready-for-output)) - (define $make-ready-for-output - (lambda (who tp) - ; rewind if textual port or codec has something buffered. - ; if underlying binary port has something buffered, we'll let - ; the first write to the binary port take care of it - (unless (and (fx= (textual-port-input-size tp) 0) - (let ([info ($port-info tp)]) - (fx= (codec-info-next info) (codec-info-iend info)))) - (if (port-handler-port-position ($port-handler tp)) - (if (port-handler-set-port-position! ($port-handler tp)) - (let ([bp (codec-info-bp ($port-info tp))]) - (call-port-handler set-port-position! who bp - (call-port-handler port-position who tp))) - (position-warning who "cannot set position for write after read on ~s" tp)) - (position-warning who "cannot determine position for write after read on ~s" tp))) - (set-textual-port-input-size! tp 0) - (set-port-eof! tp #f) - (codec-info-next-set! ($port-info tp) 0) - (unless ($port-flags-set? tp (constant port-flag-line-buffered)) - (set-textual-port-output-size! tp (fx1- (string-length (textual-port-output-buffer tp))))) - ($reset-port-flags! tp (constant port-flag-input-mode)))) - (define-syntax make-ready-for-output - (syntax-rules () - [(_ ?who ?tp) - (let ([tp ?tp]) - (when ($port-flags-set? tp (constant port-flag-input-mode)) - ($make-ready-for-output ?who tp)))]))) - (define contains-eol-char? - (lambda (s i end) - (let f ([i i]) - (and (not (fx= i end)) - (or (eol-char? (string-ref s i)) - (f (fx+ i 1))))))) - (define transcoded-port-ready? - (lambda (who tp) - (assert-not-closed who tp) - (make-ready-for-input who tp) - (or (not (port-input-empty? tp)) - (port-flag-eof-set? tp) - (not (eq? (fill-from-codec who tp #t) 0))))) - (define transcoded-port-lookahead - (lambda (who tp) - (assert-not-closed who tp) - (make-ready-for-input who tp) - (cond - [(not (port-input-empty? tp)) - (string-ref (textual-port-input-buffer tp) - (textual-port-input-index tp))] - [(port-flag-eof-set? tp) (eof-object)] - [else (let loop () - (let ([n (fill-from-codec who tp #f)]) - (cond - [(eq? n 0) (loop)] - [(eof-object? n) n] - [else (string-ref (textual-port-input-buffer tp) 0)])))]))) - (define transcoded-port-unget - (lambda (who tp x) - (assert-not-closed who tp) - (make-ready-for-input who tp) - (when (port-flag-eof-set? tp) (unget-error who tp x)) - (if (eof-object? x) - (let () - (unless (port-input-empty? tp) (unget-error who tp x)) - (set-port-eof! tp #t)) - (let ([index (textual-port-input-index tp)]) - (when (fx= index 0) (unget-error who tp x)) - (set-textual-port-input-index! tp (fx- index 1)))))) - (define transcoded-port-get - (lambda (who tp) - (assert-not-closed who tp) - (make-ready-for-input who tp) - (cond - [(not (port-input-empty? tp)) - (let ([index (textual-port-input-index tp)]) - (set-textual-port-input-index! tp (fx1+ index)) - (string-ref (textual-port-input-buffer tp) index))] - [(port-flag-eof-set? tp) (set-port-eof! tp #f) (eof-object)] - [else (let loop () - (let ([n (fill-from-codec who tp #f)]) - (cond - [(eq? 0 n) (loop)] - [(eof-object? n) (set-port-eof! tp #f) (eof-object)] - [else - (set-textual-port-input-index! tp 1) - (string-ref (textual-port-input-buffer tp) 0)])))]))) - (define transcoded-port-get-some - (lambda (who tp str start count) - (assert-not-closed who tp) - (make-ready-for-input who tp) - (let ([port-count (textual-port-input-count tp)]) - (cond - [(not (fx= port-count 0)) - (let ([count (fxmin count port-count)] - [index (textual-port-input-index tp)]) - (string-copy! (textual-port-input-buffer tp) index str start count) - (set-textual-port-input-index! tp (fx+ index count)) - count)] - [(port-flag-eof-set? tp) (set-port-eof! tp #f) (eof-object)] - [else (read-from-codec who tp str start count #f)])))) - (define transcoded-port-clear-input - (lambda (who tp) - (assert-not-closed who tp) - (when ($port-flags-set? tp (constant port-flag-input-mode)) - ; position will be wrong after this. c'est la vie. - (set-textual-port-input-size! tp 0) - (set-port-eof! tp #f) - (let ([info ($port-info tp)]) - (codec-info-next-set! info 0) - (codec-info-iend-set! info 0) - (codec-info-icr-set! info #f) - (let ([bp (codec-info-bp info)]) - (call-port-handler clear-input who bp)))))) - (define transcoded-port-put - (lambda (who tp elt) - (assert-not-closed who tp) - (make-ready-for-output who tp) - (let ([index (textual-port-output-index tp)]) - (string-set! (textual-port-output-buffer tp) index elt) - (let ([index (fx+ index 1)]) - (cond - [(not (port-output-full? tp)) - (set-textual-port-output-index! tp index)] - [($port-flags-set? tp (constant port-flag-line-buffered)) - (cond - [(eol-char? elt) - (flush-to-codec who tp index) - (flush-from-codec who tp) - (flush-from-bp who tp)] - [(fx< (textual-port-output-size tp) (fx- (string-length (textual-port-output-buffer tp)) 1)) - (set-textual-port-output-size! tp index) - (set-textual-port-output-index! tp index)] - [else (flush-to-codec who tp index)])] - [else (flush-to-codec who tp index)]))))) - (define transcoded-port-put-some - (lambda (who tp str start count) - (assert-not-closed who tp) - (make-ready-for-output who tp) - (cond - [($port-flags-set? tp (constant port-flag-line-buffered)) - (if (contains-eol-char? str start (fx+ start count)) - (begin - ; line-buffering trumps nonblocking - (flush-to-codec who tp) - (let loop ([start start] [count count]) - (unless (fx= count 0) - (let ([n (write-to-codec who tp str start count)]) - (loop (fx+ start n) (fx- count n))))) - (flush-from-codec who tp) - (flush-from-bp who tp) - count) - (let ([buf (textual-port-output-buffer tp)] - [index (textual-port-output-index tp)]) - (if (and (fx<= count max-put-copy) (fx< (fx+ index count) (string-length buf))) - ; there's room to copy str with one character to spare - (begin - (string-copy! str start buf index count) - (let ([index (fx+ index count)]) - (set-textual-port-output-size! tp index) - (set-textual-port-output-index! tp index)) - count) - (if (try-flush-to-codec who tp) (write-to-codec who tp str start count) 0))))] - [else (if (try-flush-to-codec who tp) (write-to-codec who tp str start count) 0)]))) - (define transcoded-port-flush - (lambda (who tp) - (assert-not-closed who tp) - (make-ready-for-output who tp) - (flush-to-codec who tp) - (flush-from-codec who tp) - (flush-from-bp who tp))) - (define transcoded-port-clear-output - (lambda (who tp) - (assert-not-closed who tp) - (unless ($port-flags-set? tp (constant port-flag-input-mode)) - ; position will be wrong after this. c'est la vie. - (if ($port-flags-set? tp (constant port-flag-line-buffered)) - (set-textual-port-output-size! tp 0) - (set-textual-port-output-index! tp 0)) - (let ([info ($port-info tp)]) - (codec-info-next-set! info 0) - (let ([bp (codec-info-bp info)]) - (call-port-handler clear-output who bp)))))) - (define transcoded-port-close-port - (lambda (who tp) - (unless (port-closed? tp) - (when (output-port? tp) - (make-ready-for-output who tp) - (flush-to-codec who tp) - (flush-from-codec who tp) - (flush-from-bp who tp)) - (unless (or (eq? tp $console-input-port) ; refuse to close original console ports - (eq? tp $console-output-port) - (eq? tp $console-error-port)) - (when (output-port? tp) - (set-textual-port-output-size! tp 0)) - (when (input-port? tp) - (set-textual-port-input-size! tp 0) - (set-port-eof! tp #f)) - (let ([info ($port-info tp)]) - (close-port (codec-info-bp info)) - ((codec-info-close info) info)) - (unregister-open-file tp) - (mark-port-closed! tp))))) - (define transcoded-port-port-position - (lambda (who tp) - (assert-not-closed who tp) - (cond - [($port-flags-set? tp (constant port-flag-input-mode)) - ; (port-position bp) gives us position in bytes after characters and bytes - ; we haven't yet consumed. to get position of first unconsumed character or - ; byte, need to adjust downward by the number of bytes buffered, using - ; ioffsets to determine the byte position of the first unconsumed character - ; relative to the start of the port's buffer, ibytes to determine the total - ; number of bytes represented by the characters in the port's buffer, and - ; (- iend next) to determine the number of bytes not yet converted - ; into characters. if ioffsets is not available, the reported port-position - ; may not be accurate. - (let ([info ($port-info tp)]) - (- (call-port-handler port-position who (codec-info-bp info)) - (let ([buffered-bytes (fx- (codec-info-iend info) (codec-info-next info))]) - (cond - [(port-input-empty? tp) buffered-bytes] - [(codec-info-ioffsets info) => - (lambda (ioffsets) - (fx- (fx+ (codec-info-ibytes info) buffered-bytes) - (fxvector-ref ioffsets (textual-port-input-index tp))))] - [else - (position-warning who "cannot determine accurate position for operation on ~s" tp) - buffered-bytes]))))] - [else - (flush-to-codec who tp) - (flush-from-codec who tp) - (let ([bp (codec-info-bp ($port-info tp))]) - (call-port-handler port-position who bp))]))) - (define transcoded-port-set-port-position! - (lambda (who tp pos) - (assert-not-closed who tp) - (let ([info ($port-info tp)]) - (if ($port-flags-set? tp (constant port-flag-input-mode)) - (begin - (set-textual-port-input-size! tp 0) - (set-port-eof! tp #f) - (codec-info-next-set! info 0) - (codec-info-iend-set! info 0) - (codec-info-icr-set! info #f)) - (begin - (flush-to-codec who tp) - (flush-from-codec who tp))) - (let ([bp (codec-info-bp info)]) - (call-port-handler set-port-position! who bp - ; position past bom if known to be present at position 0 - ; if it was found or put elsewhere, all bets are off - (if (and (eq? pos 0) (codec-info-zbom info)) 2 pos)))))) - (define transcoded-port-port-length - (lambda (who tp) - (assert-not-closed who tp) - (unless ($port-flags-set? tp (constant port-flag-input-mode)) - (flush-to-codec who tp) - (flush-from-codec who tp)) - (let ([bp (codec-info-bp ($port-info tp))]) - (call-port-handler port-length who bp)))) - (define transcoded-port-set-port-length! - (lambda (who tp pos) - (assert-not-closed who tp) - (unless ($port-flags-set? tp (constant port-flag-input-mode)) - (flush-to-codec who tp) - (flush-from-codec who tp)) - (let ([bp (codec-info-bp ($port-info tp))]) - (call-port-handler set-port-length! who bp pos)))) - (define transcoded-port-port-nonblocking? - (lambda (who tp) - (assert-not-closed who tp) - (port-nonblocking? (codec-info-bp ($port-info tp))))) - (define transcoded-port-set-port-nonblocking! - (lambda (who tp b) - (assert-not-closed who tp) - (set-port-nonblocking! (codec-info-bp ($port-info tp)) b))) - (define (make-transcoded-port-handler bp) - ; could cache these, but the savings would be minimal - (make-port-handler - [ready? (and (input-port? bp) transcoded-port-ready?)] - [lookahead (and (input-port? bp) transcoded-port-lookahead)] - [unget (and (input-port? bp) transcoded-port-unget)] - [get (and (input-port? bp) transcoded-port-get)] - [get-some (and (input-port? bp) transcoded-port-get-some)] - [clear-input (and (input-port? bp) transcoded-port-clear-input)] - [put (and (output-port? bp) transcoded-port-put)] - [put-some (and (output-port? bp) transcoded-port-put-some)] - [flush (and (output-port? bp) transcoded-port-flush)] - [clear-output (and (output-port? bp) transcoded-port-clear-output)] - [close-port transcoded-port-close-port] - [port-position - (and (port-handler-port-position ($port-handler bp)) - transcoded-port-port-position)] - [set-port-position! - (and (port-handler-set-port-position! ($port-handler bp)) - transcoded-port-set-port-position!)] - [port-length - (and (port-handler-port-length ($port-handler bp)) - transcoded-port-port-length)] - [set-port-length! - (and (port-handler-set-port-length! ($port-handler bp)) - transcoded-port-set-port-length!)] - [port-nonblocking? - (and (port-handler-port-nonblocking? ($port-handler bp)) - transcoded-port-port-nonblocking?)] - [set-port-nonblocking! - (and (port-handler-set-port-nonblocking! ($port-handler bp)) - transcoded-port-set-port-nonblocking!)]))) - (set-who! transcoded-port - (lambda (bp tx) - (define-syntax copy-flag! - (syntax-rules () - [(_ from to flag) - (when ($port-flags-set? from (constant flag)) - ($set-port-flags! to (constant flag)))])) - (define (clone-port bp) - (let ([bpc ($make-textual-input/output-port "" ($port-handler bp) "" "" #f)]) - ($byte-copy! bp (constant port-type-disp) bpc (constant port-type-disp) (constant size-port)) - bpc)) - (unless (and (port? bp) (binary-port? bp)) ($oops who "~s is not a binary port" bp)) - (unless ($transcoder? tx) ($oops who "~s is not a transcoder" tx)) - (let* ([bpc (clone-port bp)] - [name (port-name bpc)] - [buffer-length (if (or ($port-flags-set? bp (constant port-flag-block-buffered)) - ($port-flags-set? bp (constant port-flag-line-buffered))) - buffered-transcoded-port-buffer-length - unbuffered-transcoded-port-buffer-length)] - [codec ($transcoder-codec tx)] - [info ((codec-make-info codec) who tx bpc (make-bytevector codec-buffer-length))] - [handler (make-transcoded-port-handler bpc)] - [tp (if (input-port? bpc) - (if (output-port? bpc) - ($make-textual-input/output-port name handler - (make-string buffer-length) - (make-string buffer-length) - info) - ($make-textual-input-port name handler - (make-string buffer-length) info)) - ($make-textual-output-port name handler - (make-string buffer-length) info))]) - (copy-flag! bpc tp port-flag-block-buffered) - (copy-flag! bpc tp port-flag-line-buffered) - (mark-port-closed! bp) - (when (input-port? bp) - (set-binary-port-input-size! bp 0) - (set-port-eof! bp #f) - (set-textual-port-input-size! tp 0)) - (when (output-port? bp) - (set-binary-port-output-size! bp 0) - (set-textual-port-output-size! tp - (if ($port-flags-set? tp (constant port-flag-line-buffered)) - 0 - (fx1- buffer-length))) - ($set-port-flags! tp (constant port-flag-bol))) - ($set-port-info! bp tp) ; back-link for bytevector-output-port extractor - (when (registered-open-file? bp) - (unregister-open-file bp) - (register-open-file tp)) - tp)))) - - (let () - (define-syntax set-who!-port-has - (lambda (x) - (syntax-case x () - [(_ name) - (with-syntax ([name (construct-name #'name "port-has-" #'name "?")] - [field (construct-name #'name "port-handler-" #'name)]) - #'(set-who! name - (lambda (p) - (unless (port? p) ($oops who "~s is not a port" p)) - (and (field ($port-handler p)) #t))))]))) - - (define-syntax set-who!-port - (lambda (x) - (syntax-case x () - [(_ name (args ...)) - (with-syntax ([field (construct-name #'name "port-handler-" #'name)]) - #'(set-who! name - (lambda (p args ...) - (unless (port? p) ($oops who "~s is not a port" p)) - (let ([op (field ($port-handler p))]) - (unless op ($oops who "~s does not support operation" p)) - (op who p args ...)))))]))) - - (set-who!-port-has port-position) - (set-who!-port port-position ()) - (set-who!-port-has set-port-position!) - (set-who!-port set-port-position! (x)) - - ;; The following are not in R6RS - (set-who!-port-has port-nonblocking?) - (set-who!-port port-nonblocking? ()) - (set-who!-port-has set-port-nonblocking!) - (set-who!-port set-port-nonblocking! (x)) - (set-who!-port-has port-length) - (set-who!-port port-length ()) - (set-who!-port-has set-port-length!) - (set-who!-port set-port-length! (x))) - - (set-who! file-position - (case-lambda - [(p) - (unless (port? p) ($oops who "~s is not a port" p)) - (let ([op (port-handler-port-position ($port-handler p))]) - (unless op ($oops who "~s does not support operation" p)) - (op who p))] - [(p pos) - (unless (port? p) ($oops who "~s is not a port" p)) - (let ([op (port-handler-set-port-position! ($port-handler p))]) - (unless op ($oops who "~s does not support operation" p)) - (op who p pos))])) - - (set-who! file-length - (lambda (p) - (unless (port? p) ($oops who "~s is not a port" p)) - (let ([op (port-handler-port-length ($port-handler p))]) - (unless op ($oops who "~s does not support operation" p)) - (op who p)))) - - ;; Not in R6RS - ;; truncate-file is set-port-length and set-port-position combined - (let () - (define (tp who port pos) - (unless (output-port? port) ($oops who "~s is not an output port" port)) - (let ([handler ($port-handler port)]) - (let ([set-len! (port-handler-set-port-length! handler)] - [set-pos! (port-handler-set-port-position! handler)]) - (unless (and set-len! set-pos!) - ($oops who "~s does not support operation" port)) - (set-len! who port pos) - (set-pos! who port pos)))) - - (set-who! truncate-port - (case-lambda - [(port) (tp who port 0)] - [(port pos) (tp who port pos)])) - - (set-who! truncate-file - (case-lambda - [(port) (tp who port 0)] - [(port pos) (tp who port pos)]))) - - (set-who! close-port - (lambda (port) - (unless (port? port) ($oops who "~s is not a port" port)) - (call-port-handler close-port who port))) - - (set-who! call-with-port - (lambda (port proc) - (unless (port? port) ($oops who "~s is not a port" port)) - (unless (procedure? proc) ($oops who "~s is not a procedure" proc)) - (call-with-values - (lambda () (proc port)) - (case-lambda - [(x) - (call-port-handler close-port who port) - x] - [args - (call-port-handler close-port who port) - (apply values args)])))) - -;;;; 8.2.7 Input ports - ;; input-port? in prims.ss - ;; port-eof? in prims.ss - - ;; Not in R6RS - (set-who! input-port-ready? - (lambda (input-port) - (unless (input-port? input-port) - ($oops who "~s is not an input port" input-port)) - (or (not (port-input-empty? input-port)) - (port-flag-eof-set? input-port) - (call-port-handler ready? who input-port)))) - - (let () - ;; open-file-input-port - (define open-binary-file-input-port - (lambda (who filename options mode) - (unless (string? filename) - ($oops who "~s is not a string" filename)) - (unless (and (enum-set? options) - (enum-set-subset? options $file-options)) - ($oops who "~s is not a file-options object" options)) - (unless (buffer-mode? mode) - ($oops who "~s is not a valid buffer mode" mode)) - (when (enum-set-subset? (file-options exclusive) options) - ($oops who "exclusive option not supported for file input ports")) - (let ([fd (critical-section ($open-input-fd filename (enum-set-subset? (file-options compressed) options)))]) - (when (pair? fd) (open-oops who filename options fd)) - (if (box? fd) ; box iff file opened with compressed option is actually gzip'd - (open-binary-fd-input-port who filename (unbox fd) #t mode #t) - (open-binary-fd-input-port who filename fd #t mode #f))))) - - (define open-binary-standard-input-port - (lambda (b-mode) - (define who 'standard-input-port) - (unless (buffer-mode? b-mode) - ($oops who "~s is not a valid buffer mode" b-mode)) - (open-binary-fd-input-port who "stdin" (make-fd 0) ($fd-regular? 0) b-mode #f))) - - (define help-open-file-input-port - (lambda (who filename options buffer-mode maybe-transcoder) - (let ([binary-port (open-binary-file-input-port who filename options buffer-mode)]) - (if maybe-transcoder - (transcoded-port binary-port maybe-transcoder) - binary-port)))) - - (set-who! port-file-compressed! - (lambda (p) - (unless (port? p) ($oops who "~s is not a port" p)) - (when (and (input-port? p) (output-port? p)) ($oops who "cannot compress input/output port ~s" p)) - (let ([bp (if (binary-port? p) - p - (let ([info ($port-info p)]) - (and (codec-info? info) (codec-info-bp info))))]) - (unless (and bp ($port-flags-set? bp (constant port-flag-file))) ($oops who "~s is not a file port" p)) - (unless ($port-flags-set? bp (constant port-flag-compressed)) - (let ([fd ($port-info bp)]) - (unless ($fd-regular? fd) ($oops who "~s is not a regular file" p)) - ; flush any uncompressed data in the output buffer - (when (output-port? p) (flush-output-port p)) - (critical-section - (let ([gzfd (if (input-port? p) - (let ([fp (port-position p)]) - ; reposition to 'unread' any compressed data in the input buffer - (set-port-position! p fp) - ($compress-input-fd fd fp)) - ($compress-output-fd fd))]) - (when (string? gzfd) ($oops who "failed for ~s: ~(~a~)" p gzfd)) - (unless (eqv? gzfd fd) ; uncompressed input port - (assert (box? gzfd)) - ($set-port-info! bp (unbox gzfd)) - ($set-port-flags! bp (constant port-flag-compressed)))))))))) - - (set-who! open-fd-input-port - (case-lambda - [(fd) - (unless (and (fixnum? fd) (fx>= fd 0)) - ($oops who "~s is not a file descriptor" fd)) - (open-binary-fd-input-port who (format "fd ~s" fd) (make-fd fd) ($fd-regular? fd) (buffer-mode block) #f)] - [(fd buffer-mode) - (unless (and (fixnum? fd) (fx>= fd 0)) - ($oops who "~s is not a file descriptor" fd)) - (unless (buffer-mode? buffer-mode) - ($oops who "~s is not a buffer mode" buffer-mode)) - (open-binary-fd-input-port who (format "fd ~s" fd) (make-fd fd) ($fd-regular? fd) buffer-mode #f)] - [(fd buffer-mode maybe-transcoder) - (unless (and (fixnum? fd) (fx>= fd 0)) - ($oops who "~s is not a file descriptor" fd)) - (unless (buffer-mode? buffer-mode) - ($oops who "~s is not a buffer mode" buffer-mode)) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (let ([binary-port (open-binary-fd-input-port who (format "fd ~s" fd) (make-fd fd) ($fd-regular? fd) buffer-mode #f)]) - (if maybe-transcoder - (transcoded-port binary-port maybe-transcoder) - binary-port))])) - - (let () - (define s-process (foreign-procedure "(cs)s_process" (string boolean) scheme-object)) - (define (subprocess-port who what fd pid b-mode maybe-transcoder) - (unless (buffer-mode? b-mode) - ($oops who "~s is not a valid buffer mode" b-mode)) - (let ([name (format "pid ~s ~a" pid what)]) - (let ([bp (if (eq? what 'stdin) - (open-binary-fd-output-port who name (make-fd fd) #f b-mode #f #f) - (open-binary-fd-input-port who name (make-fd fd) #f b-mode #f))]) - (if maybe-transcoder (transcoded-port bp maybe-transcoder) bp)))) - (set-who! process - (lambda (s) - (unless (string? s) ($oops who "~s is not a string" s)) - (apply (lambda (ifd ofd pid) - (list - (subprocess-port who 'stdout ifd pid (buffer-mode block) (current-transcoder)) - (subprocess-port who 'stdin ofd pid (buffer-mode line) (current-transcoder)) - pid)) - (s-process s #f)))) - (set-who! open-process-ports - (case-lambda - [(s) - (unless (string? s) ($oops who "~s is not a string" s)) - (apply (lambda (ifd efd ofd pid) - (values - (subprocess-port who 'stdin ofd pid (buffer-mode block) #f) - (subprocess-port who 'stdout ifd pid (buffer-mode block) #f) - (subprocess-port who 'stderr efd pid (buffer-mode block) #f) - pid)) - (s-process s #t))] - [(s b-mode) - (unless (string? s) ($oops who "~s is not a string" s)) - (apply (lambda (ifd efd ofd pid) - (values - (subprocess-port who 'stdin ofd pid b-mode #f) - (subprocess-port who 'stdout ifd pid b-mode #f) - (subprocess-port who 'stderr efd pid b-mode #f) - pid)) - (s-process s #t))] - [(s b-mode maybe-transcoder) - (unless (string? s) ($oops who "~s is not a string" s)) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (apply (lambda (ifd efd ofd pid) - (values - (subprocess-port who 'stdin ofd pid b-mode maybe-transcoder) - (subprocess-port who 'stdout ifd pid b-mode maybe-transcoder) - (subprocess-port who 'stderr efd pid b-mode maybe-transcoder) - pid)) - (s-process s #t))]))) - - (set-who! open-file-input-port - (case-lambda - [(filename) - (open-binary-file-input-port who filename (file-options) (buffer-mode block))] - [(filename options) - (open-binary-file-input-port who filename options (buffer-mode block))] - [(filename options buffer-mode) - (open-binary-file-input-port who filename options buffer-mode)] - [(filename options buffer-mode maybe-transcoder) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (help-open-file-input-port who filename options buffer-mode maybe-transcoder)])) - - (set! $open-file-input-port - (case-lambda - [(who filename) - (open-binary-file-input-port who filename (file-options) (buffer-mode block))] - [(who filename options) - (open-binary-file-input-port who filename options (buffer-mode block))] - [(who filename options buffer-mode) - (open-binary-file-input-port who filename options buffer-mode)] - [(who filename options buffer-mode maybe-transcoder) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (help-open-file-input-port who filename options buffer-mode maybe-transcoder)])) - - (set-who! standard-input-port - (case-lambda - [() (open-binary-standard-input-port (buffer-mode block))] - [(b-mode) (open-binary-standard-input-port b-mode)] - [(b-mode maybe-transcoder) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (let ([binary-port (open-binary-standard-input-port b-mode)]) - (if maybe-transcoder - (transcoded-port binary-port maybe-transcoder) - binary-port))])) - - (set-who! r6rs:standard-input-port - (rec standard-input-port - (lambda () - (open-binary-standard-input-port (buffer-mode block))))) - - ; simple i/o routines here to share helpers - (let () - (define (oif who s o) - (unless (string? s) ($oops who "~s is not a string" s)) - (let ([o (if (list? o) o (list o))]) - (let loop ([o o] [zmode #f] [bmode #f]) - (if (null? o) - (help-open-file-input-port who s - (if (eq? zmode 'compressed) (file-options compressed) (file-options)) - (if (eq? bmode 'unbuffered) (buffer-mode none) (buffer-mode block)) - (current-transcoder)) - (case (car o) - [(compressed uncompressed) - (check-option who zmode (car o)) - (loop (cdr o) (car o) bmode)] - [(buffered unbuffered) - (check-option who bmode (car o)) - (loop (cdr o) zmode (car o))] - [else ($oops who "invalid option ~s" (car o))]))))) - - (set-who! #(r6rs: open-input-file) - (lambda (s) (oif who s '()))) - - (set-who! open-input-file - (case-lambda - [(s) (oif who s '())] - [(s o) (oif who s o)])) - - (let () - (define (cwif who s f o) - (unless (procedure? f) - ($oops 'call-with-input-file "~s is not a procedure" f)) - (let ([p (oif 'call-with-input-file s o)]) - (call-with-values - (lambda () (f p)) - (lambda args (close-input-port p) (apply values args))))) - (set-who! #(r6rs: call-with-input-file) - (lambda (s f) (cwif who s f '()))) - (set-who! call-with-input-file - (case-lambda - [(s f) (cwif who s f '())] - [(s f o) (cwif who s f o)]))) - - (let () - (define (wiff who s f o) - (unless (procedure? f) - ($oops 'with-input-from-file "~s is not a procedure" f)) - (let ([p (oif 'with-input-from-file s o)]) - (call-with-values - (lambda () (parameterize ([current-input-port p]) (f))) - (lambda v (close-input-port p) (apply values v))))) - (set-who! #(r6rs: with-input-from-file) - (lambda (s f) (wiff who s f '()))) - (set-who! with-input-from-file - (case-lambda - [(s f) (wiff who s f '())] - [(s f o) (wiff who s f o)])))) - ) - - ;; open-bytevector-input-port - (let () - ;; port-info stores whether to claim it is nonblocking or not - (define $bytevector-input-handler - (make-port-handler - [ready? - (lambda (who p) - (assert-not-closed who p) - #t)] - [lookahead - (lambda (who p) - (assert-not-closed who p) - (if (port-input-empty? p) - (eof-object) - (bytevector-u8-ref (binary-port-input-buffer p) - (binary-port-input-index p))))] - [unget - (lambda (who p x) - (assert-not-closed who p) - (if (eof-object? x) - ;; We don't set port-eof b/c #!eof only comes at end anyway - (unless (port-input-empty? p) (unget-error who p x)) - (let ([index (binary-port-input-index p)]) - (when (eq? 0 index) (unget-error who p x)) - (set-binary-port-input-index! p (fx1- index)))))] - [get - (lambda (who p) - (assert-not-closed who p) - (if (port-input-empty? p) - (eof-object) - (let ([index (binary-port-input-index p)]) - (set-binary-port-input-index! p (fx1+ index)) - (bytevector-u8-ref (binary-port-input-buffer p) index))))] - [get-some - (lambda (who p bv start count) - (assert-not-closed who p) - (let ([port-count (binary-port-input-count p)]) - (if (eq? 0 port-count) - (eof-object) - (let ([index (binary-port-input-index p)] - [count (fxmin count port-count)]) - (bytevector-copy! (binary-port-input-buffer p) index - bv start count) - (set-binary-port-input-index! p (fx+ index count)) - count))))] - [clear-input - (lambda (who p) - (assert-not-closed who p))] - [put #f] - [put-some #f] - [flush #f] - [clear-output #f] - [close-port - (lambda (who p) - (unless (port-closed? p) - (mark-port-closed! p) - (set-binary-port-input-size! p 0)))] - [port-position - (lambda (who p) - (assert-not-closed who p) - (binary-port-input-index p))] - [set-port-position! - (lambda (who p x) - (assert-not-closed who p) - (unless (and (fixnum? x) (not ($fxu< (binary-port-input-size p) x))) - (if (or (and (fixnum? x) (fx>= x 0)) (and (bignum? x) (>= x 0))) - (position-oops who p x "out of range") - ($oops who "~s is not a valid position" x))) - (set-binary-port-input-index! p x))] - [port-length - (lambda (who p) - (assert-not-closed who p) - (bytevector-length (binary-port-input-buffer p)))] - [set-port-length! #f] - [port-nonblocking? - (lambda (who p) - (assert-not-closed who p) - ($port-info p))] - [set-port-nonblocking! - (lambda (who p x) - (assert-not-closed who p) - ($set-port-info! p x))])) - - (define open-binary-bytevector-input-port - (lambda (bv) - (define who 'open-bytevector-input-port) - (unless (bytevector? bv) - ($oops who "~s is not a bytevector" bv)) - (let ([p ($make-binary-input-port "bytevector" $bytevector-input-handler bv #f)]) - ($set-port-flags! p (constant port-flag-block-buffered)) - p))) - - (set-who! open-bytevector-input-port - (case-lambda - [(bv) (open-binary-bytevector-input-port bv)] - [(bv maybe-transcoder) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (let ([binary-port (open-binary-bytevector-input-port bv)]) - (if maybe-transcoder - (transcoded-port binary-port maybe-transcoder) - binary-port))])) - ) - - ;; open-string-input-port - (let () - ;; port-info stores whether to claim it is nonblocking or not - (define $string-input-handler - (make-port-handler - [ready? - (lambda (who p) - (assert-not-closed who p) - #t)] - [lookahead - (lambda (who p) - (assert-not-closed who p) - (if (port-input-empty? p) - (eof-object) - (string-ref (textual-port-input-buffer p) - (textual-port-input-index p))))] - [unget - (lambda (who p x) - (assert-not-closed who p) - (if (eof-object? x) - ;; We don't set port-eof b/c #!eof only comes at end anyway - (unless (port-input-empty? p) (unget-error who p x)) - (let ([index (textual-port-input-index p)]) - (when (eq? 0 index) (unget-error who p x)) - (set-textual-port-input-index! p (fx1- index)))))] - [get - (lambda (who p) - (assert-not-closed who p) - (if (port-input-empty? p) - (eof-object) - (let ([index (textual-port-input-index p)]) - (set-textual-port-input-index! p (fx1+ index)) - (string-ref (textual-port-input-buffer p) index))))] - [get-some - (lambda (who p st start count) - (assert-not-closed who p) - (let ([port-count (textual-port-input-count p)]) - (if (eq? 0 port-count) - (eof-object) - (let ([index (textual-port-input-index p)] - [count (fxmin count port-count)]) - (string-copy! (textual-port-input-buffer p) index - st start count) - (set-textual-port-input-index! p (fx+ index count)) - count))))] - [clear-input - (lambda (who p) - (assert-not-closed who p))] - [put #f] - [put-some #f] - [flush #f] - [clear-output #f] - [close-port - (lambda (who p) - (unless (port-closed? p) - (mark-port-closed! p) - (set-textual-port-input-size! p 0)))] - [port-position - (lambda (who p) - (assert-not-closed who p) - (textual-port-input-index p))] - [set-port-position! - (lambda (who p x) - (assert-not-closed who p) - (unless (and (fixnum? x) (not ($fxu< (textual-port-input-size p) x))) - (if (or (and (fixnum? x) (fx>= x 0)) (and (bignum? x) (>= x 0))) - (position-oops who p x "out of range") - ($oops who "~s is not a valid position" x))) - (set-textual-port-input-index! p x))] - [port-length - (lambda (who p) - (assert-not-closed who p) - (string-length (textual-port-input-buffer p)))] - [set-port-length! #f] - [port-nonblocking? - (lambda (who p) - (assert-not-closed who p) - ($port-info p))] - [set-port-nonblocking! - (lambda (who p x) - (assert-not-closed who p) - ($set-port-info! p x))])) - - (define (osip who str) - (unless (string? str) - ($oops who "~s is not a string" str)) - (let ([p ($make-textual-input-port "string" $string-input-handler str #f)]) - ($set-port-flags! p (constant port-flag-block-buffered)) - ($set-port-flags! p (constant port-flag-char-positions)) - p)) - - (set-who! open-string-input-port - (lambda (str) - (osip who str))) - - (set-who! open-input-string - (lambda (str) - (osip who str))) - ) - - ;; standard-input-port in open-binary-file-input-port section - ;; current-input-port in prims.ss - - (set-who! make-custom-binary-input-port - (lambda (id read! get-position set-position! close) - (unless (string? id) ($oops who "~s is not a string" id)) - (unless (procedure? read!) ($oops who "~s is not a procedure" read!)) - (unless (or (not get-position) (procedure? get-position)) - ($oops who "~s is not a procedure or #f" get-position)) - (unless (or (not set-position!) (procedure? set-position!)) - ($oops who "~s is not a procedure or #f" set-position!)) - (unless (or (not close) (procedure? close)) - ($oops who "~s is not a procedure or #f" close)) - (let ([handler - (make-port-handler - [ready? - (lambda (who p) - (assert-not-closed who p) - (or (not (port-input-empty? p)) - (port-flag-eof-set? p) - (read-oops who p "cannot determine ready status")))] - [lookahead - (lambda (who p) - (assert-not-closed who p) - (binary-custom-port-lookahead who p read!))] - [unget - (lambda (who p x) - (assert-not-closed who p) - (binary-custom-port-unget who p x))] - [get - (lambda (who p) - (assert-not-closed who p) - (binary-custom-port-get who p read!))] - [get-some - (lambda (who p bv start count) - (assert-not-closed who p) - (binary-custom-port-get-some who p read! bv start count))] - [clear-input - (lambda (who p) - (assert-not-closed who p) - (binary-custom-port-clear-input who p))] - [put #f] - [put-some #f] - [flush #f] - [clear-output #f] - [close-port - (lambda (who p) - (unless (port-closed? p) - (binary-custom-port-close-port who p close)))] - [port-position - (and get-position - (lambda (who p) - (assert-not-closed who p) - (binary-custom-port-port-position in who p get-position)))] - [set-port-position! - (and set-position! - (lambda (who p x) - (unless (or (and (fixnum? x) (fx>= x 0)) (and (bignum? x) (>= x 0))) - ($oops who "~s is not a valid position" x)) - (assert-not-closed who p) - (set-binary-port-input-size! p 0) ;; junk the buffer data - (set-port-eof! p #f) - (set-position! x)))] - [port-length #f] - [set-port-length! #f] - [port-nonblocking? #f] - [set-port-nonblocking! #f])]) - (let ([p ($make-binary-input-port id handler - (make-bytevector (custom-port-buffer-size)) - #f)]) - ($set-port-flags! p (constant port-flag-block-buffered)) - (set-binary-port-input-size! p 0) - p)))) - - (set-who! make-custom-textual-input-port - (lambda (id read! get-position set-position! close) - (unless (string? id) ($oops who "~s is not a string" id)) - (unless (procedure? read!) ($oops who "~s is not a procedure" read!)) - (unless (or (not get-position) (procedure? get-position)) - ($oops who "~s is not a procedure or #f" get-position)) - (unless (or (not set-position!) (procedure? set-position!)) - ($oops who "~s is not a procedure or #f" set-position!)) - (unless (or (not close) (procedure? close)) - ($oops who "~s is not a procedure or #f" close)) - (let ([handler - (make-port-handler - [ready? - (lambda (who p) - (assert-not-closed who p) - (or (not (port-input-empty? p)) - (port-flag-eof-set? p) - (read-oops who p "cannot determine ready status")))] - [lookahead - (lambda (who p) - (assert-not-closed who p) - (textual-custom-port-lookahead who p read!))] - [unget - (lambda (who p x) - (assert-not-closed who p) - (textual-custom-port-unget who p x))] - [get - (lambda (who p) - (assert-not-closed who p) - (textual-custom-port-get who p read!))] - [get-some - (lambda (who p str start count) - (assert-not-closed who p) - (textual-custom-port-get-some who p read! str start count))] - [clear-input - (lambda (who p) - (assert-not-closed who p) - (textual-custom-port-clear-input who p))] - [put #f] - [put-some #f] - [flush #f] - [clear-output #f] - [close-port - (lambda (who p) - (unless (port-closed? p) - (textual-custom-port-close-port who p close)))] - [port-position - (and get-position - (lambda (who p) - (assert-not-closed who p) - (unless (port-input-empty? p) - (position-warning who - "cannot determine accurate position after read on ~s" - p)) - (get-position)))] - [set-port-position! - (and set-position! - (lambda (who p x) - (assert-not-closed who p) - (set-textual-port-input-size! p 0) ;; junk the buffer data - (set-port-eof! p #f) - (set-position! x)))] - [port-length #f] - [set-port-length! #f] - [port-nonblocking? #f] - [set-port-nonblocking! #f])]) - (let ([p ($make-textual-input-port id handler - (make-string (custom-port-buffer-size)) - #f)]) - ($set-port-flags! p (constant port-flag-block-buffered)) - (set-textual-port-input-size! p 0) - p)))) - - -;;;; 8.2.8 Binary input - ;; get-u8 in prims.ss - ;; lookahead-u8 in prims.ss - ;; unget-u8 in prims.ss - - ;; get-bytevector! :: port * bv * start * max -> count TODO(not R6RS) - - (let () - ;; This helper handles all the looping for the following functions - (define (get-bytevector-min-max who p bv start min max) - (if (eq? 0 max) - 0 - (let ([get-some (port-handler-get-some ($port-handler p))]) - ;; Loop invariant: - ;; next = next spot to fill in the bytevector - ;; min = minimum left to read - ;; max = maximum left to read - (let loop ([next start] - [min min] - [max max]) - (let ([n (get-some who p bv next max)]) - (if (eof-object? n) - (if (eq? start next) - (eof-object) ;; We couldn't even read one byte - (begin ;; Got some but got #!eof before full - (call-port-handler unget who p (eof-object)) ;; Put the #!eof back - (fx- next start))) ;; Return our count - (let ([min (fx- min n)] - [next (fx+ next n)]) - (if (fx<= min 0) - (fx- next start) ;; We got enough to stop - (loop next min (fx- max n)))))))))) - - (define (append-blocks size block-size block blocks) - (let ([buffer (#2%make-bytevector size)]) - (let loop ([block-size block-size] [block block] [blocks blocks] [end size]) - (let ([end (fx- end block-size)]) - (bytevector-copy! block 0 buffer end block-size) - (if (null? blocks) - buffer - (loop (caar blocks) (cdar blocks) (cdr blocks) end)))))) - - (set-who! get-bytevector-n - (lambda (binary-input-port count) - (unless (and (input-port? binary-input-port) (binary-port? binary-input-port)) - ($oops who "~s is not a binary input port" binary-input-port)) - (unless (and (fixnum? count) (fx>= count 0)) - ($oops who "~s is not a nonnegative fixnum" count)) - (let ([buffer-size (file-buffer-size)]) - (if (not ($fxu< buffer-size count)) - (let ([bv (make-bytevector count)]) - (let ([n (get-bytevector-min-max - who binary-input-port bv 0 count count)]) - (if (eof-object? n) n (bytevector-truncate! bv n)))) - (let ([get-some (port-handler-get-some ($port-handler binary-input-port))]) - (let loop ([count count] - [size 0] - [next-block-index 0] - [next-block (make-bytevector buffer-size)] - [blocks '()]) - (let ([next-size (get-some who binary-input-port - next-block next-block-index - (fxmin count (fx- buffer-size next-block-index)))]) - (if (or (eof-object? next-size) (eq? next-size 0)) - (if (eqv? size 0) - (if (eof-object? next-size) (eof-object) #vu8()) - (append-blocks size next-block-index next-block blocks)) - (let ([count (fx- count next-size)] - [size (fx+ size next-size)] - [next-block-index (fx+ next-block-index next-size)]) - (if (eqv? count 0) - (append-blocks size next-block-index next-block blocks) - (if (fx>= next-block-index (fxquotient buffer-size 2)) - (loop count size 0 - (make-bytevector buffer-size) - (cons (cons next-block-index next-block) blocks)) - (loop count size next-block-index next-block blocks)))))))))))) - - (set-who! get-bytevector-n! - (lambda (binary-input-port bv start count) - (unless (and (input-port? binary-input-port) (binary-port? binary-input-port)) - ($oops who "~s is not a binary input port" binary-input-port)) - (unless (bytevector? bv) - ($oops who "~s is not a bytevector" bv)) - (unless (and (fixnum? start) (fx>= start 0)) - ($oops who "invalid start value ~s" start)) - (unless (and (fixnum? count) (fx>= count 0)) - ($oops who "invalid count ~s" count)) - (unless (fx<= count (fx- (bytevector-length bv) start)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" start count bv)) - (get-bytevector-min-max who binary-input-port bv start count count))) - - (set-who! get-bytevector-some - (lambda (binary-input-port) - (let ([buffer-size (file-buffer-size)]) - (unless (and (input-port? binary-input-port) (binary-port? binary-input-port)) - ($oops who "~s is not a binary input port" binary-input-port)) - (let ([bv (make-bytevector buffer-size)]) - (let ([n (get-bytevector-min-max who binary-input-port bv 0 0 buffer-size)]) - (if (eof-object? n) - (eof-object) - (bytevector-truncate! bv n))))))) - - (set-who! get-bytevector-some! - (lambda (binary-input-port bv start count) - (unless (and (input-port? binary-input-port) (binary-port? binary-input-port)) - ($oops who "~s is not a binary input port" binary-input-port)) - (unless (bytevector? bv) - ($oops who "~s is not a bytevector" bv)) - (unless (and (fixnum? start) (fx>= start 0)) - ($oops who "invalid start value ~s" start)) - (unless (and (fixnum? count) (fx>= count 0)) - ($oops who "invalid count ~s" count)) - (unless (fx<= count (fx- (bytevector-length bv) start)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" start count bv)) - (get-bytevector-min-max who binary-input-port bv start 0 count))) - - (set-who! get-bytevector-all - (lambda (binary-input-port) - (unless (and (input-port? binary-input-port) (binary-port? binary-input-port)) - ($oops who "~s is not a binary input port" binary-input-port)) - (let ([buffer-size (file-buffer-size)]) - (let ([get-some (port-handler-get-some ($port-handler binary-input-port))]) - (let loop ([size 0] - [next-block-index 0] - [next-block (make-bytevector buffer-size)] - [blocks '()]) - (let ([next-size (get-some who binary-input-port - next-block next-block-index - (fx- buffer-size next-block-index))]) - (if (eof-object? next-size) - (if (eq? size 0) - (eof-object) - (append-blocks size next-block-index next-block blocks)) - (let ([size (fx+ size next-size)] - [next-block-index (fx+ next-block-index next-size)]) - (if (fx>= next-block-index (fxquotient buffer-size 2)) - (loop size 0 - (make-bytevector buffer-size) - (cons (cons next-block-index next-block) blocks)) - (loop size next-block-index next-block blocks)))))))))) - ) - - -;;;; 8.2.9 Textual input - ;; get-char in prims.ss - ;; lookahead-char in prims.ss - - (let () - ;; TODO: this code is identical to get-bytevector-min-max - ;; This helper handles all the looping for the following functions - (define (get-string-min-max who p bv start min max) - (if (eq? 0 max) - 0 - (let ([get-some (port-handler-get-some ($port-handler p))]) - ;; Loop invariant: - ;; next = next spot to fill in the bytevector - ;; min = minimum left to read - ;; max = maximum left to read - (let loop ([next start] - [min min] - [max max]) - (let ([n (get-some who p bv next max)]) - (if (eof-object? n) - (if (eq? start next) - (eof-object) ;; We couldn't even read one byte - (begin ;; Got some but got #!eof before full - (call-port-handler unget who p (eof-object)) ;; Put the #!eof back - (fx- next start))) ;; Return our count - (let ([min (fx- min n)] - [next (fx+ next n)]) - (if (fx<= min 0) - (fx- next start) ;; We got enough to stop - (loop next min (fx- max n)))))))))) - - (define (append-blocks size block-size block blocks) - (let ([buffer (#2%make-string size)]) - (let loop ([block-size block-size] [block block] [blocks blocks] [end size]) - (let ([end (fx- end block-size)]) - (string-copy! block 0 buffer end block-size) - (if (null? blocks) - buffer - (loop (caar blocks) (cdar blocks) (cdr blocks) end)))))) - - (define $get-string-all - (lambda (who textual-input-port) - (let ([buffer-size (file-buffer-size)]) - (let ([get-some (port-handler-get-some ($port-handler textual-input-port))]) - (let loop ([size 0] - [next-block-index 0] - [next-block (make-string buffer-size)] - [blocks '()]) - (let ([next-size (get-some who textual-input-port - next-block next-block-index - (fx- buffer-size next-block-index))]) - (if (eof-object? next-size) - (if (eq? size 0) - (eof-object) - (append-blocks size next-block-index next-block blocks)) - (let ([size (fx+ size next-size)] - [next-block-index (fx+ next-block-index next-size)]) - (if (fx>= next-block-index (fxquotient buffer-size 2)) - (loop size 0 - (make-string buffer-size) - (cons (cons next-block-index next-block) blocks)) - (loop size next-block-index next-block blocks)))))))))) - - (set-who! get-string-n - (lambda (textual-input-port count) - (unless (and (input-port? textual-input-port) (textual-port? textual-input-port)) - ($oops who "~s is not a textual input port" textual-input-port)) - (unless (and (fixnum? count) (fx>= count 0)) - ($oops who "~s is not a nonnegative fixnum" count)) - (let ([buffer-size (file-buffer-size)]) - (if (not ($fxu< buffer-size count)) - (let ([st (make-string count)]) - (let ([n (get-string-min-max - who textual-input-port st 0 count count)]) - (if (eof-object? n) n (string-truncate! st n)))) - (let ([get-some (port-handler-get-some ($port-handler textual-input-port))]) - (let loop ([count count] - [size 0] - [next-block-index 0] - [next-block (make-string buffer-size)] - [blocks '()]) - (let ([next-size (get-some who textual-input-port - next-block next-block-index - (fxmin count (fx- buffer-size next-block-index)))]) - (if (or (eof-object? next-size) (eq? next-size 0)) - (if (eqv? size 0) - (if (eof-object? next-size) (eof-object) "") - (append-blocks size next-block-index next-block blocks)) - (let ([count (fx- count next-size)] - [size (fx+ size next-size)] - [next-block-index (fx+ next-block-index next-size)]) - (if (eqv? count 0) - (append-blocks size next-block-index next-block blocks) - (if (fx>= next-block-index (fxquotient buffer-size 2)) - (loop count size 0 - (make-string buffer-size) - (cons (cons next-block-index next-block) blocks)) - (loop count size next-block-index next-block blocks)))))))))))) - - (set-who! get-string-n! - (lambda (textual-input-port st start count) - (unless (and (input-port? textual-input-port) (textual-port? textual-input-port)) - ($oops who "~s is not a textual input port" textual-input-port)) - (unless (string? st) - ($oops who "~s is not a string" st)) - (unless (and (fixnum? start) (fx>= start 0)) - ($oops who "invalid start value ~s" start)) - (unless (and (fixnum? count) (fx>= count 0)) - ($oops who "invalid count ~s" count)) - (unless (fx<= count (fx- (string-length st) start)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" start count st)) - (get-string-min-max who textual-input-port st start count count))) - - (set-who! get-string-some - (lambda (textual-input-port) - (unless (and (input-port? textual-input-port) (textual-port? textual-input-port)) - ($oops who "~s is not a textual input port" textual-input-port)) - (let ([buffer-size (file-buffer-size)]) - (let ([st (make-string buffer-size)]) - (let ([n (get-string-min-max who textual-input-port st 0 0 buffer-size)]) - (if (eof-object? n) - (eof-object) - (string-truncate! st n))))))) - - (set-who! get-string-some! - (lambda (textual-input-port st start count) - (unless (and (input-port? textual-input-port) (textual-port? textual-input-port)) - ($oops who "~s is not a textual input port" textual-input-port)) - (unless (string? st) - ($oops who "~s is not a string" st)) - (unless (and (fixnum? start) (fx>= start 0)) - ($oops who "invalid start value ~s" start)) - (unless (and (fixnum? count) (fx>= count 0)) - ($oops who "invalid count ~s" count)) - (unless (fx<= count (fx- (string-length st) start)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" start count st)) - (get-string-min-max who textual-input-port st start 0 count))) - - (set-who! get-string-all - (lambda (textual-input-port) - (unless (and (input-port? textual-input-port) (textual-port? textual-input-port)) - ($oops who "~s is not a textual input port" textual-input-port)) - ($get-string-all who textual-input-port))) - - (set-who! bytevector->string - (lambda (bv tx) - (unless (bytevector? bv) - ($oops who "~s is not a bytevector" bv)) - (unless ($transcoder? tx) - ($oops who "~s is not a transcoder" tx)) - (let ([str ($get-string-all who (open-bytevector-input-port bv tx))]) - (if (eof-object? str) "" str)))) - ) - - (set-who! get-line - (lambda (tp) - (unless (and (input-port? tp) (textual-port? tp)) - ($oops who "~s is not a textual input port" tp)) - (let f ([n 0]) - (let ([c (get-char tp)]) - (cond - [(eof-object? c) (if (fx= n 0) c (begin (unget-char tp c) (make-string n)))] - [(char=? c #\newline) (make-string n)] - [else (let ([s (f (fx+ n 1))]) (string-set! s n c) s)]))))) - - ;; get-datum in read.ss - -;;;; 8.2.10 Output ports - ;; output-port? in prims.ss - (let () - (define who 'flush-output-port) - (define flush-help - (lambda (output-port) - (call-port-handler flush who output-port))) - (define flush-check-help - (lambda (output-port) - (unless (output-port? output-port) - ($oops who "~s is not an output port" output-port)) - (flush-help output-port))) - (set! flush-output-port - (case-lambda - [() (flush-help (current-output-port))] - [(output-port) (flush-check-help output-port)])) - (set! r6rs:flush-output-port - (rec flush-output-port - (lambda (output-port) - (flush-check-help output-port))))) - - ; input-port-buffer-mode isn't required by r6rs but would be essentially - ; the same code. if anything, it would be even more useless. - (set-who! output-port-buffer-mode - (lambda (output-port) - (unless (output-port? output-port) - ($oops who "~s is not an output port" output-port)) - (cond - [($port-flags-set? output-port (constant port-flag-block-buffered)) - (buffer-mode block)] - [($port-flags-set? output-port (constant port-flag-line-buffered)) - (buffer-mode line)] - [else (buffer-mode none)]))) - - ;; open-file-output-port - (let () - (define open-binary-file-output-port - (lambda (who filename options perms b-mode) - (let ([no-create (enum-set-subset? (file-options no-create) options)] - [no-fail (enum-set-subset? (file-options no-fail) options)] - [no-truncate (enum-set-subset? (file-options no-truncate) options)] - [append (enum-set-subset? (file-options append) options)] - [lock (enum-set-subset? (file-options exclusive) options)] - [replace (enum-set-subset? (file-options replace) options)] - [compressed (enum-set-subset? (file-options compressed) options)]) - (when (and compressed lock) - ($oops who "exclusive option is not supported with compress option")) - (when-feature windows - (unless-feature pthreads - ; try to work around windows file open semantics by trying - ; to close any open ports to the file if we cannot delete it - ; without doing so. - (when replace - (delete-file filename #f) - (when (file-exists? filename) - (collect (collect-maximum-generation)))))) - (let ([fd (critical-section - ($open-output-fd filename perms - no-create no-fail no-truncate - append lock replace compressed))]) - (when (pair? fd) (open-oops who filename options fd)) - (open-binary-fd-output-port who filename fd #t b-mode lock compressed))))) - - (define help-open-file-output-port - (lambda (who filename options perms b-mode maybe-transcoder) - (let ([bp (open-binary-file-output-port who filename options perms b-mode)]) - (if maybe-transcoder - (transcoded-port bp maybe-transcoder) - bp)))) - - (define open-binary-standard-output-port - (lambda (who fd name b-mode) - (unless (buffer-mode? b-mode) - ($oops who "~s is not a valid buffer mode" b-mode)) - (open-binary-fd-output-port who name (make-fd fd) ($fd-regular? fd) b-mode #f #f))) - - (set-who! open-file-output-port - (rec open-file-output-port - (case-lambda - [(filename) (open-file-output-port filename (file-options))] - [(filename options) (open-file-output-port filename options (buffer-mode block))] - [(filename options b-mode) (open-file-output-port filename options b-mode #f)] - [(filename options b-mode maybe-transcoder) - (unless (string? filename) ($oops who "~s is not a string" filename)) - (unless (and (enum-set? options) (enum-set-subset? options $file-options)) - ($oops who "~s is not a file-options object" options)) - (unless (buffer-mode? b-mode) - ($oops who "~s is not a valid buffer mode" b-mode)) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (help-open-file-output-port who filename options - (extract-permission-mask options) b-mode maybe-transcoder)]))) - - (set! $open-file-output-port - (rec $open-file-output-port - (case-lambda - [(who filename) ($open-file-output-port who filename (file-options))] - [(who filename options) ($open-file-output-port who filename options (buffer-mode block))] - [(who filename options b-mode) ($open-file-output-port who filename options b-mode #f)] - [(who filename options b-mode maybe-transcoder) - (unless (string? filename) ($oops who "~s is not a string" filename)) - (unless (and (enum-set? options) (enum-set-subset? options $file-options)) - ($oops who "~s is not a file-options object" options)) - (unless (buffer-mode? b-mode) - ($oops who "~s is not a valid buffer mode" b-mode)) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (help-open-file-output-port who filename options - (extract-permission-mask options) b-mode maybe-transcoder)]))) - - (set-who! open-fd-output-port - (case-lambda - [(fd) - (unless (and (fixnum? fd) (fx>= fd 0)) - ($oops who "~s is not a file descriptor" fd)) - (open-binary-fd-output-port who (format "fd ~s" fd) (make-fd fd) ($fd-regular? fd) (buffer-mode block) #f #f)] - [(fd buffer-mode) - (unless (and (fixnum? fd) (fx>= fd 0)) - ($oops who "~s is not a file descriptor" fd)) - (unless (buffer-mode? buffer-mode) - ($oops who "~s is not a buffer mode" buffer-mode)) - (open-binary-fd-output-port who (format "fd ~s" fd) (make-fd fd) ($fd-regular? fd) buffer-mode #f #f)] - [(fd buffer-mode maybe-transcoder) - (unless (and (fixnum? fd) (fx>= fd 0)) - ($oops who "~s is not a file descriptor" fd)) - (unless (buffer-mode? buffer-mode) - ($oops who "~s is not a buffer mode" buffer-mode)) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (let ([bp (open-binary-fd-output-port who (format "fd ~s" fd) (make-fd fd) ($fd-regular? fd) buffer-mode #f #f)]) - (if maybe-transcoder - (transcoded-port bp maybe-transcoder) - bp))])) - - (set-who! standard-output-port - (case-lambda - [() (open-binary-standard-output-port who 1 "stdout" (buffer-mode line))] - [(b-mode) (open-binary-standard-output-port who 1 "stdout" b-mode)] - [(b-mode maybe-transcoder) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (let ([binary-port (open-binary-standard-output-port who 1 "stdout" b-mode)]) - (if maybe-transcoder - (transcoded-port binary-port maybe-transcoder) - binary-port))])) - - (set-who! r6rs:standard-output-port - (rec standard-output-port - (lambda () - (open-binary-standard-output-port who 1 "stdout" (buffer-mode line))))) - - (set-who! standard-error-port - (case-lambda - [() (open-binary-standard-output-port who 2 "stderr" (buffer-mode none))] - [(b-mode) (open-binary-standard-output-port who 2 "stderr" b-mode)] - [(b-mode maybe-transcoder) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (let ([binary-port (open-binary-standard-output-port who 2 "stderr" b-mode)]) - (if maybe-transcoder - (transcoded-port binary-port maybe-transcoder) - binary-port))])) - - (set-who! r6rs:standard-error-port - (rec standard-error-port - (lambda () - (open-binary-standard-output-port who 2 "stderr" (buffer-mode none))))) - - ; simple i/o routines here to share helpers - (let () - (define (oof who s o) - (unless (string? s) ($oops who "~s is not a string" s)) - (let ([o (if (list? o) o (list o))]) - (let loop ([o o] [ifexists #f] [mode #o666] [zmode #f] [xmode #f] [bmode #f]) - (if (null? o) - (help-open-file-output-port who s - (enum-set-union - (enum-set-union - (case ifexists - [(error) (file-options)] - [(truncate) (file-options no-fail)] - [(replace) (file-options no-fail no-truncate replace)] - [(append) (file-options append no-fail no-truncate)] - [else (file-options)]) - (if (eq? zmode 'compressed) (file-options compressed) (file-options))) - (if (eq? xmode 'exclusive) (file-options exclusive) (file-options))) - mode - (if (eq? bmode 'unbuffered) (buffer-mode none) (buffer-mode block)) - (current-transcoder)) - (case (car o) - [(error truncate replace append) - (check-option who ifexists (car o)) - (loop (cdr o) (car o) mode zmode xmode bmode)] - [(compressed uncompressed) - (check-option who zmode (car o)) - (loop (cdr o) ifexists mode (car o) xmode bmode)] - [(buffered unbuffered) - (check-option who bmode (car o)) - (loop (cdr o) ifexists mode zmode xmode (car o))] - [(exclusive nonexclusive) - (check-option who xmode (car o)) - (loop (cdr o) ifexists mode zmode (car o) bmode)] - [(mode) - (if (null? (cdr o)) - ($oops who "mode option requires an argument") - (let ([mode (cadr o)]) - (if (and (fixnum? mode) (fx>= mode 0)) - (loop (cddr o) ifexists mode zmode xmode bmode) - ($oops who "mode argument must be a nonnegative fixnum"))))] - [else ($oops who "invalid option ~s" (car o))]))))) - - (set-who! #(r6rs: open-output-file) - (lambda (s) (oof who s '()))) - - (set-who! open-output-file - (case-lambda - [(s) (oof who s '())] - [(s o) (oof who s o)])) - - (let () - (define (cwof who s f o) - (unless (procedure? f) - ($oops who "~s is not a procedure" f)) - (let ([p (oof who s o)]) - (call-with-values - (lambda () (f p)) - (lambda args - (close-output-port p) - (apply values args))))) - (set-who! #(r6rs: call-with-output-file) - (lambda (s f) (cwof who s f '()))) - (set-who! call-with-output-file - (case-lambda - [(s f) (cwof who s f '())] - [(s f o) (cwof who s f o)]))) - - (let () - (define (wotf who s f o) - (unless (procedure? f) - ($oops who "~s is not a procedure" f)) - (let ([p (oof who s o)]) - (call-with-values - (lambda () (parameterize ([current-output-port p]) (f))) - (lambda v - (close-output-port p) - (apply values v))))) - (set-who! #(r6rs: with-output-to-file) - (lambda (s f) (wotf who s f '()))) - (set-who! with-output-to-file - (case-lambda - [(s f) (wotf who s f '())] - [(s f o) (wotf who s f o)])))) - - ) - - ;; open-bytevector-output-port - (let () - ;; if info-index != index, there was put/put-some after last set-pos - ;; and (max info-length index) is true length - ;; if info-index == index, there was set-pos after last put/put-some - ;; and info-length is true length - - ;; Invariant: info-index <= index - ;; Invariant: size = (max length index) - ;; Invariant: if no put/put-some after last set-pos/set-length, - ;; then info-index = index and true length = info-length - ;; Invariant: if put/put-some after last set-pos/set-length, - ;; then info-index < index and true length = max info-length index - - ;; It is always safe to increment index when count != 0 - ;; It is always safe to write at index when count != 0 - ;; Index always contains the current position - ;; The only operation that needs to decrement index is set-position - ;; which needs to set info-index anyway - - (define-record-type bytevector-output-port-info - (nongenerative) - (opaque #t) - (sealed #t) - (fields - (mutable index) - (mutable length) - (mutable nonblocking))) - - ;; NOTE: leaves index at 0, callers must reset index if needed - (define (extend-buffer p count) - (let ([old-size (binary-port-output-size p)] - [old-buffer (binary-port-output-buffer p)] - [old-index (binary-port-output-index p)]) - (let* ([new-length (fxmax bytevector-buffer-length - (fx* 2 (fx+ old-size count)))] - [new-buffer (make-bytevector new-length)]) - (bytevector-copy! old-buffer 0 new-buffer 0 - (fxmin (bytevector-length old-buffer) old-size)) - (set-binary-port-output-buffer! p new-buffer)))) - - (define port-length - (lambda (who p) - (let ([info ($port-info p)] - [index (binary-port-output-index p)]) - (let ([info-index (bytevector-output-port-info-index info)] - [info-length (bytevector-output-port-info-length info)]) - (if (eq? index info-index) - info-length ;; last op was set-pos - (max index info-length)))))) ;; last op was put - - (define $bytevector-output-handler - (make-port-handler - [ready? #f] - [lookahead #f] - [unget #f] - [get #f] - [get-some #f] - [clear-input #f] - [put - (lambda (who p x) - (assert-not-closed who p) - (let ([index (binary-port-output-index p)]) - (when (port-output-full? p) (extend-buffer p 0)) - (bytevector-u8-set! (binary-port-output-buffer p) index x) - (set-binary-port-output-index! p (fx1+ index))))] - [put-some - (lambda (who p bv start count) - (assert-not-closed who p) - (let ([index (binary-port-output-index p)]) - (when ($fxu< (binary-port-output-count p) count) (extend-buffer p count)) - (bytevector-copy! bv start - (binary-port-output-buffer p) index count) - (set-binary-port-output-index! p (fx+ index count))) - count)] - [flush ; no-op on bytevector output ports - (lambda (who p) - (assert-not-closed who p))] - [clear-output ; no-op on bytevector output ports - (lambda (who p) - (assert-not-closed who p))] - [close-port - (lambda (who p) - (unless (port-closed? p) - ; sync info-index for possible post-close extraction - (let ([info ($port-info p)] [index (binary-port-output-index p)]) - (unless (eq? index (bytevector-output-port-info-index info)) - (bytevector-output-port-info-length-set! info - (fxmax index (bytevector-output-port-info-length info))))) - (mark-port-closed! p) - (set-binary-port-output-size! p 0)))] - [port-position - (lambda (who p) - (assert-not-closed who p) - (binary-port-output-index p))] - [set-port-position! - (lambda (who p pos) - (assert-not-closed who p) - (unless (and (fixnum? pos) (fx>= pos 0)) - (if (and (bignum? pos) (>= pos 0)) - (position-oops who p pos "out of range") - ($oops who "~s is not a valid position" pos))) - (let ([info ($port-info p)] - [index (binary-port-output-index p)]) - ; unless last op was set-pos, save the true length - (unless (eq? index (bytevector-output-port-info-index info)) - (bytevector-output-port-info-length-set! info - (fxmax index (bytevector-output-port-info-length info)))) - (set-binary-port-output-size! p - (fxmax pos (fx1- (bytevector-length (binary-port-output-buffer p))))) - (set-binary-port-output-index! p pos) - (bytevector-output-port-info-index-set! info pos)))] - [port-length - (lambda (who p) - (assert-not-closed who p) - (port-length who p))] - [set-port-length! - (lambda (who p pos) - (unless (and (fixnum? pos) (fx>= pos 0)) - (if (and (bignum? pos) (>= pos 0)) - (position-oops who p pos "out of range") - ($oops who "~s is not a valid length" pos))) - (assert-not-closed who p) - (let ([info ($port-info p)] - [index (binary-port-output-index p)] - [size (binary-port-output-size p)]) - ;; ensure the bytevector is long enough - (let ([buflen-1 (fx1- (bytevector-length (binary-port-output-buffer p)))]) - (when ($fxu< buflen-1 pos) - (extend-buffer p (fx- pos buflen-1)) - (set-binary-port-output-index! p index))) - ;; make it look like a set-pos was done last - ;; (i.e. index might be beyond true length) - (bytevector-output-port-info-index-set! info index) - ;; set the true length - (bytevector-output-port-info-length-set! info pos)))] - [port-nonblocking? - (lambda (who p) - (assert-not-closed who p) - (bytevector-output-port-info-nonblocking ($port-info p)))] - [set-port-nonblocking! - (lambda (who p x) - (assert-not-closed who p) - (bytevector-output-port-info-nonblocking-set! ($port-info p) x))])) - - (define extractor - (lambda (p) - (let ([old-buffer - (bytevector-truncate! - (binary-port-output-buffer p) - (port-length #f p))]) - (set-binary-port-output-buffer! p #vu8()) - (let ([info ($port-info p)]) - (bytevector-output-port-info-index-set! info 0) - (bytevector-output-port-info-length-set! info 0)) - old-buffer))) - - (define open-binary-bytevector-output-port - (lambda () - (let ([p ($make-binary-output-port "bytevector" - $bytevector-output-handler - #vu8() - (make-bytevector-output-port-info 0 0 #f))]) - ($set-port-flags! p (constant port-flag-block-buffered)) - (values - p - (lambda () - (let ([info ($port-info p)]) - (if (bytevector-output-port-info? info) - (extractor p) - ; the port must have been transcoded - (begin - (flush-output-port info) - (extractor (codec-info-bp ($port-info info))))))))))) - - (set-who! open-bytevector-output-port - (case-lambda - [() (open-binary-bytevector-output-port)] - [(maybe-transcoder) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (let-values ([(binary-port extractor) - (open-binary-bytevector-output-port)]) - (values - (if maybe-transcoder - (transcoded-port binary-port maybe-transcoder) - binary-port) - extractor))])) - ) - - ;; open-bytevector-list-output-port - (let () - (define-record-type bv-list-op-info - (nongenerative) - (sealed #t) - (fields - (mutable nonblocking) - (mutable bv*))) - - ; allocate in chunk-size chunks - (define chunk-size 4096) - - (define (extend-buffer p) - (let ([bv (binary-port-output-buffer p)]) - (unless (eqv? bv #vu8()) - (let ([info ($port-info p)]) - (bv-list-op-info-bv*-set! info - (cons bv (bv-list-op-info-bv* info)))))) - (set-binary-port-output-buffer! p (make-bytevector chunk-size))) - - (define $bytevector-list-output-handler - (make-port-handler - [ready? #f] - [lookahead #f] - [unget #f] - [get #f] - [get-some #f] - [clear-input #f] - [put - (lambda (who p x) - (assert-not-closed who p) - (when (port-output-full? p) (extend-buffer p)) - (let ([index (binary-port-output-index p)]) - (bytevector-u8-set! (binary-port-output-buffer p) index x) - (set-binary-port-output-index! p (fx1+ index))))] - [put-some - (lambda (who p bv start count) - (assert-not-closed who p) - (when (port-output-full? p) (extend-buffer p)) - (let ([count (fxmin count (binary-port-output-count p))] - [index (binary-port-output-index p)]) - (bytevector-copy! bv start (binary-port-output-buffer p) index count) - (set-binary-port-output-index! p (fx+ index count)) - count))] - [flush ; no-op on bytevector output ports - (lambda (who p) - (assert-not-closed who p))] - [clear-output ; no-op on bytevector output ports - (lambda (who p) - (assert-not-closed who p))] - [close-port - (lambda (who p) - (unless (port-closed? p) - ; sync info-index for possible post-close extraction - #;(let ([old-buffer (bytevector-truncate! - (binary-port-output-buffer p) - (binary-port-output-index p))] - [bv* (bv-list-op-info-bv* info)]) - (bv-list-op-info-size-set! info - (fx+ (bytevector-length old-buffer) - (fx* (length bv*) chunk-size))) - (bv-list-op-info-bv*-set! info - (reverse (if (eq? old-buffer #vu8()) - bv* - (cons old-buffer bv*))))) - (mark-port-closed! p) - (set-binary-port-output-size! p 0)))] - [port-position - (lambda (who p) - (assert-not-closed who p) - (fx+ (binary-port-output-index p) - (fx* (length (bv-list-op-info-bv* ($port-info p))) chunk-size)))] - [set-port-position! #f] - [port-length - (lambda (who p) - (assert-not-closed who p) - (fx+ (binary-port-output-index p) - (fx* (length (bv-list-op-info-bv* ($port-info p))) chunk-size)))] - [set-port-length! #f] - [port-nonblocking? - (lambda (who p) - (assert-not-closed who p) - (bv-list-op-info-nonblocking ($port-info p)))] - [set-port-nonblocking! - (lambda (who p x) - (assert-not-closed who p) - (bv-list-op-info-nonblocking-set! ($port-info p) x))])) - - (define extractor - (lambda (p) - (let ([info ($port-info p)]) - (let ([bv (bytevector-truncate! - (binary-port-output-buffer p) - (binary-port-output-index p))] - [bv* (bv-list-op-info-bv* info)]) - (let ([size (fx+ (bytevector-length bv) (fx* (length bv*) chunk-size))]) - (set-binary-port-output-buffer! p #vu8()) - (bv-list-op-info-bv*-set! info '()) - (values (reverse (if (eqv? bv #vu8()) bv* (cons bv bv*))) size)))))) - - (set-who! $open-bytevector-list-output-port - (lambda () - (let ([p ($make-binary-output-port "bytevector-list" - $bytevector-list-output-handler - #vu8() - (make-bv-list-op-info #f '()))]) - ($set-port-flags! p (constant port-flag-block-buffered)) - (values p (lambda () (extractor p))))))) - - (let () - (define ($call-with-bytevector-output-port who proc maybe-transcoder) - (let-values ([(port extractor) (open-bytevector-output-port maybe-transcoder)]) - (proc port) - (let ([bv (extractor)]) - (call-port-handler close-port who port) - bv))) - - (set-who! call-with-bytevector-output-port - (case-lambda - [(proc) - (unless (procedure? proc) ($oops who "~s is not a procedure" proc)) - ($call-with-bytevector-output-port who proc #f)] - [(proc maybe-transcoder) - (unless (procedure? proc) - ($oops who "~s is not a procedure" proc)) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not a transcoder" maybe-transcoder)) - ($call-with-bytevector-output-port who proc maybe-transcoder)])) - - (set-who! string->bytevector - (lambda (str tx) - (unless (string? str) - ($oops who "~s is not a string" str)) - (unless ($transcoder? tx) - ($oops who "~s is not a transcoder" tx)) - ($call-with-bytevector-output-port who - (lambda (op) (put-string op str)) - tx)))) - - ;; open-string-output-port - (let () - ;; see open-bytevector-output-port for explanation of algorithm - - (define-record-type string-output-port-info - (nongenerative) - (opaque #t) - (sealed #t) - (fields - (mutable index) - (mutable length) - (mutable nonblocking))) - - ;; NOTE: leaves index at 0, callers must reset index if needed - (define (extend-buffer p count) - (let ([old-size (textual-port-output-size p)] - [old-buffer (textual-port-output-buffer p)] - [old-index (textual-port-output-index p)]) - (let* ([new-length (fxmax string-buffer-length - (fx* 2 (fx+ old-size count)))] - [new-buffer (make-string new-length)]) - (string-copy! old-buffer 0 new-buffer 0 - (fxmin (string-length old-buffer) old-size)) - (set-textual-port-output-buffer! p new-buffer)))) - - (define port-length - (lambda (who p) - (let ([info ($port-info p)] - [index (textual-port-output-index p)]) - (let ([info-index (string-output-port-info-index info)] - [info-length (string-output-port-info-length info)]) - (if (eq? index info-index) - info-length ;; last op was set-pos - (max index info-length)))))) ;; last op was put - - (define $string-output-handler - (make-port-handler - [ready? #f] - [lookahead #f] - [unget #f] - [get #f] - [get-some #f] - [clear-input #f] - [put - (lambda (who p x) - (assert-not-closed who p) - (let ([index (textual-port-output-index p)]) - (when (port-output-full? p) (extend-buffer p 0)) - (string-set! (textual-port-output-buffer p) index x) - (set-textual-port-output-index! p (fx1+ index))))] - [put-some - (lambda (who p st start count) - (assert-not-closed who p) - (let ([index (textual-port-output-index p)]) - (when ($fxu< (textual-port-output-count p) count) (extend-buffer p count)) - (string-copy! st start - (textual-port-output-buffer p) index count) - (set-textual-port-output-index! p (fx+ index count))) - count)] - [flush ; no-op on string output ports - (lambda (who p) - (assert-not-closed who p))] - [clear-output ; no-op on string output ports - (lambda (who p) - (assert-not-closed who p))] - [close-port - (lambda (who p) - (unless (port-closed? p) - ; sync info-index for possible post-close extraction - (let ([info ($port-info p)] [index (textual-port-output-index p)]) - (unless (eq? index (string-output-port-info-index info)) - (string-output-port-info-length-set! info - (fxmax index (string-output-port-info-length info))))) - (mark-port-closed! p) - (set-textual-port-output-size! p 0)))] - [port-position - (lambda (who p) - (assert-not-closed who p) - (textual-port-output-index p))] - [set-port-position! - (lambda (who p pos) - (assert-not-closed who p) - (unless (and (fixnum? pos) (fx>= pos 0)) - (if (and (bignum? pos) (>= pos 0)) - (position-oops who p pos "out of range") - ($oops who "~s is not a valid position" pos))) - (let ([info ($port-info p)] - [index (textual-port-output-index p)]) - ; unless last op was set-pos, save the true length - (unless (eq? index (string-output-port-info-index info)) - (string-output-port-info-length-set! info - (fxmax index (string-output-port-info-length info)))) - (set-textual-port-output-size! p - (fxmax pos (fx1- (string-length (textual-port-output-buffer p))))) - (set-textual-port-output-index! p pos) - (string-output-port-info-index-set! info pos)))] - [port-length - (lambda (who p) - (assert-not-closed who p) - (port-length who p))] - [set-port-length! - (lambda (who p pos) - (unless (and (fixnum? pos) (fx>= pos 0)) - (if (and (bignum? pos) (>= pos 0)) - (position-oops who p pos "out of range") - ($oops who "~s is not a valid length" pos))) - (assert-not-closed who p) - (let ([info ($port-info p)] - [index (textual-port-output-index p)] - [size (textual-port-output-size p)]) - ;; ensure the bytevector is long enough - (let ([buflen-1 (fx1- (string-length (textual-port-output-buffer p)))]) - (when ($fxu< buflen-1 pos) - (extend-buffer p (fx- pos buflen-1)) - (set-textual-port-output-index! p index))) - ;; make it look like a set-pos was done last - ;; (i.e. index might be beyond true length) - (string-output-port-info-index-set! info index) - ;; set the true length - (string-output-port-info-length-set! info pos)))] - [port-nonblocking? - (lambda (who p) - (assert-not-closed who p) - (string-output-port-info-nonblocking ($port-info p)))] - [set-port-nonblocking! - (lambda (who p x) - (assert-not-closed who p) - (string-output-port-info-nonblocking-set! ($port-info p) x))])) - - (define ($open-string-output-port) - (let ([p ($make-textual-output-port "string" - $string-output-handler - "" - (make-string-output-port-info 0 0 #f))]) - ($set-port-flags! p (constant port-flag-block-buffered)) - ($set-port-flags! p (constant port-flag-char-positions)) - ($set-port-flags! p (constant port-flag-bol)) - p)) - - (define ($get-output-string p) - (let ([old-buffer - (string-truncate! - (textual-port-output-buffer p) - (port-length #f p))]) - (set-textual-port-output-buffer! p "") - (let ([info ($port-info p)]) - (string-output-port-info-index-set! info 0) - (string-output-port-info-length-set! info 0)) - old-buffer)) - - (set-who! open-string-output-port - (lambda () - (let ([p ($open-string-output-port)]) - (values p (lambda () ($get-output-string p)))))) - - (set-who! open-output-string - (lambda () - ($open-string-output-port))) - - (set-who! get-output-string - (lambda (p) - (unless (and (port? p) (eq? ($port-handler p) $string-output-handler)) - ($oops who "~s is not a string output port" p)) - ($get-output-string p))) - ) - - - (set-who! call-with-string-output-port - (lambda (proc) - (unless (procedure? proc) - ($oops who "~s is not a procedure" proc)) - (let-values ([(port extractor) (open-string-output-port)]) - (proc port) - (let ([st (extractor)]) - (call-port-handler close-port who port) - st)))) - - ;; current-output-port and current-error-port are in prims.ss - - (set-who! make-custom-binary-output-port - (lambda (id write! get-position set-position! close) - (unless (string? id) ($oops who "~s is not a string" id)) - (unless (procedure? write!) ($oops who "~s is not a procedure" write!)) - (unless (or (not get-position) (procedure? get-position)) - ($oops who "~s is not a procedure or #f" get-position)) - (unless (or (not set-position!) (procedure? set-position!)) - ($oops who "~s is not a procedure or #f" set-position!)) - (unless (or (not close) (procedure? close)) - ($oops who "~s is not a procedure or #f" close)) - (let ([handler - (make-port-handler - [ready? #f] - [lookahead #f] - [unget #f] - [get #f] - [get-some #f] - [clear-input #f] - [put - (lambda (who p x) - (assert-not-closed who p) - (binary-custom-port-put who p write! x))] - [put-some - (lambda (who p bv start count) - (assert-not-closed who p) - (binary-custom-port-put-some who p write! bv start count))] - [flush - (lambda (who p) - (assert-not-closed who p) - (binary-custom-port-flush who p write!))] - [clear-output - (lambda (who p) - (assert-not-closed who p) - (binary-custom-port-clear-output who p))] - [close-port - (lambda (who p) - (unless (port-closed? p) - (binary-custom-port-flush who p write!) - (binary-custom-port-close-port who p close)))] - [port-position - (and get-position - (lambda (who p) - (assert-not-closed who p) - (binary-custom-port-port-position out who p get-position)))] - [set-port-position! - (and set-position! - (lambda (who p x) - (unless (or (and (fixnum? x) (fx>= x 0)) (and (bignum? x) (>= x 0))) - ($oops who "~s is not a valid position" x)) - (assert-not-closed who p) - (binary-custom-port-flush who p write!) - (set-position! x)))] - [port-length #f] - [set-port-length! #f] - [port-nonblocking? #f] - [set-port-nonblocking! #f])]) - (let ([bufsiz (custom-port-buffer-size)]) - (let ([p ($make-binary-output-port id handler (make-bytevector bufsiz) #f)]) - ($set-port-flags! p (constant port-flag-block-buffered)) - (set-binary-port-output-size! p (fx1- bufsiz)) ;; leave room for put to work - p))))) - - (set-who! make-custom-textual-output-port - (lambda (id write! get-position set-position! close) - (unless (string? id) ($oops who "~s is not a string" id)) - (unless (procedure? write!) ($oops who "~s is not a procedure" write!)) - (unless (or (not get-position) (procedure? get-position)) - ($oops who "~s is not a procedure or #f" get-position)) - (unless (or (not set-position!) (procedure? set-position!)) - ($oops who "~s is not a procedure or #f" set-position!)) - (unless (or (not close) (procedure? close)) - ($oops who "~s is not a procedure or #f" close)) - (let ([handler - (make-port-handler - [ready? #f] - [lookahead #f] - [unget #f] - [get #f] - [get-some #f] - [clear-input #f] - [put - (lambda (who p x) - (assert-not-closed who p) - (textual-custom-port-put who p write! x))] - [put-some - (lambda (who p str start count) - (assert-not-closed who p) - (textual-custom-port-put-some who p write! str start count))] - [flush - (lambda (who p) - (assert-not-closed who p) - (textual-custom-port-flush who p write!))] - [clear-output - (lambda (who p) - (assert-not-closed who p) - (textual-custom-port-clear-output who p))] - [close-port - (lambda (who p) - (unless (port-closed? p) - (textual-custom-port-flush who p write!) - (textual-custom-port-close-port who p close)))] - [port-position - (and get-position - (lambda (who p) - (assert-not-closed who p) - (textual-custom-port-flush who p write!) - (get-position)))] - [set-port-position! - (and set-position! - (lambda (who p x) - (assert-not-closed who p) - (textual-custom-port-flush who p write!) - (set-position! x)))] - [port-length #f] - [set-port-length! #f] - [port-nonblocking? #f] - [set-port-nonblocking! #f])]) - (let ([bufsiz (custom-port-buffer-size)]) - (let ([p ($make-textual-output-port id handler (make-string bufsiz) #f)]) - ($set-port-flags! p (constant port-flag-block-buffered)) - ($set-port-flags! p (constant port-flag-bol)) - (set-textual-port-output-size! p (fx1- bufsiz)) ;; leave room for put to work - p))))) - - -;;;; 8.2.11 Binary output - ;; put-u8 in prims.ss - - (set-who! put-bytevector - (case-lambda - [(binary-output-port bv) - (unless (and (output-port? binary-output-port) (binary-port? binary-output-port)) - ($oops who "~s is not a binary output port" binary-output-port)) - (unless (bytevector? bv) - ($oops who "~s is not a bytevector" bv)) - (#3%put-bytevector binary-output-port bv)] - [(binary-output-port bv start) - (unless (and (output-port? binary-output-port) (binary-port? binary-output-port)) - ($oops who "~s is not a binary output port" binary-output-port)) - (unless (bytevector? bv) - ($oops who "~s is not a bytevector" bv)) - (unless (and (fixnum? start) (not ($fxu< (bytevector-length bv) start))) - ($oops who "invalid start value ~s" start)) - (#3%put-bytevector binary-output-port bv start)] - [(binary-output-port bv start count) - (unless (and (output-port? binary-output-port) (binary-port? binary-output-port)) - ($oops who "~s is not a binary output port" binary-output-port)) - (unless (bytevector? bv) - ($oops who "~s is not a bytevector" bv)) - (unless (and (fixnum? start) (fx<= 0 start)) - ($oops who "invalid start value ~s" start)) - (unless (and (fixnum? count) (fx<= 0 count)) - ($oops who "invalid count ~s" count)) - (unless (fx<= count (fx- (bytevector-length bv) start)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" start count bv)) - (#3%put-bytevector binary-output-port bv start count)])) - - ;; not in R6RS - (set-who! put-bytevector-some - (case-lambda - [(binary-output-port bv) - (unless (and (output-port? binary-output-port) (binary-port? binary-output-port)) - ($oops who "~s is not a binary output port" binary-output-port)) - (unless (bytevector? bv) - ($oops who "~s is not a bytevector" bv)) - (#3%put-bytevector-some binary-output-port bv)] - [(binary-output-port bv start) - (unless (and (output-port? binary-output-port) (binary-port? binary-output-port)) - ($oops who "~s is not a binary output port" binary-output-port)) - (unless (bytevector? bv) - ($oops who "~s is not a bytevector" bv)) - (unless (and (fixnum? start) (not ($fxu< (bytevector-length bv) start))) - ($oops who "invalid start value ~s" start)) - (#3%put-bytevector-some binary-output-port bv start)] - [(binary-output-port bv start count) - (unless (and (output-port? binary-output-port) (binary-port? binary-output-port)) - ($oops who "~s is not a binary output port" binary-output-port)) - (unless (bytevector? bv) - ($oops who "~s is not a bytevector" bv)) - (unless (and (fixnum? start) (fx<= 0 start)) - ($oops who "invalid start value ~s" start)) - (unless (and (fixnum? count) (fx<= 0 count)) - ($oops who "invalid count ~s" count)) - (unless (fx<= count (fx- (bytevector-length bv) start)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" start count bv)) - (#3%put-bytevector-some binary-output-port bv start count)])) - -;;;; 8.2.12 Textual output - ;; put-char in prims.ss - - (set-who! put-string - (case-lambda - [(textual-output-port str) - (unless (and (output-port? textual-output-port) (textual-port? textual-output-port)) - ($oops who "~s is not a textual output port" textual-output-port)) - (unless (string? str) - ($oops who "~s is not a string" str)) - (#3%put-string textual-output-port str)] - [(textual-output-port str start) - (unless (and (output-port? textual-output-port) (textual-port? textual-output-port)) - ($oops who "~s is not a textual output port" textual-output-port)) - (unless (string? str) - ($oops who "~s is not a string" str)) - (unless (and (fixnum? start) (not ($fxu< (string-length str) start))) - ($oops who "invalid start value ~s" start)) - (#3%put-string textual-output-port str start)] - [(textual-output-port str start count) - (unless (and (output-port? textual-output-port) (textual-port? textual-output-port)) - ($oops who "~s is not a textual output port" textual-output-port)) - (unless (string? str) - ($oops who "~s is not a string" str)) - (unless (and (fixnum? start) (fx<= 0 start)) - ($oops who "invalid start value ~s" start)) - (unless (and (fixnum? count) (fx<= 0 count)) - ($oops who "invalid count value ~s" count)) - (unless (fx<= count (fx- (string-length str) start)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" start count str)) - (#3%put-string textual-output-port str start count)])) - - ;; not in R6RS - (set-who! put-string-some - (case-lambda - [(textual-output-port str) - (unless (and (output-port? textual-output-port) (textual-port? textual-output-port)) - ($oops who "~s is not a textual output port" textual-output-port)) - (unless (string? str) - ($oops who "~s is not a string" str)) - (#3%put-string-some textual-output-port str)] - [(textual-output-port str start) - (unless (and (output-port? textual-output-port) (textual-port? textual-output-port)) - ($oops who "~s is not a textual output port" textual-output-port)) - (unless (string? str) - ($oops who "~s is not a string" str)) - (unless (and (fixnum? start) (not ($fxu< (string-length str) start))) - ($oops who "invalid start value ~s" start)) - (#3%put-string-some textual-output-port str start)] - [(textual-output-port str start count) - (unless (and (output-port? textual-output-port) (textual-port? textual-output-port)) - ($oops who "~s is not a textual output port" textual-output-port)) - (unless (string? str) - ($oops who "~s is not a string" str)) - (unless (and (fixnum? start) (fx<= 0 start)) - ($oops who "invalid start value ~s" start)) - (unless (and (fixnum? count) (fx<= 0 count)) - ($oops who "invalid count value ~s" count)) - (unless (fx<= count (fx- (string-length str) start)) ; avoid overflow - ($oops who "index ~s + count ~s is beyond the end of ~s" start count str)) - (#3%put-string-some textual-output-port str start count)])) - - ;; put-datum in print.ss - -;;;; 8.2.13 Input/output ports - ;; open-file-input/output-port - (let () - (define open-binary-file-input/output-port - (lambda (who filename options perms b-mode) - (let ([no-create (enum-set-subset? (file-options no-create) options)] - [no-fail (enum-set-subset? (file-options no-fail) options)] - [no-truncate (enum-set-subset? (file-options no-truncate) options)] - [append (enum-set-subset? (file-options append) options)] - [lock (enum-set-subset? (file-options exclusive) options)] - [replace (enum-set-subset? (file-options replace) options)] - [compressed (enum-set-subset? (file-options compressed) options)]) - (when (and compressed lock) - ($oops who "exclusive option is not supported with compress option")) - (when-feature windows - (unless-feature pthreads - ; try to work around windows file open semantics by trying - ; to close any open ports to the file if we cannot delete it - ; without doing so. - (when replace - (delete-file filename #f) - (when (file-exists? filename) - (collect (collect-maximum-generation)))))) - (let ([fd (critical-section - ($open-input/output-fd filename perms - no-create no-fail no-truncate - append lock replace compressed))]) - (when (pair? fd) (open-oops who filename options fd)) - (open-binary-fd-input/output-port who filename fd #t b-mode lock compressed))))) - - (define help-open-file-input/output-port - (lambda (who filename options perms b-mode maybe-transcoder) - (let ([bp (open-binary-file-input/output-port who filename options perms b-mode)]) - (if maybe-transcoder - (transcoded-port bp maybe-transcoder) - bp)))) - - (set-who! open-file-input/output-port - (rec open-file-input/output-port - (case-lambda - [(filename) (open-file-input/output-port filename (file-options))] - [(filename options) (open-file-input/output-port filename options (buffer-mode block))] - [(filename options b-mode) (open-file-input/output-port filename options b-mode #f)] - [(filename options b-mode maybe-transcoder) - (unless (string? filename) ($oops who "~s is not a string" filename)) - (unless (and (enum-set? options) (enum-set-subset? options $file-options)) - ($oops who "~s is not a file-options object" options)) - (unless (buffer-mode? b-mode) ($oops who "~s is not a valid buffer mode" b-mode)) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (help-open-file-input/output-port who filename options - (extract-permission-mask options) b-mode maybe-transcoder)]))) - - (set! $open-file-input/output-port - (rec $open-file-input/output-port - (case-lambda - [(who filename) ($open-file-input/output-port who filename (file-options))] - [(who filename options) ($open-file-input/output-port who filename options (buffer-mode block))] - [(who filename options b-mode) ($open-file-input/output-port who filename options b-mode #f)] - [(who filename options b-mode maybe-transcoder) - (unless (string? filename) ($oops who "~s is not a string" filename)) - (unless (and (enum-set? options) (enum-set-subset? options $file-options)) - ($oops who "~s is not a file-options object" options)) - (unless (buffer-mode? b-mode) ($oops who "~s is not a valid buffer mode" b-mode)) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (help-open-file-input/output-port who filename options - (extract-permission-mask options) b-mode maybe-transcoder)]))) - - (set-who! open-fd-input/output-port - (case-lambda - [(fd) - (unless (and (fixnum? fd) (fx>= fd 0)) - ($oops who "~s is not a file descriptor" fd)) - (open-binary-fd-input/output-port who (format "fd ~s" fd) (make-fd fd) ($fd-regular? fd) (buffer-mode block) #f #f)] - [(fd buffer-mode) - (unless (and (fixnum? fd) (fx>= fd 0)) - ($oops who "~s is not a file descriptor" fd)) - (unless (buffer-mode? buffer-mode) - ($oops who "~s is not a buffer mode" buffer-mode)) - (open-binary-fd-input/output-port who (format "fd ~s" fd) (make-fd fd) ($fd-regular? fd) buffer-mode #f #f)] - [(fd buffer-mode maybe-transcoder) - (unless (and (fixnum? fd) (fx>= fd 0)) - ($oops who "~s is not a file descriptor" fd)) - (unless (buffer-mode? buffer-mode) - ($oops who "~s is not a buffer mode" buffer-mode)) - (unless (or (not maybe-transcoder) ($transcoder? maybe-transcoder)) - ($oops who "~s is not #f or a transcoder" maybe-transcoder)) - (let ([binary-port - (open-binary-fd-input/output-port who (format "fd ~s" fd) (make-fd fd) ($fd-regular? fd) buffer-mode #f #f)]) - (if maybe-transcoder - (transcoded-port binary-port maybe-transcoder) - binary-port))])) - - ; TODO: standard-input/output-port. requires paired fds - - ; simple i/o routines here to share helpers - (let () - (define (oiof who s o) - (unless (string? s) ($oops who "~s is not a string" s)) - (let ([o (if (list? o) o (list o))]) - (let loop ([o o] [ifexists #f] [mode #o666] [xmode #f] [bmode #f]) - (if (null? o) - (help-open-file-input/output-port who s - (enum-set-union - (case ifexists - [(error) (file-options)] - [(truncate) (file-options no-fail)] - [(replace) (file-options no-fail no-truncate replace)] - [(append) (file-options append no-fail no-truncate)] - [else (file-options no-fail no-truncate)]) - (if (eq? xmode 'exclusive) (file-options exclusive) (file-options))) - mode - (if (eq? bmode 'unbuffered) (buffer-mode none) (buffer-mode block)) - (current-transcoder)) - (case (car o) - [(error truncate replace append) - (check-option who ifexists (car o)) - (loop (cdr o) (car o) mode xmode bmode)] - [(buffered unbuffered) - (check-option who bmode (car o)) - (loop (cdr o) ifexists mode xmode (car o))] - [(exclusive nonexclusive) - (check-option who xmode (car o)) - (loop (cdr o) ifexists mode (car o) bmode)] - [(mode) - (if (null? (cdr o)) - ($oops who "mode option requires an argument") - (let ([mode (cadr o)]) - (if (and (fixnum? mode) (fx>= mode 0)) - (loop (cddr o) ifexists mode xmode bmode) - ($oops who "mode argument must be a nonnegative fixnum"))))] - [else ($oops who "invalid option ~s" (car o))]))))) - (set-who! open-input-output-file - (case-lambda - [(s) (oiof who s '())] - [(s o) (oiof who s o)]))) - ) - - ;; make-custom-binary-input/output-port - (let () - (define-syntax make-ready-for-input - (syntax-rules () - [(_ who p_ write!) - (let ([p p_]) - (unless (eq? 0 (binary-port-output-size p)) - (binary-custom-port-flush who p write!) - ;; don't set input-size; it is set only after a read - (set-binary-port-output-size! p 0)))])) - - (module ((make-ready-for-output $make-ready-for-output)) - (define $make-ready-for-output - (lambda (who p get-position set-position!) - (unless (eq? (binary-port-input-size p) 0) - (unless (port-input-empty? p) - (if (not (and get-position set-position!)) - (position-warning who - (if get-position - "cannot set position for write after read on ~s" - "cannot determine position for write after read on ~s") - p) - (set-position! (- (get-position) (binary-port-input-count p))))) - (set-binary-port-input-size! p 0)) - (set-port-eof! p #f) - (set-binary-port-output-size! p - (fx1- (bytevector-length (binary-port-output-buffer p)))))) - - (define-syntax make-ready-for-output - (syntax-rules () - [(_ ?who ?p ?get-position ?set-position!) - (let ([p ?p]) - (when (eq? (binary-port-output-size p) 0) - ($make-ready-for-output ?who p ?get-position ?set-position!)))]))) - - ;; Ports start with a non-ill-defined position. - ;; Unless get-position and set-position! are provided, - ;; doing a buffered read operation makes the position ill-defined. - ;; - ;; A put, put-some or (textual)port-position operation may give - ;; unexpected results when the position is ill-defined. - ;; - ;; A set-port-position is sufficient to make - ;; the position no longer ill-defined. - ;; - ;; Buffered read operations include lookahead, port-eof?, and unget. - ;; Buffered read operations also include get and get-some if buffer-mode is not none. - - (set-who! make-custom-binary-input/output-port - (lambda (id read! write! get-position set-position! close) - (unless (string? id) ($oops who "~s is not a string" id)) - (unless (procedure? read!) ($oops who "~s is not a procedure" read!)) - (unless (procedure? write!) ($oops who "~s is not a procedure" write!)) - (unless (or (not get-position) (procedure? get-position)) - ($oops who "~s is not a procedure or #f" get-position)) - (unless (or (not set-position!) (procedure? set-position!)) - ($oops who "~s is not a procedure or #f" set-position!)) - (unless (or (not close) (procedure? close)) - ($oops who "~s is not a procedure or #f" close)) - (let ([handler - (make-port-handler - [ready? - (lambda (who p) - (assert-not-closed who p) - (make-ready-for-input who p write!) - (or (not (port-input-empty? p)) - (port-flag-eof-set? p) - (read-oops who p "cannot determine ready status")))] - [lookahead - (lambda (who p) - (assert-not-closed who p) - (make-ready-for-input who p write!) - (binary-custom-port-lookahead who p read!))] - [unget - (lambda (who p x) - (assert-not-closed who p) - (make-ready-for-input who p write!) - (binary-custom-port-unget who p x))] - [get - (lambda (who p) - (assert-not-closed who p) - (make-ready-for-input who p write!) - (binary-custom-port-get who p read!))] - [get-some - (lambda (who p bv start count) - (assert-not-closed who p) - (make-ready-for-input who p write!) - (binary-custom-port-get-some who p read! bv start count))] - [clear-input - (lambda (who p) - (assert-not-closed who p) - (binary-custom-port-clear-input who p))] - [put - (lambda (who p x) - (assert-not-closed who p) - (make-ready-for-output who p get-position set-position!) - (binary-custom-port-put who p write! x))] - [put-some - (lambda (who p bv start count) - (assert-not-closed who p) - (make-ready-for-output who p get-position set-position!) - (binary-custom-port-put-some who p write! bv start count))] - [flush - (lambda (who p) - (assert-not-closed who p) - ; binary-custom-port-flush must be a no-op in input mode - (binary-custom-port-flush who p write!))] - [clear-output - (lambda (who p) - (assert-not-closed who p) - (binary-custom-port-clear-output who p))] - [close-port - (lambda (who p) - (unless (port-closed? p) - ; binary-custom-port-flush must be a no-op in input mode - (binary-custom-port-flush who p write!) - (binary-custom-port-close-port who p close)))] - [port-position - (and get-position - (lambda (who p) - (assert-not-closed who p) - (binary-custom-port-port-position in/out who p get-position)))] - [set-port-position! - (and set-position! - (lambda (who p x) - (unless (or (and (fixnum? x) (fx>= x 0)) (and (bignum? x) (>= x 0))) - ($oops who "~s is not a valid position" x)) - (assert-not-closed who p) - (binary-custom-port-flush who p write!) - (set-binary-port-input-size! p 0) ;; junk the buffer data - (set-port-eof! p #f) - (set-position! x)))] - [port-length #f] - [set-port-length! #f] - [port-nonblocking? #f] - [set-port-nonblocking! #f])]) - (let ([bufsiz (custom-port-buffer-size)]) - (let ([p ($make-binary-input/output-port id handler - (make-bytevector bufsiz) - (make-bytevector bufsiz) - #f)]) - ($set-port-flags! p (constant port-flag-block-buffered)) - (set-binary-port-input-size! p 0) - (set-binary-port-output-size! p (fx1- bufsiz)) ;; leave room for put to work - p)))))) - - ;; make-custom-textual-input/output-port - (let () - (define-syntax make-ready-for-input - (syntax-rules () - [(_ who p_ write!) - (let ([p p_]) - (unless (eq? 0 (textual-port-output-size p)) - (textual-custom-port-flush who p write!) - ;; don't set input-size; it is set only after a read - (set-textual-port-output-size! p 0)))])) - - (module ((make-ready-for-output $make-ready-for-output)) - (define $make-ready-for-output - (lambda (who p get-position set-position!) - (unless (eq? (textual-port-input-size p) 0) - (unless (port-input-empty? p) - (position-warning who "cannot set position for write after read on ~s" p)) - (set-textual-port-input-size! p 0)) - (set-port-eof! p #f) - (set-textual-port-output-size! p - (fx1- (string-length (textual-port-output-buffer p)))))) - - (define-syntax make-ready-for-output - (syntax-rules () - [(_ ?who ?p ?get-position ?set-position!) - (let ([p ?p]) - (when (eq? (textual-port-output-size p) 0) - ($make-ready-for-output ?who p ?get-position ?set-position!)))]))) - - ;; Ports start with a non-ill-defined position. - ;; Unless get-position and set-position! are provided, - ;; doing a buffered read operation makes the position ill-defined. - ;; - ;; A put, put-some or (textual)port-position operation may give - ;; unexpected results when the position is ill-defined. - ;; - ;; A set-port-position is sufficient to make - ;; the position no longer ill-defined. - ;; - ;; Buffered read operations include lookahead, port-eof?, and unget. - ;; Buffered read operations also include get and get-some if buffer-mode is not none. - - (set-who! make-custom-textual-input/output-port - (lambda (id read! write! get-position set-position! close) - (unless (string? id) ($oops who "~s is not a string" id)) - (unless (procedure? read!) ($oops who "~s is not a procedure" read!)) - (unless (procedure? write!) ($oops who "~s is not a procedure" write!)) - (unless (or (not get-position) (procedure? get-position)) - ($oops who "~s is not a procedure or #f" get-position)) - (unless (or (not set-position!) (procedure? set-position!)) - ($oops who "~s is not a procedure or #f" set-position!)) - (unless (or (not close) (procedure? close)) - ($oops who "~s is not a procedure or #f" close)) - (let ([handler - (make-port-handler - [ready? - (lambda (who p) - (assert-not-closed who p) - (make-ready-for-input who p write!) - (or (not (port-input-empty? p)) - (port-flag-eof-set? p) - (read-oops who p "cannot determine ready status")))] - [lookahead - (lambda (who p) - (assert-not-closed who p) - (make-ready-for-input who p write!) - (textual-custom-port-lookahead who p write!))] - [unget - (lambda (who p x) - (assert-not-closed who p) - (make-ready-for-input who p write!) - (textual-custom-port-unget who p x))] - [get - (lambda (who p) - (assert-not-closed who p) - (make-ready-for-input who p write!) - (textual-custom-port-get who p read!))] - [get-some - (lambda (who p str start count) - (assert-not-closed who p) - (make-ready-for-input who p write!) - (textual-custom-port-get-some who p read! str start count))] - [clear-input - (lambda (who p) - (assert-not-closed who p) - (textual-custom-port-clear-input who p))] - [put - (lambda (who p x) - (assert-not-closed who p) - (make-ready-for-output who p get-position set-position!) - (textual-custom-port-put who p write! x))] - [put-some - (lambda (who p str start count) - (assert-not-closed who p) - (make-ready-for-output who p get-position set-position!) - (textual-custom-port-put-some who p write! str start count))] - [flush - (lambda (who p) - (assert-not-closed who p) - ; textual-custom-port-flush must be a no-op in input mode - (textual-custom-port-flush who p write!))] - [clear-output - (lambda (who p) - (assert-not-closed who p) - (textual-custom-port-clear-output who p))] - [close-port - (lambda (who p) - (unless (port-closed? p) - ; textual-custom-port-flush must be a no-op in input mode - (textual-custom-port-flush who p write!) - (textual-custom-port-close-port who p close)))] - [port-position - (and get-position - (lambda (who p) - (assert-not-closed who p) - (unless (port-input-empty? p) - (position-warning who - "cannot determine accurate position after read on ~s" - p)) - (textual-custom-port-flush who p write!) - (get-position)))] - [set-port-position! - (and set-position! - (lambda (who p x) - (assert-not-closed who p) - (textual-custom-port-flush who p write!) - (set-textual-port-input-size! p 0) ;; junk the buffer data - (set-port-eof! p #f) - (set-position! x)))] - [port-length #f] - [set-port-length! #f] - [port-nonblocking? #f] - [set-port-nonblocking! #f])]) - (let ([bufsiz (custom-port-buffer-size)]) - (let ([p ($make-textual-input/output-port id handler - (make-string bufsiz) - (make-string bufsiz) - #f)]) - ($set-port-flags! p (constant port-flag-block-buffered)) - ($set-port-flags! p (constant port-flag-bol)) - (set-textual-port-input-size! p 0) - (set-textual-port-output-size! p (fx1- bufsiz)) ;; leave room for put to work - p)))))) - -;;;; 8.3 Simple I/O: (rnrs io simple (6)) - (let () - ;; eof-object in 8.2 - ;; eof-object? in 8.2 - - ;; call-with-input-file in 8.2 (to share helpers) - ;; call-with-output-file in 8.2 (to share helpers) - - ;; input-port? in 8.2 - ;; output-port? in 8.2 - ;; current-input-port in 8.2 - ;; current-output-port in 8.2 - ;; current-error-port in 8.2 - - ;; with-input-from-file in 8.2 (to share helpers) - ;; with-output-to-file in 8.2 (to share helpers) - - ;; open-input-file in 8.2 (to share helpers) - ;; open-output-file in 8.2 (to share helpers) - - (set-who! close-input-port - (lambda (input-port) - (unless (input-port? input-port) - ($oops who "~s is not an input port" input-port)) - (close-port input-port))) - - (set-who! close-output-port - (lambda (output-port) - (unless (output-port? output-port) - ($oops who "~s is not an output port" output-port)) - (close-port output-port))) - ) - - (let () - (define ($block-read who p s count) - (if (fx= count 0) - (if (port-eof? p) (eof-object) 0) - (call-port-handler get-some who p s 0 count))) - (set-who! block-read - (case-lambda - [(p s) - (unless (and (input-port? p) (textual-port? p)) - ($oops who "~s is not a textual input port" p)) - (unless (string? s) - ($oops who "invalid buffer argument ~s" s)) - ($block-read who p s (string-length s))] - [(p s n) - (unless (and (input-port? p) (textual-port? p)) - ($oops who "~s is not a textual input port" p)) - (unless (string? s) ($oops who "invalid buffer argument ~s" s)) - (unless (and (fixnum? n) (fx<= 0 n (string-length s))) - ($oops who "invalid count argument ~s" n)) - ($block-read who p s n)]))) - - (let () - (define ($block-write who p s count) - (let loop ([i 0] [count count]) - (unless (fx= count 0) - (let ([n (call-port-handler put-some who p s i count)]) - (loop (fx+ i n) (fx- count n))))) - (call-port-handler flush who p)) - (set-who! block-write - (case-lambda - [(p s) - (unless (and (output-port? p) (textual-port? p)) - ($oops who "~s is not a textual output port" p)) - (unless (string? s) ($oops who "invalid buffer argument ~s" s)) - ($block-write who p s (string-length s))] - [(p s n) - (unless (and (output-port? p) (textual-port? p)) - ($oops who "~s is not a textual output port" p)) - (unless (string? s) ($oops who "invalid buffer argument ~s" s)) - (unless (and (fixnum? n) (fx<= 0 n (string-length s))) - ($oops who "invalid count argument ~s" n)) - ($block-write who p s n)]))) - - (let () - (define ($char-ready? input-port who) - (or (not (port-input-empty? input-port)) - (port-flag-eof-set? input-port) - (call-port-handler ready? who input-port))) - (set-who! char-ready? - (case-lambda - [() ($char-ready? (current-input-port) who)] - [(input-port) - (unless (and (input-port? input-port) (textual-port? input-port)) - ($oops who "~s is not a textual input port" input-port)) - ($char-ready? input-port who)]))) - - (set-who! clear-input-port - (rec clear-input-port - (case-lambda - [() (let ([p (current-input-port)]) - (call-port-handler clear-input who p))] - [(p) - (unless (input-port? p) - ($oops who "~s is not an input port" p)) - (call-port-handler clear-input who p)]))) - - (set-who! clear-output-port - (rec clear-output-port - (case-lambda - [() (let ([p (current-output-port)]) - (call-port-handler clear-output who p))] - [(p) - (unless (output-port? p) - ($oops who "~s is not an output port" p)) - (call-port-handler clear-output who p)]))) - - (set-who! fresh-line - (rec fresh-line - (case-lambda - [() (fresh-line (current-output-port))] - [(p) - (unless (and (output-port? p) (textual-port? p)) - ($oops who "~s is not a textual output port" p)) - (assert-not-closed who p) - (unless ($textual-port-bol? p) - (call-port-handler put who p #\newline))]))) - - (set-who! port-bol? - (lambda (p) - (unless (and (output-port? p) (textual-port? p)) - ($oops who "~s is not a textual output port" p)) - (assert-not-closed who p) - ($textual-port-bol? p))) - - (let () - (define (binary-fd-port? bp) - ($port-flags-set? bp (constant port-flag-file))) - - (set-who! file-port? - (lambda (p) - (unless (port? p) ($oops who "~s is not a port" p)) - (if (binary-port? p) - (binary-fd-port? p) - (let ([info ($port-info p)]) - (and (codec-info? info) (binary-fd-port? (codec-info-bp info))))))) - - (set-who! port-file-descriptor - (let () - (define gzfile-fd (foreign-procedure "(cs)gzxfile_fd" (ptr) int)) - (define (binary-port-fd p bp) - (unless (binary-fd-port? bp) - ($oops who "~s is not a file port" p)) - (let ([x ($port-info bp)]) - (if (port-gz-mode bp) - (gzfile-fd x) - x))) - (lambda (p) - (unless (port? p) ($oops who "~s is not a port" p)) - (if (binary-port? p) - (binary-port-fd p p) - (let ([info ($port-info p)]) - (unless (codec-info? info) - ($oops who "~s is not a file port" p)) - (binary-port-fd p (codec-info-bp info)))))))) - - (let () - (define $generic-port-handler - (make-port-handler - [ready? - (lambda (who p) - (assert-not-closed who p) - (and (($port-info p) 'char-ready? p) #t))] - [lookahead - (lambda (who p) - (assert-not-closed who p) - (let ([c (($port-info p) 'peek-char p)]) - (unless (or (char? c) (eof-object? c)) - ($oops 'generic-port-handler "invalid peek-char return value ~s" c)) - c))] - [unget - (lambda (who p x) - (assert-not-closed who p) - (unless (eof-object? x) (($port-info p) 'unread-char x p)) - (void))] - [get - (lambda (who p) - (assert-not-closed who p) - (let ([c (($port-info p) 'read-char p)]) - (unless (or (char? c) (eof-object? c)) - ($oops 'generic-port-handler "invalid read-char return value ~s" c)) - c))] - [get-some - (lambda (who p st start count) - (if (= start 0) - (let ([n (($port-info p) 'block-read p st count)]) - (unless (or (and (fixnum? n) (not ($fxu< count n))) - (eof-object? n)) - ($oops 'generic-port-handler "invalid block-read return value ~s on ~s" n p)) - n) - (let ([tmp (make-string count)]) - (let ([n (($port-info p) 'block-read p tmp count)]) - (cond - [(and (fixnum? n) (not ($fxu< count n))) - (string-copy! tmp 0 st start n) - n] - [(eof-object? n) n] - [else ($oops 'generic-port-handler "invalid block-read return value ~s on ~s" n p)])))))] - [clear-input - (lambda (who p) - (assert-not-closed who p) - (($port-info p) 'clear-input-port p) - (void))] - [put - (lambda (who p x) - (assert-not-closed who p) - (($port-info p) 'write-char x p) - (void))] - [put-some - (lambda (who p st start count) - (assert-not-closed who p) - (if (= start 0) - (($port-info p) 'block-write p st count) - (let ([tmp (make-string count)]) - (string-copy! st start tmp 0 count) - (($port-info p) 'block-write p tmp count))) - count)] - [flush - (lambda (who p) - (assert-not-closed who p) - (($port-info p) 'flush-output-port p) - (void))] - [clear-output - (lambda (who p) - (assert-not-closed who p) - (($port-info p) 'clear-output-port p) - (void))] - [close-port - (lambda (who p) - (unless (port-closed? p) - (($port-info p) 'close-port p)) - (void))] - [port-position - (lambda (who p) - (assert-not-closed who p) - (($port-info p) 'file-position p))] - [set-port-position! - (lambda (who p x) - (assert-not-closed who p) - (($port-info p) 'file-position p x))] - [port-length - (lambda (who p) - (assert-not-closed who p) - (($port-info p) 'file-length p))] - [set-port-length! - (lambda (who p pos) - (assert-not-closed who p) - (($port-info p) 'truncate-file p pos))] - [port-nonblocking? #f] - [set-port-nonblocking! #f])) - - (define (set-name p) - (guard (c [#t (void)]) - (let ([name (($port-info p) 'port-name p)]) - (when (string? name) (set-port-name! p name)))) - p) - - (set-who! make-input-port - (lambda (handler buffer) - (unless (procedure? handler) - (if (and (fixnum? handler) (fx>= handler 0)) - ($oops who "fixnum handler no longer supported; use open-fd-input-port") - ($oops who "~s is not a procedure" handler))) - (unless (string? buffer) ($oops who "~s is not a string" buffer)) - (set-name - ($make-textual-input-port "generic" - $generic-port-handler - buffer handler)))) - - (set-who! make-output-port - (lambda (handler buffer) - (unless (procedure? handler) - (if (and (fixnum? handler) (fx>= handler 0)) - ($oops who "fixnum handler no longer supported; use open-fd-input-port") - ($oops who "~s is not a procedure" handler))) - (unless (string? buffer) ($oops who "~s is not a string" buffer)) - (set-name - ($make-textual-output-port "generic" - $generic-port-handler - buffer handler)))) - - (set-who! make-input/output-port - (lambda (handler ibuffer obuffer) - (unless (procedure? handler) - (if (and (fixnum? handler) (fx>= handler 0)) - ($oops who "fixnum handler no longer supported; use open-fd-input-port") - ($oops who "~s is not a procedure" handler))) - (unless (string? ibuffer) ($oops who "~s is not a string" ibuffer)) - (unless (string? obuffer) ($oops who "~s is not a string" obuffer)) - (set-name - ($make-textual-input/output-port "generic" - $generic-port-handler - ibuffer obuffer handler)))) - - (set-who! port-handler - (let () - (define check - (lambda (msg n) - (unless (cond - [(assq n - '((1 char-ready? clear-input-port clear-output-port close-port - file-length file-position flush-output-port peek-char - port-name read-char) - (2 file-position unread-char write-char) - (3 block-read block-write))) => - (lambda (ls) (memq msg (cdr ls)))] - [else #f]) - ($oops 'non-generic-port-handler - "cannot handle message ~s with argument count ~s" - msg n)))) - (define non-generic-port-handler - (lambda (msg . args) - (check msg (length args)) - (apply ($top-level-value msg) args))) - (lambda (p) - (unless (port? p) ($oops who "~s is not a port" p)) - (if (eq? ($port-handler p) $generic-port-handler) - ($port-info p) - non-generic-port-handler)))) - ) - - (record-writer (type-descriptor codec) - (lambda (x p wr) - (fprintf p "#" (codec-name x)))) - - (record-writer (type-descriptor transcoder) - (lambda (x p wr) - (fprintf p "#" - (codec-name ($transcoder-codec x)) - ($transcoder-eol-style x) - ($transcoder-error-handling-mode x)))) - - (set-who! #(r6rs: current-input-port) - (lambda () - (#2%current-input-port))) - - (set-who! #(r6rs: current-output-port) - (lambda () - (#2%current-output-port))) - - (set-who! #(r6rs: current-error-port) - (lambda () - (#2%current-error-port))) - - ; thread-safe transcript-on, transcript-off, transcript-cafe - (let () - (define-record-type xscript-info - (nongenerative) - (opaque #t) - (sealed #t) - (fields ip op xp (mutable ungot)) - (protocol - (lambda (new) - (lambda (ip op xp) - (new ip op xp '()))))) - - (module (make-xscript-port xscript-port? constituent-ports) - (define-syntax with-xscript-info - (syntax-rules () - [(_ (p ip op xp ungot) e1 e2 ...) - (andmap identifier? #'(ip op xp ungot)) - (let ([x ($port-info p)]) - (let ([ip (xscript-info-ip x)] - [op (xscript-info-op x)] - [xp (xscript-info-xp x)]) - (define-syntax ungot - (identifier-syntax - [id (xscript-info-ungot x)] - [(set! id e) (xscript-info-ungot-set! x e)])) - e1 e2 ...))])) - - (define-syntax thread-safe - (syntax-rules () - [(_ (p ip op xp ungot) e1 e2 ...) - (with-xscript-info (p ip op xp ungot) - (with-tc-mutex e1 e2 ...))])) - - (define-syntax call-xp-handler - (syntax-rules () - [(_ msg who xp arg ...) - (identifier? #'xp) - (and (not (port-closed? xp)) - (call-port-handler msg who xp arg ...))])) - - (define slurp-input - (lambda (who p) - (with-xscript-info (p ip op xp ungot) - (let ([tognu (reverse ungot)]) - (guard (c [#t (void)]) ; guard ready? calls - (let loop () - (when (call-port-handler ready? who ip) - (let ([c (call-port-handler get who ip)]) - (unless (eof-object? c) - (call-xp-handler put who xp c) - (set! tognu (cons c tognu)) - (loop)))))) - (set! ungot (reverse tognu)))))) - - ; similar in structure to thread-safe console-port handler - (define xscript-handler - (make-port-handler - [ready? - (lambda (who p) - (thread-safe (p ip op xp ungot) - (or (not (null? ungot)) - (begin - (call-port-handler flush who op) - (call-port-handler ready? who ip)))))] - [lookahead - (lambda (who p) - (thread-safe (p ip op xp ungot) - (if (not (null? ungot)) - (car ungot) - (begin - (call-port-handler flush who op) - (let ([c (call-port-handler get who ip)]) - (set! ungot (list c)) - (unless (eof-object? c) (call-xp-handler put who xp c)) - c)))))] - [unget - (lambda (who p x) - (thread-safe (p ip op xp ungot) - (set! ungot (cons x ungot))))] - [get - (lambda (who p) - (thread-safe (p ip op xp ungot) - (if (not (null? ungot)) - (let ([c (car ungot)]) - (set! ungot (cdr ungot)) - c) - (begin - (call-port-handler flush who op) - (let ([c (call-port-handler get who ip)]) - (unless (eof-object? c) (call-xp-handler put who xp c)) - c)))))] - [get-some - (lambda (who p str start count) - (thread-safe (p ip op xp ungot) - (if (and (fx> count 0) (not (null? ungot))) - (let ([c (car ungot)]) - (set! ungot (cdr ungot)) - (if (eof-object? c) - c - (begin (string-set! str start c) 1))) - (begin - (call-port-handler flush who op) - (let ([count (call-port-handler get-some who ip str start count)]) - (unless (or (eof-object? count) (fx= count 0)) - (call-xp-handler put-some who xp str start count)) - count)))))] - [clear-input - (lambda (who p) - (thread-safe (p ip op xp ungot) - (set! ungot '()) - (call-port-handler clear-input who ip)))] - [put - (lambda (who p x) - (thread-safe (p ip op xp ungot) - (slurp-input who p) - (call-port-handler put who op x) - (call-xp-handler put who xp x) - (if ($textual-port-bol? op) - ($set-port-flags! p (constant port-flag-bol)) - ($reset-port-flags! p (constant port-flag-bol)))))] - [put-some - (lambda (who p str start count) - (thread-safe (p ip op xp ungot) - (slurp-input who p) - (let ([count (call-port-handler put-some who op str start count)]) - (let f ([start start] [count count]) - (unless (fx= count 0) - (let ([n (call-xp-handler put-some who xp str start count)]) - (and n (f (fx+ start n) (fx- count n)))))) - (if ($textual-port-bol? op) - ($set-port-flags! p (constant port-flag-bol)) - ($reset-port-flags! p (constant port-flag-bol))) - count)))] - [flush - (lambda (who p) - (thread-safe (p ip op xp ungot) - (call-port-handler flush who op) - (call-xp-handler flush who xp)))] - [clear-output - (lambda (who p) - ; clearing may put op and xp out of sync, so just flush instead - (thread-safe (p ip op xp ungot) - (call-port-handler flush who op) - (call-xp-handler flush who xp)))] - [close-port - (lambda (who p) - ; refuse to close transcript ports, like console ports---just flush instead - (thread-safe (p ip op xp ungot) - (call-port-handler flush who op) - (call-xp-handler flush who xp)))] - [port-position #f] - [set-port-position! #f] - [port-length #f] - [set-port-length! #f] - [port-nonblocking? #f] - [set-port-nonblocking! #f])) - - (define (make-xscript-port ip op xp) - (let ([p ($make-textual-input/output-port - "transcript" xscript-handler "" "" - (make-xscript-info ip op xp))]) - (when ($port-flags-set? ip (constant port-flag-r6rs)) - ($set-port-flags! p (constant port-flag-r6rs))) - (when ($port-flags-set? ip (constant port-flag-fold-case)) - ($set-port-flags! p (constant port-flag-fold-case))) - (when ($port-flags-set? ip (constant port-flag-no-fold-case)) - ($set-port-flags! p (constant port-flag-no-fold-case))) - (when ($textual-port-bol? op) - ($set-port-flags! p (constant port-flag-bol))) - p)) - - (define xscript-port? - (lambda (p) - (eq? ($port-handler p) xscript-handler))) - - (define constituent-ports - (lambda (p) - (with-xscript-info (p ip op xp ungot) - (values ip op xp))))) - - (set-who! $xscript-port? (lambda (p) (xscript-port? p))) - - (set-who! $constituent-ports (lambda (p) (constituent-ports p))) - - (set-who! transcript-on - (lambda (pathname) - (unless (string? pathname) ($oops who "~s is not a string" pathname)) - (let ([ip (console-input-port)] [op (console-output-port)]) - (when (and (guard (c [#t #f]) (char-ready? ip)) - (eqv? (peek-char ip) #\newline)) - (read-char ip)) - (let ([xp ($open-file-output-port who pathname (file-options replace) - (buffer-mode block) - (current-transcoder))]) - (let ([p (make-xscript-port ip op xp)]) - (when (eq? (console-error-port) op) (console-error-port p)) - (when (eq? (current-input-port) ip) (current-input-port p)) - (when (eq? (current-output-port) op) (current-output-port p)) - (when (eq? (current-error-port) op) (current-error-port p)) - (when (eq? (trace-output-port) op) (trace-output-port p)) - (console-input-port p) - (console-output-port p))) - (printf "Chez Scheme Transcript [~a]\n" (date-and-time))))) - - (set-who! transcript-off - (lambda () - (cond - [(ormap (lambda (p) (and (xscript-port? p) p)) - (list (console-input-port) - (console-output-port) - (console-error-port) - (current-input-port) - (current-output-port) - (current-error-port) - (trace-output-port))) => - (lambda (p) - (let-values ([(ip op xp) (constituent-ports p)]) - (when (eq? (console-input-port) p) (console-input-port ip)) - (when (eq? (console-output-port) p) (console-output-port op)) - (when (eq? (console-error-port) p) (console-error-port op)) - (when (eq? (current-input-port) p) (current-input-port ip)) - (when (eq? (current-output-port) p) (current-output-port op)) - (when (eq? (current-error-port) p) (current-error-port op)) - (when (eq? (trace-output-port) p) (trace-output-port op)) - (flush-output-port p) - (close-port xp)))]))) - - (set-who! transcript-cafe - (lambda (pathname) - (unless (string? pathname) ($oops who "~s is not a string" pathname)) - (let ([ip (console-input-port)] [op (console-output-port)]) - (when (and (guard (c [#t #f]) (char-ready? (console-input-port))) - (eqv? (peek-char (console-input-port)) #\newline)) - (read-char (console-input-port))) - (let ([xp ($open-file-output-port who pathname (file-options replace) - (buffer-mode block) - (current-transcoder))]) - (let ([p (make-xscript-port ip op xp)]) - (with-values - (dynamic-wind - (lambda () - (when (eq? (console-input-port) ip) (console-input-port p)) - (when (eq? (console-output-port) op) (console-output-port p)) - (when (eq? (console-error-port) op) (console-error-port p)) - (when (eq? (current-input-port) ip) (current-input-port p)) - (when (eq? (current-output-port) op) (current-output-port p)) - (when (eq? (current-error-port) op) (current-error-port p)) - (when (eq? (trace-output-port) op) (trace-output-port p))) - (lambda () - (printf "Chez Scheme Transcript [~a]\n" (date-and-time)) - (new-cafe)) - (lambda () - (when (eq? (console-input-port) p) (console-input-port ip)) - (when (eq? (console-output-port) p) (console-output-port op)) - (when (eq? (console-error-port) p) (console-error-port op)) - (when (eq? (current-input-port) p) (current-input-port ip)) - (when (eq? (current-output-port) p) (current-output-port op)) - (when (eq? (current-error-port) p) (current-error-port op)) - (when (eq? (trace-output-port) p) (trace-output-port op)) - (flush-output-port p))) - (lambda vals - (close-port xp) - (apply values vals))))))))) - - #;(let () - (define debug-port-handler - (make-port-handler - [ready? (lambda (who p) (input-port-ready? ($port-info p)))] - [lookahead - (lambda (who p) - (let ([b (lookahead-u8 ($port-info p))]) - (if (eof-object? b) b (integer->char b))))] - [unget - (lambda (who p x) - (unget-u8 ($port-info p) (if (eof-object? x) x (char->integer x))))] - [get - (lambda (who p) - (let ([b (get-u8 ($port-info p))]) - (if (eof-object? b) b (integer->char b))))] - [get-some - (lambda (who p str start count) - (if (fx= count 0) - 0 - (let ([b (get-u8 ($port-info p))]) - (if (eof-object? b) - b - (begin - (string-set! str start (integer->char b)) - 1)))))] - [clear-input - (lambda (who p) - (clear-input-port ($port-info p)))] - [put - (lambda (who p x) - (put-u8 ($port-info p) (char->integer x)))] - [put-some - (lambda (who p str start count) - (if (fx= count 0) - 0 - (begin - (put-u8 ($port-info p) (char->integer (string-ref str start))) - 1)))] - [flush - (lambda (who p) - (flush-output-port ($port-info p)))] - [clear-output - (lambda (who p) - (clear-output-port ($port-info p)))] - [close-port (lambda (who p) (flush-output-port ($port-info p)) (void))] - [port-position - (lambda (who p) - (port-position ($port-info p)))] - [set-port-position! - (lambda (who p x) - (set-port-position! ($port-info p) x))] - [port-length - (lambda (who p) - (port-length ($port-info p)))] - [set-port-length! - (lambda (who p x) - (set-port-length! ($port-info p) x))] - [port-nonblocking? #f] - [set-port-nonblocking! #f])) - (set! $console-input-port ($make-textual-input-port "debug-stdin" debug-port-handler "" (standard-input-port (buffer-mode block)))) - (set! $console-output-port ($make-textual-output-port "debug-stdout" debug-port-handler "" (standard-output-port (buffer-mode none)))) - (set! $console-output-port ($make-textual-output-port "debug-stderr" debug-port-handler "" (standard-error-port (buffer-mode none))))) - - (let ([ip (standard-input-port (buffer-mode block) (current-transcoder))] - [op (standard-output-port (buffer-mode line) (current-transcoder))]) - (define same-device? (foreign-procedure "(cs)same_devicep" (int int) boolean)) - (if-feature pthreads - (let () - ; it would be nice to make port->thread-safe-port available generally, - ; but since it grabs the tc mutex, making it public would be - ; inappropriate. tried using a fresh mutex, but the thread mat - ; that runs compile-file freezes, possibly due to a deadlock where one - ; thread has the tc mutex and another has the port's mutex. should - ; revisit... - (define (make-thread-safe-handler ip op) - (make-port-handler - [ready? - (and ip - (lambda (who p) - (with-tc-mutex - (call-port-handler flush who op) - (call-port-handler ready? who ip))))] - [lookahead - (and ip - (lambda (who p) - (with-tc-mutex - (call-port-handler flush who op) - (call-port-handler lookahead who ip))))] - [unget - (and ip - (lambda (who p x) - (with-tc-mutex - (call-port-handler unget who ip x))))] - [get - (and ip - (lambda (who p) - (with-tc-mutex - (call-port-handler flush who op) - (call-port-handler get who ip))))] - [get-some - (and ip - (lambda (who p str start count) - (with-tc-mutex - (call-port-handler flush who op) - (call-port-handler get-some who ip str start count))))] - [clear-input - (and ip - (lambda (who p) - (with-tc-mutex - (call-port-handler clear-input who ip))))] - [put - (and op - (lambda (who p x) - (with-tc-mutex - (call-port-handler put who op x) - (if ($textual-port-bol? op) - ($set-port-flags! p (constant port-flag-bol)) - ($reset-port-flags! p (constant port-flag-bol))))))] - [put-some - (and op - (lambda (who p str start count) - (with-tc-mutex - (let ([count (call-port-handler put-some who op str start count)]) - (if ($textual-port-bol? op) - ($set-port-flags! p (constant port-flag-bol)) - ($reset-port-flags! p (constant port-flag-bol))) - count))))] - [flush - (and op - (lambda (who p) - (with-tc-mutex - (call-port-handler flush who op))))] - [clear-output - (and op - (lambda (who p) - (with-tc-mutex - (call-port-handler clear-output who op))))] - [close-port ; refuse to close console ports---just flush instead - (if op - (lambda (who p) - (with-tc-mutex - (call-port-handler flush who op))) - (lambda (who p) - (void)))] - [port-position #f] - [set-port-position! #f] - [port-length #f] - [set-port-length! #f] - [port-nonblocking? #f] - [set-port-nonblocking! #f])) - (define thread-safe-console-input/output-port - (lambda (name ip op) - (let ([p ($make-textual-input/output-port name (make-thread-safe-handler ip op) "" "" #f)]) - (when ($port-flags-set? ip (constant port-flag-r6rs)) - ($set-port-flags! p (constant port-flag-r6rs))) - (when ($port-flags-set? ip (constant port-flag-fold-case)) - ($set-port-flags! p (constant port-flag-fold-case))) - (when ($port-flags-set? ip (constant port-flag-no-fold-case)) - ($set-port-flags! p (constant port-flag-no-fold-case))) - (when ($textual-port-bol? op) - ($set-port-flags! p (constant port-flag-bol))) - p))) - (define thread-safe-console-output-port - (lambda (name op) - (let ([p ($make-textual-output-port name (make-thread-safe-handler #f op) "" #f)]) - (when ($textual-port-bol? op) - ($set-port-flags! p (constant port-flag-bol))) - p))) - (let ([p (thread-safe-console-input/output-port "stdin/out" ip op)]) - (set! $console-input-port p) - (set! $console-output-port p) - (set! $console-error-port - (if (same-device? 1 2) - p - (thread-safe-console-output-port "stderr" (standard-error-port (buffer-mode line) (current-transcoder))))))) - (begin - (set! $console-input-port ip) - (set! $console-output-port op) - (set! $console-error-port - (if (same-device? 1 2) - op - (standard-error-port (buffer-mode line) (current-transcoder))))))) - - (current-input-port $console-input-port) - (current-output-port $console-output-port) - (current-error-port $console-error-port) - (set-who! console-input-port - (make-parameter - $console-input-port - (lambda (ip) - (unless (and (input-port? ip) (textual-port? ip)) - ($oops who "~s is not a textual input port" ip)) - ip))) - (set-who! console-output-port - (make-parameter - $console-output-port - (lambda (op) - (unless (and (output-port? op) (textual-port? op)) - ($oops who "~s is not a textual output port" op)) - op))) - (set-who! console-error-port - (make-parameter - $console-error-port - (lambda (op) - (unless (and (output-port? op) (textual-port? op)) - ($oops who "~s is not a textual output port" op)) - op))) - (set! $io-init - (lambda () - (clear-open-files) - ; reregister the console ports - (register-open-file $console-input-port) - (register-open-file $console-output-port) - (unless (eq? $console-error-port $console-output-port) - (register-open-file $console-error-port)))) - - ; utf8->string, etc., are in prims.ss, since they are used by - ; foreign procedures argument and return values -) -) diff --git a/ta6ob/s/io.ta6ob b/ta6ob/s/io.ta6ob deleted file mode 100644 index 0e84822..0000000 Binary files a/ta6ob/s/io.ta6ob and /dev/null differ diff --git a/ta6ob/s/layout.ss b/ta6ob/s/layout.ss deleted file mode 100644 index a46b552..0000000 --- a/ta6ob/s/layout.ss +++ /dev/null @@ -1,111 +0,0 @@ -;;; layout.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(define compute-field-offsets - ; type-disp is the offset from the ptr to the object's true address - ; ls is a list of field descriptors - (lambda (who type-disp ls) - (define parse-field - (lambda (f) - (define supported-type - (lambda (x) - (let ([x (filter-foreign-type x)]) - (and (memq x (record-datatype list)) x)))) - (define (err) ($oops who "invalid field specifier ~s" f)) - (define (s0 f) - (cond - [(symbol? f) (values f #t 'scheme-object 'scheme-object 1)] - [(list? f) (s1 f)] - [else (err)])) - (define (s1 f) - (cond - [(null? f) (err)] - [(null? (cdr f)) - (if (symbol? (car f)) - (values (car f) #t 'scheme-object 'scheme-object 1) - (err))] - [(eq? (car f) 'immutable) (s2 (cdr f) #f)] - [(eq? (car f) 'mutable) (s2 (cdr f) #t)] - [else (s2 f #t)])) - (define (s2 f mutable?) - (cond - [(null? f) (err)] - [(null? (cdr f)) - (if (symbol? (car f)) - (values (car f) mutable? 'scheme-object 'scheme-object 1) - (err))] - [(supported-type (car f)) => - (lambda (real-type) (s3 (cdr f) mutable? (car f) real-type))] - [else (s3 f mutable? 'scheme-object 'scheme-object)])) - (define (s3 f mutable? type real-type) - (cond - [(null? f) (err)] - [(symbol? (car f)) (s4 (cdr f) mutable? type real-type (car f))] - [else (err)])) - (define (s4 f mutable? type real-type name) - (cond - [(null? f) (values name mutable? type real-type 1)] - [(and (integer? (car f)) (nonnegative? (car f))) - (values name mutable? type real-type (car f))] - [else (err)])) - (s0 f))) - (define type->bytes - (lambda (ty) - (define-syntax ->bytes - (syntax-rules () ((_ type bytes pred) bytes))) - (record-datatype cases ty ->bytes - ($oops who "unrecognized type ~s" ty)))) - (define get-max-alignment - (lambda (ty) - (case ty - [(single-float double-float) (constant max-float-alignment)] - [else (constant max-integer-alignment)]))) - (define align - (lambda (n bytes type) - (let ([k (gcd (get-max-alignment type) bytes)]) - (logand (+ n (fx- k 1)) (fx- k))))) - (with-values - (let f ((ls ls) (byte 0)) - (if (null? ls) - (values 0 0 '() byte) ; pm, mpm, flds, size - (with-values (parse-field (car ls)) - (lambda (name mutable? type real-type len) - (let* ((bytes (type->bytes real-type)) - ; align even if len is zero to give element its - ; proper alignment, since zero at the end can mean - ; variable-length - (byte (align byte bytes real-type))) - (with-values (f (cdr ls) (+ byte (* bytes len))) - (lambda (pm mpm flds size) - (let ((flds (cons (make-fld name mutable? type (+ type-disp byte)) flds))) - (if (eq? real-type 'scheme-object) - (let ((m (ash (- (ash 1 len) 1) - (fxsrl byte (constant log2-ptr-bytes))))) - (values - (+ pm m) - (if mutable? (+ mpm m) mpm) - flds - size)) - (values pm mpm flds size)))))))))) - (lambda (pm mpm flds size) - (define sanitize-mask - ; if bits are set for each word, return mask of -1 - ; to give gc a quick test for pure vs. impure - (lambda (m size) - (if (= (- (ash 1 (quotient (+ size -1 (constant ptr-bytes)) (constant ptr-bytes))) 1) m) - -1 - m))) - (values (sanitize-mask pm size) mpm flds size))))) - diff --git a/ta6ob/s/library.ss b/ta6ob/s/library.ss deleted file mode 100644 index f9f2988..0000000 --- a/ta6ob/s/library.ss +++ /dev/null @@ -1,1637 +0,0 @@ -;;; library.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; Library entries should not contain references that could themselves -;;; compile into library entries. (Actually it will work as long as the -;;; use follows the definition, but...) Consequently they should be -;;; kept simple. - -(eval-when (compile) - (optimize-level 3) - (generate-inspector-information #f) - ($compile-profile #f) - ($optimize-closures #t) - (run-cp0 (default-run-cp0)) - (generate-interrupt-trap #f) - ($track-dynamic-closure-counts #f)) - -(eval-when (compile) -(define-syntax define-library-entry - (lambda (x) - (define name->libspec - (lambda (name) - (or ($sgetprop name '*libspec* #f) - ($oops 'define-library-entry "~s is undefined" name)))) - (define name->does-not-expect-headroom-libspec - (lambda (name) - (or ($sgetprop name '*does-not-expect-headroom-libspec* #f) - ($oops 'define-library-entry "~s is missing no headroom libspec" name)))) - (syntax-case x () - [(_ (name . args) e1 e2 ...) - (identifier? #'name) - (let ([libspec (name->libspec (datum name))] - [does-not-expect-headroom-libspec (name->does-not-expect-headroom-libspec (datum name))]) - (with-syntax ([index (libspec-index libspec)] - [does-not-expect-headroom-index (libspec-index does-not-expect-headroom-libspec)] - [libspec (datum->syntax #'name libspec)] - [does-not-expect-headroom-libspec (datum->syntax #'name does-not-expect-headroom-libspec)]) - ; NB: we are duplicating code here, because looking up the library entry fails on startup. - #'(begin - ($install-library-entry - 'index - (case-lambda libspec (args e1 e2 ...))) - ($install-library-entry - 'does-not-expect-headroom-index - (case-lambda does-not-expect-headroom-libspec (args e1 e2 ...))))))]))) -) - -; we can't evaluate any dirty writes (eg. defines) until scan-remembered-set -; is ready, so install it up front. -(let ([install-library-entry ($hand-coded '$install-library-entry-procedure)]) - (install-library-entry - (libspec-index (lookup-libspec scan-remembered-set)) - ($hand-coded 'scan-remembered-set))) - -(let ([install-library-entry ($hand-coded '$install-library-entry-procedure)]) - ; no top-level defines before this point, or the linker won't have - ; nonprocedure-code to insert in pvalue slot - (install-library-entry - (libspec-index (lookup-libspec nonprocedure-code)) - ($hand-coded 'nonprocedure-code))) - -(define $foreign-entry ($hand-coded '$foreign-entry-procedure)) -(define $install-library-entry - ($hand-coded '$install-library-entry-procedure)) - -(eval-when (compile) -(define-syntax define-hand-coded-library-entry - (lambda (x) - (syntax-case x () - ((_ name) - (identifier? #'name) - #'($install-library-entry (libspec-index (lookup-libspec name)) - ($hand-coded 'name)))))) -) - -(define-hand-coded-library-entry get-room) -(define-hand-coded-library-entry call-error) -(define-hand-coded-library-entry dooverflood) -(define-hand-coded-library-entry dooverflow) -(define-hand-coded-library-entry dorest0) -(define-hand-coded-library-entry dorest1) -(define-hand-coded-library-entry dorest2) -(define-hand-coded-library-entry dorest3) -(define-hand-coded-library-entry dorest4) -(define-hand-coded-library-entry dorest5) -;;; doargerr must come before dounderflow* -(define-hand-coded-library-entry doargerr) - -;;; dounderflow* must come before dounderflow -(define-library-entry (dounderflow* k args) - ($do-wind ($current-winders) ($continuation-winders k)) - (cond - ((null? args) (k)) - ((null? (cdr args)) (k (car args))) - (else (#2%apply k args)))) ; library apply not available yet - -;;; dounderflow & nuate must come before callcc -(define-hand-coded-library-entry dounderflow) -(define-hand-coded-library-entry nuate) -(define-hand-coded-library-entry callcc) -(define-hand-coded-library-entry call1cc) -(define-hand-coded-library-entry dofargint32) -(define-hand-coded-library-entry dofretint32) -(define-hand-coded-library-entry dofretuns32) -(define-hand-coded-library-entry dofargint64) -(define-hand-coded-library-entry dofretint64) -(define-hand-coded-library-entry dofretuns64) -(define-hand-coded-library-entry dofretu8*) -(define-hand-coded-library-entry dofretu16*) -(define-hand-coded-library-entry dofretu32*) -(define-hand-coded-library-entry domvleterr) -(define-hand-coded-library-entry values-error) -(define-hand-coded-library-entry bytevector=?) - -(define $instantiate-code-object ($hand-coded '$instantiate-code-object)) - -;;; set up $nuate for overflow -(define $nuate ($closure-code (call/1cc (lambda (k) k)))) - -(set! #{raw-ref-count bhowt6w0coxl0s2y-1} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) -(set! #{raw-create-count bhowt6w0coxl0s2y-2} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) -(set! #{raw-alloc-count bhowt6w0coxl0s2y-3} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) -(set! #{ref-count bhowt6w0coxl0s2y-4} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) -(set! #{pair-create-count bhowt6w0coxl0s2y-5} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) -(set! #{vector-create-count bhowt6w0coxl0s2y-6} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) -(set! #{vector-alloc-count bhowt6w0coxl0s2y-8} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) -(set! #{padded-vector-alloc-count bhowt6w0coxl0s2y-11} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) -(set! #{closure-create-count bhowt6w0coxl0s2y-7} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) -(set! #{closure-alloc-count bhowt6w0coxl0s2y-9} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) -(set! #{padded-closure-alloc-count bhowt6w0coxl0s2y-10} '#[#{profile-counter b5vnnom9h4o4uny0-2} 0]) - -(let () - (include "hashtable-types.ss") - (set! $eq-ht-rtd (record-type-descriptor eq-ht)) - (set! $symbol-ht-rtd (record-type-descriptor symbol-ht))) - -(define-library-entry (cfl* x y) - ;; a+bi * c+di => ac-bd + (ad+bc)i - ;; spurious overflows - (cond - [(flonum? x) - (if (flonum? y) - (fl* x y) - (fl-make-rectangular - (fl* x ($inexactnum-real-part y)) - (fl* x ($inexactnum-imag-part y))))] - [(flonum? y) - (fl-make-rectangular - (fl* ($inexactnum-real-part x) y) - (fl* ($inexactnum-imag-part x) y))] - [else - (let ([a ($inexactnum-real-part x)] [b ($inexactnum-imag-part x)] - [c ($inexactnum-real-part y)] [d ($inexactnum-imag-part y)]) - (fl-make-rectangular - (fl- (fl* a c) (fl* b d)) - (fl+ (fl* a d) (fl* b c))))])) - -(define-library-entry (cfl+ x y) - ;; a+bi + c+di => (a+c) + (b+d)i - (cond - [(flonum? x) - (if (flonum? y) - (fl+ x y) - (fl-make-rectangular - (fl+ x ($inexactnum-real-part y)) - ($inexactnum-imag-part y)))] - [(flonum? y) - (fl-make-rectangular - (fl+ ($inexactnum-real-part x) y) - ($inexactnum-imag-part x))] - [else - (fl-make-rectangular - (fl+ ($inexactnum-real-part x) ($inexactnum-real-part y)) - (fl+ ($inexactnum-imag-part x) ($inexactnum-imag-part y)))])) - -(define-library-entry (cfl- x y) - ;; a+bi - c+di => (a-c) + (b-d)i - (cond - [(flonum? x) - (if (flonum? y) - (fl- x y) - (fl-make-rectangular - (fl- x ($inexactnum-real-part y)) - (fl- ($inexactnum-imag-part y))))] - [(flonum? y) - (fl-make-rectangular - (fl- ($inexactnum-real-part x) y) - ($inexactnum-imag-part x))] - [else - (fl-make-rectangular - (fl- ($inexactnum-real-part x) ($inexactnum-real-part y)) - (fl- ($inexactnum-imag-part x) ($inexactnum-imag-part y)))])) - -(define-library-entry (cfl/ x y) - ;; spurious overflows, underflows, and division by zero - (cond - [(flonum? y) - ;; a+bi/c => a/c + (b/c)i - (if (flonum? x) - (fl/ x y) - (fl-make-rectangular - (fl/ ($inexactnum-real-part x) y) - (fl/ ($inexactnum-imag-part x) y)))] - [(flonum? x) - ;; a / c+di => c(a/(cc+dd)) + (-d(a/cc+dd))i - (let ([c ($inexactnum-real-part y)] [d ($inexactnum-imag-part y)]) - (let ([t (fl/ x (fl+ (fl* c c) (fl* d d)))]) - (fl-make-rectangular (fl* c t) (fl- (fl* d t)))))] - [else - ;; a+bi / c+di => (ac+bd)/(cc+dd) + ((bc-ad)/(cc+dd))i - (let ([a ($inexactnum-real-part x)] [b ($inexactnum-imag-part x)] - [c ($inexactnum-real-part y)] [d ($inexactnum-imag-part y)]) - (let ([t (fl+ (fl* c c) (fl* d d))]) - (fl-make-rectangular (fl/ (fl+ (fl* a c) (fl* b d)) t) - (fl/ (fl- (fl* b c) (fl* a d)) t))))])) - -(let () - (define char-oops - (lambda (who x) - ($oops who "~s is not a character" x))) - (define fixnum-oops - (lambda (who x) - ($oops who "~s is not a fixnum" x))) - (define string-oops - (lambda (who x) - ($oops who "~s is not a string" x))) - (define mutable-string-oops - (lambda (who x) - ($oops who "~s is not a mutable string" x))) - (define vector-oops - (lambda (who x) - ($oops who "~s is not a vector" x))) - (define mutable-vector-oops - (lambda (who x) - ($oops who "~s is not a mutable vector" x))) - (define fxvector-oops - (lambda (who x) - ($oops who "~s is not an fxvector" x))) - (define mutable-fxvector-oops - (lambda (who x) - ($oops who "~s is not a mutable fxvector" x))) - (define bytevector-oops - (lambda (who x) - ($oops who "~s is not a bytevector" x))) - (define mutable-bytevector-oops - (lambda (who x) - ($oops who "~s is not a mutable bytevector" x))) - (define index-oops - (lambda (who x i) - ($oops who "~s is not a valid index for ~s" i x))) - - (define-library-entry (char->integer x) (char-oops 'char->integer x)) - - (define-library-entry (string-ref s i) - (if (string? s) - (index-oops 'string-ref s i) - (string-oops 'string-ref s))) - - (define-library-entry (string-set! s i c) - (if ($string-set!-check? s i) - (if (char? c) - (string-set! s i c) - (char-oops 'string-set! c)) - (if (mutable-string? s) - (index-oops 'string-set! s i) - (mutable-string-oops 'string-set! s)))) - - (define-library-entry (string-length s) - (string-oops 'string-length s)) - - (define-library-entry (vector-ref v i) - (if (vector? v) - (index-oops 'vector-ref v i) - (vector-oops 'vector-ref v))) - - (define-library-entry (vector-set! v i x) - (if (mutable-vector? v) - (index-oops 'vector-set! v i) - (mutable-vector-oops 'vector-set! v))) - - (define-library-entry (vector-set-fixnum! v i x) - (if (fixnum? x) - (if (mutable-vector? v) - (index-oops 'vector-set-fixnum! v i) - (mutable-vector-oops 'vector-set-fixnum! v)) - ($oops 'vector-set-fixnum! "~s is not a fixnum" x))) - - (define-library-entry (vector-length v) - (vector-oops 'vector-length v)) - - (define-library-entry (vector-cas! v i old-x new-x) - (if (mutable-vector? v) - (index-oops 'vector-cas! v i) - (mutable-vector-oops 'vector-cas! v))) - - (define-library-entry (fxvector-ref v i) - (if (fxvector? v) - (index-oops 'fxvector-ref v i) - (fxvector-oops 'fxvector-ref v))) - - (define-library-entry (fxvector-set! v i x) - (if (mutable-fxvector? v) - (if (and (fixnum? i) ($fxu< i (fxvector-length v))) - (fixnum-oops 'fxvector-set! x) - (index-oops 'fxvector-set! v i)) - (mutable-fxvector-oops 'fxvector-set! v))) - - (define-library-entry (fxvector-length v) - (fxvector-oops 'fxvector-length v)) - - (define-library-entry (bytevector-s8-ref v i) - (if (bytevector? v) - (index-oops 'bytevector-s8-ref v i) - (bytevector-oops 'bytevector-s8-ref v))) - - (define-library-entry (bytevector-u8-ref v i) - (if (bytevector? v) - (index-oops 'bytevector-u8-ref v i) - (bytevector-oops 'bytevector-u8-ref v))) - - (define-library-entry (bytevector-s8-set! v i k) - (if ($bytevector-set!-check? 8 v i) - (if (and (fixnum? k) (fx<= -128 k 127)) - (bytevector-s8-set! v i k) - ($oops 'bytevector-s8-set! "invalid value ~s" k)) - (if (mutable-bytevector? v) - (index-oops 'bytevector-s8-set! v i) - (mutable-bytevector-oops 'bytevector-s8-set! v)))) - - (define-library-entry (bytevector-u8-set! v i k) - (if ($bytevector-set!-check? 8 v i) - (if (and (fixnum? k) (fx<= 0 k 255)) - (bytevector-u8-set! v i k) - ($oops 'bytevector-u8-set! "invalid value ~s" k)) - (if (mutable-bytevector? v) - (index-oops 'bytevector-u8-set! v i) - (mutable-bytevector-oops 'bytevector-u8-set! v)))) - - (define-library-entry (bytevector-length v) - (bytevector-oops 'bytevector-length v)) - - (define-library-entry (char=? x y) (char-oops 'char=? (if (char? x) y x))) - (define-library-entry (char? x y) (char-oops 'char>? (if (char? x) y x))) - (define-library-entry (char<=? x y) (char-oops 'char<=? (if (char? x) y x))) - (define-library-entry (char>=? x y) (char-oops 'char>=? (if (char? x) y x))) -) - -(define-library-entry (real->flonum x who) - (cond - [(fixnum? x) (fixnum->flonum x)] - [(or (bignum? x) (ratnum? x)) (inexact x)] - [(flonum? x) x] - [else ($oops who "~s is not a real number" x)])) - -(let () - (define pair-oops - (lambda (who x) - ($oops who "~s is not a pair" x))) - - (define-library-entry (car x) (pair-oops 'car x)) - (define-library-entry (cdr x) (pair-oops 'cdr x)) - (define-library-entry (set-car! x y) (pair-oops 'set-car! x)) - (define-library-entry (set-cdr! x y) (pair-oops 'set-cdr! x)) -) - -(let () - (define c..r-oops - (lambda (who obj) - ($oops who "incorrect list structure ~s" obj))) - - (define-library-entry (caar x) (c..r-oops 'caar x)) - (define-library-entry (cadr x) (c..r-oops 'cadr x)) - (define-library-entry (cdar x) (c..r-oops 'cdar x)) - (define-library-entry (cddr x) (c..r-oops 'cddr x)) - (define-library-entry (caaar x) (c..r-oops 'caaar x)) - (define-library-entry (caadr x) (c..r-oops 'caadr x)) - (define-library-entry (cadar x) (c..r-oops 'cadar x)) - (define-library-entry (caddr x) (c..r-oops 'caddr x)) - (define-library-entry (cdaar x) (c..r-oops 'cdaar x)) - (define-library-entry (cdadr x) (c..r-oops 'cdadr x)) - (define-library-entry (cddar x) (c..r-oops 'cddar x)) - (define-library-entry (cdddr x) (c..r-oops 'cdddr x)) - (define-library-entry (caaaar x) (c..r-oops 'caaaar x)) - (define-library-entry (caaadr x) (c..r-oops 'caaadr x)) - (define-library-entry (caadar x) (c..r-oops 'caadar x)) - (define-library-entry (caaddr x) (c..r-oops 'caaddr x)) - (define-library-entry (cadaar x) (c..r-oops 'cadaar x)) - (define-library-entry (cadadr x) (c..r-oops 'cadadr x)) - (define-library-entry (caddar x) (c..r-oops 'caddar x)) - (define-library-entry (cadddr x) (c..r-oops 'cadddr x)) - (define-library-entry (cdaaar x) (c..r-oops 'cdaaar x)) - (define-library-entry (cdaadr x) (c..r-oops 'cdaadr x)) - (define-library-entry (cdadar x) (c..r-oops 'cdadar x)) - (define-library-entry (cdaddr x) (c..r-oops 'cdaddr x)) - (define-library-entry (cddaar x) (c..r-oops 'cddaar x)) - (define-library-entry (cddadr x) (c..r-oops 'cddadr x)) - (define-library-entry (cdddar x) (c..r-oops 'cdddar x)) - (define-library-entry (cddddr x) (c..r-oops 'cddddr x)) -) - -(define-library-entry (unbox x) - ($oops 'unbox "~s is not a box" x)) - -(define-library-entry (set-box! b v) - ($oops 'set-box! "~s is not a mutable box" b)) - -(define-library-entry (box-cas! b old-v new-v) - ($oops 'box-cas! "~s is not a mutable box" b)) - -(let () -(define (fxnonfixnum1 who x) - ($oops who "~s is not a fixnum" x)) - -(define (fxnonfixnum2 who x y) - ($oops who "~s is not a fixnum" (if (fixnum? x) y x))) - -(define (fxoops1 who x) - (if (fixnum? x) - ($impoops who "fixnum overflow with argument ~s" x) - (fxnonfixnum1 who x))) - -(define (fxoops2 who x y) - (if (fixnum? x) - (if (fixnum? y) - ($impoops who "fixnum overflow with arguments ~s and ~s" x y) - (fxnonfixnum1 who y)) - (fxnonfixnum1 who x))) - -(define (shift-count-oops who x) - ($oops who "invalid shift count ~s" x)) - -(define-library-entry (fx+ x y) (fxoops2 'fx+ x y)) -(define-library-entry (fx- x y) (fxoops2 'fx- x y)) -(define-library-entry (fx* x y) (fxoops2 'fx* x y)) -(define-library-entry (fx1+ x) (fxoops1 'fx1+ x)) -(define-library-entry (fx1- x) (fxoops1 'fx1- x)) - -(define-library-entry (fx= x y) (fxnonfixnum2 'fx= x y)) -(define-library-entry (fx< x y) (fxnonfixnum2 'fx< x y)) -(define-library-entry (fx> x y) (fxnonfixnum2 'fx> x y)) -(define-library-entry (fx<= x y) (fxnonfixnum2 'fx<= x y)) -(define-library-entry (fx>= x y) (fxnonfixnum2 'fx>= x y)) -(define-library-entry (fx=? x y) (fxnonfixnum2 'fx=? x y)) -(define-library-entry (fx? x y) (fxnonfixnum2 'fx>? x y)) -(define-library-entry (fx<=? x y) (fxnonfixnum2 'fx<=? x y)) -(define-library-entry (fx>=? x y) (fxnonfixnum2 'fx>=? x y)) -(define-library-entry (fxzero? x) (fxnonfixnum1 'fxzero? x)) -(define-library-entry (fxpositive? x) (fxnonfixnum1 'fxpositive? x)) -(define-library-entry (fxnonpositive? x) (fxnonfixnum1 'fxnonpositive? x)) -(define-library-entry (fxnegative? x) (fxnonfixnum1 'fxnegative? x)) -(define-library-entry (fxnonnegative? x) (fxnonfixnum1 'fxnonnegative? x)) -(define-library-entry (fxeven? x) (fxnonfixnum1 'fxeven? x)) -(define-library-entry (fxodd? x) (fxnonfixnum1 'fxodd? x)) -(define-library-entry (fxlogior x y) (fxnonfixnum2 'fxlogior x y)) -(define-library-entry (fxlogor x y) (fxnonfixnum2 'fxlogor x y)) -(define-library-entry (fxlogxor x y) (fxnonfixnum2 'fxlogxor x y)) -(define-library-entry (fxlogand x y) (fxnonfixnum2 'fxlogand x y)) -(define-library-entry (fxlognot x) (fxnonfixnum1 'fxlognot x)) -(define-library-entry (fxior x y) (fxnonfixnum2 'fxior x y)) -(define-library-entry (fxxor x y) (fxnonfixnum2 'fxxor x y)) -(define-library-entry (fxand x y) (fxnonfixnum2 'fxand x y)) -(define-library-entry (fxnot x) (fxnonfixnum1 'fxnot x)) - -(define-library-entry (fxsll x y) - (cond - [(not (fixnum? x)) (fxnonfixnum1 'fxsll x)] - [(not (fixnum? y)) (fxnonfixnum1 'fxsll y)] - [(fx= 0 y) x] - [($fxu< y (constant fixnum-bits)) - (if (fx>= x 0) - (if (fx< x (fxsll 1 (fx- (- (constant fixnum-bits) 1) y))) - (fxsll x y) - (fxoops2 'fxsll x y)) - (if (fx>= x (fxsll -1 (fx- (- (constant fixnum-bits) 1) y))) - (fxsll x y) - (fxoops2 'fxsll x y)))] - [(fx= y (constant fixnum-bits)) (if (fx= x 0) x (fxoops2 'fxsll x y))] - [else (shift-count-oops 'fxsll y)])) - -(define-library-entry (fxarithmetic-shift-left x y) - (cond - [(not (fixnum? x)) (fxnonfixnum1 'fxarithmetic-shift-left x)] - [(not (fixnum? y)) (fxnonfixnum1 'fxarithmetic-shift-left y)] - [(fx= 0 y) x] - [($fxu< y (constant fixnum-bits)) - (if (fx>= x 0) - (if (fx< x (fxsll 1 (fx- (- (constant fixnum-bits) 1) y))) - (fxsll x y) - (fxoops2 'fxarithmetic-shift-left x y)) - (if (fx>= x (fxsll -1 (fx- (- (constant fixnum-bits) 1) y))) - (fxsll x y) - (fxoops2 'fxarithmetic-shift-left x y)))] - [else (shift-count-oops 'fxarithmetic-shift-left y)])) - -(define-library-entry (fxsrl x y) - (cond - [(not (fixnum? x)) (fxnonfixnum1 'fxsrl x)] - [(not (fixnum? y)) (fxnonfixnum1 'fxsrl y)] - [else (shift-count-oops 'fxsrl y)])) - -(define-library-entry (fxsra x y) - (cond - [(not (fixnum? x)) (fxnonfixnum1 'fxsra x)] - [(not (fixnum? y)) (fxnonfixnum1 'fxsra y)] - [else (shift-count-oops 'fxsra y)])) - -(define-library-entry (fxarithmetic-shift-right x y) - (cond - [(not (fixnum? x)) (fxnonfixnum1 'fxarithmetic-shift-right x)] - [(not (fixnum? y)) (fxnonfixnum1 'fxarithmetic-shift-right y)] - [else (shift-count-oops 'fxarithmetic-shift-right y)])) - -(define-library-entry (fxarithmetic-shift x y) - (cond - [(not (fixnum? x)) (fxnonfixnum1 'fxarithmetic-shift x)] - [(not (fixnum? y)) (fxnonfixnum1 'fxarithmetic-shift y)] - [(fx= 0 y) x] - [($fxu< y (constant fixnum-bits)) - (if (fx>= x 0) - (if (fx< x (fxsll 1 (fx- (- (constant fixnum-bits) 1) y))) - (fxsll x y) - (fxoops2 'fxarithmetic-shift x y)) - (if (fx>= x (fxsll -1 (fx- (- (constant fixnum-bits) 1) y))) - (fxsll x y) - (fxoops2 'fxarithmetic-shift x y)))] - [(fx< (fx- (constant fixnum-bits)) y 0) (fxsra x (fx- y))] - [else (shift-count-oops 'fxarithmetic-shift y)])) - -(define-library-entry (fxlogbit? k n) - (if (fixnum? n) - (if (fixnum? k) - (if (fx< k 0) - ($oops 'fxlogbit? "invalid bit index ~s" k) - ; this case left to us by cp1in fxlogbit? handler - (fx< n 0)) - (fxnonfixnum1 'fxlogbit? k)) - (fxnonfixnum1 'fxlogbit? n))) - -(define-library-entry (fxbit-set? n k) - (if (fixnum? n) - (if (fixnum? k) - (if (fx< k 0) - ($oops 'fxbit-set? "invalid bit index ~s" k) - ; this case left to us by cp1in fxbit-set? handler - (fx< n 0)) - (fxnonfixnum1 'fxbit-set? k)) - (fxnonfixnum1 'fxbit-set? n))) - -(define-library-entry (fxlogbit0 k n) - (if (fixnum? n) - (if (fixnum? k) - ($oops 'fxlogbit0 "invalid bit index ~s" k) - (fxnonfixnum1 'fxlogbit0 k)) - (fxnonfixnum1 'fxlogbit0 n))) - -(define-library-entry (fxlogbit1 k n) - (if (fixnum? n) - (if (fixnum? k) - ($oops 'fxlogbit1 "invalid bit index ~s" k) - (fxnonfixnum1 'fxlogbit1 k)) - (fxnonfixnum1 'fxlogbit1 n))) - -(define-library-entry (fxcopy-bit n k) - ; get here only if third argument is 0 or 1 - (if (fixnum? n) - (if (fixnum? k) - ($oops 'fxcopy-bit "invalid bit index ~s" k) - (fxnonfixnum1 'fxcopy-bit k)) - (fxnonfixnum1 'fxcopy-bit n))) - -(define-library-entry (fxlogtest x y) (fxnonfixnum2 'fxlogtest x y)) -) - -(let () - (define flonum-oops - (lambda (who x) - ($oops who "~s is not a flonum" x))) - - (define-library-entry (fl= x y) (flonum-oops 'fl= (if (flonum? x) y x))) - (define-library-entry (fl< x y) (flonum-oops 'fl< (if (flonum? x) y x))) - (define-library-entry (fl> x y) (flonum-oops 'fl> (if (flonum? x) y x))) - (define-library-entry (fl<= x y) (flonum-oops 'fl<= (if (flonum? x) y x))) - (define-library-entry (fl>= x y) (flonum-oops 'fl>= (if (flonum? x) y x))) - (define-library-entry (fl=? x y) (flonum-oops 'fl=? (if (flonum? x) y x))) - (define-library-entry (fl? x y) (flonum-oops 'fl>? (if (flonum? x) y x))) - (define-library-entry (fl<=? x y) (flonum-oops 'fl<=? (if (flonum? x) y x))) - (define-library-entry (fl>=? x y) (flonum-oops 'fl>=? (if (flonum? x) y x))) - - (define-library-entry (fl+ x y) (flonum-oops 'fl+ (if (flonum? x) y x))) - (define-library-entry (fl- x y) (flonum-oops 'fl- (if (flonum? x) y x))) - (define-library-entry (fl* x y) (flonum-oops 'fl* (if (flonum? x) y x))) - (define-library-entry (fl/ x y) (flonum-oops 'fl/ (if (flonum? x) y x))) - (define-library-entry (flnegate x) (flonum-oops 'fl- x)) -) - -(define-library-entry (flround x) - ; assumes round-to-nearest-or-even - (float-type-case - [(ieee) - (define threshold+ #i#x10000000000000) - (define threshold- #i#x-10000000000000)]) - (if (fl>= x 0.0) - (if (fl< x threshold+) - (fl- (fl+ x threshold+) threshold+) - x) - (if (fl> x threshold-) - (fl- (fl+ x threshold-) threshold-) - x))) - -;;; The generic comparison entries assume the fixnum case is inlined. - -(define-library-entry (= x y) - (cond - [(flonum? x) - (cond - [(flonum? y) (fl= x y)] - [($inexactnum? y) (and (fl= ($inexactnum-imag-part y) 0.0) - (fl= ($inexactnum-real-part y) x))] - [else ($= '= x y)])] - [($inexactnum? x) - (cond - [(flonum? y) (and (fl= ($inexactnum-imag-part x) 0.0) - (fl= ($inexactnum-real-part x) y))] - [($inexactnum? y) - (and (fl= ($inexactnum-imag-part x) ($inexactnum-imag-part y)) - (fl= ($inexactnum-real-part x) ($inexactnum-real-part y)))] - [else ($= '= x y)])] - [else ($= '= x y)])) - -(define-library-entry (zero? x) - (cond - [(cflonum? x) (cfl= x 0.0)] - [(or (bignum? x) (ratnum? x) ($exactnum? x)) #f] - [else ($= 'zero? x 0)])) - -(define-library-entry (< x y) - (cond - [(and (flonum? x) (flonum? y)) (fl< x y)] - [else ($< '< x y)])) - -(define-library-entry (> x y) - (cond - [(and (flonum? x) (flonum? y)) (fl> x y)] - [else ($< '> y x)])) - -(define-library-entry (<= x y) - (cond - [(and (flonum? x) (flonum? y)) (fl<= x y)] - [else ($<= '<= x y)])) - -(define-library-entry (>= x y) - (cond - [(and (flonum? x) (flonum? y)) (fl>= x y)] - [else ($<= '>= y x)])) - -(define-library-entry (+ x y) - (cond - [(flonum? x) - (cond - [(flonum? y) (fl+ x y)] - [($inexactnum? y) (cfl+ x y)] - [else ($+ '+ x y)])] - [(and ($inexactnum? x) (cflonum? y)) (cfl+ x y)] - [else ($+ '+ x y)])) - -(define-library-entry (1+ x) - (cond - [(flonum? x) (fl+ x 1.0)] - [($inexactnum? x) (cfl+ x 1.0)] - [else ($+ '1+ x 1)])) - -(define-library-entry (add1 x) - (cond - [(flonum? x) (fl+ x 1.0)] - [($inexactnum? x) (cfl+ x 1.0)] - [else ($+ 'add1 x 1)])) - -(define-library-entry (negate x) - (cond - [(flonum? x) (fl- x)] - [($inexactnum? x) (cfl- x)] - [else ($- '- 0 x)])) - -(define-library-entry (- x y) - (cond - [(flonum? x) - (cond - [(flonum? y) (fl- x y)] - [($inexactnum? y) (cfl- x y)] - [else ($- '- x y)])] - [(and ($inexactnum? x) (cflonum? y)) (cfl- x y)] - [else ($- '- x y)])) - -(define-library-entry (1- x) - (cond - [(flonum? x) (fl- x 1.0)] - [($inexactnum? x) (cfl- x 1.0)] - [else ($- '1- x 1)])) - -(define-library-entry (-1+ x) - (cond - [(flonum? x) (fl- x 1.0)] - [($inexactnum? x) (cfl- x 1.0)] - [else ($- '-1+ x 1)])) - -(define-library-entry (sub1 x) - (cond - [(flonum? x) (fl- x 1.0)] - [($inexactnum? x) (cfl- x 1.0)] - [else ($- 'sub1 x 1)])) - -(define-library-entry (* x y) - (cond - [(flonum? x) - (cond - [(flonum? y) (fl* x y)] - [($inexactnum? y) (cfl* x y)] - [else ($* '* x y)])] - [(and ($inexactnum? x) (cflonum? y)) (cfl* x y)] - [else ($* '* x y)])) - -(define-library-entry (/ x y) - (cond - [(flonum? x) - (cond - [(flonum? y) (fl/ x y)] - [($inexactnum? y) (cfl/ x y)] - [else ($/ '/ x y)])] - [(and ($inexactnum? x) (cflonum? y)) (cfl/ x y)] - [else ($/ '/ x y)])) - -;;; The logical operators assume the fixnum case is inlined. -(let () - (define exactintoops1 - (lambda (who x) - ($oops who "~s is not an exact integer" x))) - (define exactintoops2 - (lambda (who x y) - (exactintoops1 who (if (or (fixnum? x) (bignum? x)) y x)))) - - (define-library-entry (logand x y) - (if (if (fixnum? x) - (bignum? y) - (and (bignum? x) - (or (fixnum? y) (bignum? y)))) - ($logand x y) - (exactintoops2 'logand x y))) - - (define-library-entry (bitwise-and x y) - (if (if (fixnum? x) - (bignum? y) - (and (bignum? x) - (or (fixnum? y) (bignum? y)))) - ($logand x y) - (exactintoops2 'bitwise-and x y))) - - (define-library-entry (logior x y) ; same as logor - (if (if (fixnum? x) - (bignum? y) - (and (bignum? x) - (or (fixnum? y) (bignum? y)))) - ($logor x y) - (exactintoops2 'logior x y))) - - (define-library-entry (logor x y) - (if (if (fixnum? x) - (bignum? y) - (and (bignum? x) - (or (fixnum? y) (bignum? y)))) - ($logor x y) - (exactintoops2 'logor x y))) - - (define-library-entry (bitwise-ior x y) - (if (if (fixnum? x) - (bignum? y) - (and (bignum? x) - (or (fixnum? y) (bignum? y)))) - ($logor x y) - (exactintoops2 'bitwise-ior x y))) - - (define-library-entry (logxor x y) - (if (if (fixnum? x) - (bignum? y) - (and (bignum? x) - (or (fixnum? y) (bignum? y)))) - ($logxor x y) - (exactintoops2 'logxor x y))) - - (define-library-entry (bitwise-xor x y) - (if (if (fixnum? x) - (bignum? y) - (and (bignum? x) - (or (fixnum? y) (bignum? y)))) - ($logxor x y) - (exactintoops2 'bitwise-xor x y))) - - (define-library-entry (lognot x) - (if (bignum? x) - ($lognot x) - (exactintoops1 'lognot x))) - - (define-library-entry (bitwise-not x) - (if (bignum? x) - ($lognot x) - (exactintoops1 'bitwise-not x))) - - (let () - (define (do-logbit? who k n) - (cond - [(fixnum? n) - (cond - [(fixnum? k) - (if (fx< k 0) - ($oops who "invalid bit index ~s" k) - ; this case left to us by cp1in logbit? handler - (fx< n 0))] - [(bignum? k) - (if (< k 0) - ($oops who "invalid bit index ~s" k) - ; this case left to us by cp1in logbit? handler - (fx< n 0))] - [else (exactintoops1 who k)])] - [(bignum? n) - (cond - [(fixnum? k) - (if (fx< k 0) - ($oops who "invalid bit index ~s" k) - ($logbit? k n))] - [(bignum? k) - (if (< k 0) - ($oops who "invalid bit index ~s" k) - ; $logbit? requires k to be a fixnum - (fxlogtest (ash n (- k)) 1))] - [else (exactintoops1 who k)])] - [else (exactintoops1 who n)])) - (define-library-entry (logbit? k n) (do-logbit? 'logbit? k n)) - (define-library-entry (bitwise-bit-set? n k) (do-logbit? 'bitwise-bit-set? k n))) - - (define-library-entry (logbit0 k n) - (if (or (fixnum? n) (bignum? n)) - (cond - [(fixnum? k) - (if (fx< k 0) - ($oops 'logbit0 "invalid bit index ~s" k) - ($logbit0 k n))] - [(bignum? k) - (if (< k 0) - ($oops 'logbit0 "invalid bit index ~s" k) - ; $logbit0 requires k to be a fixnum - ($logand n ($lognot (ash 1 k))))] - [else (exactintoops1 'logbit0 k)]) - (exactintoops1 'logbit0 n))) - - (define-library-entry (logbit1 k n) - (if (or (fixnum? n) (bignum? n)) - (cond - [(fixnum? k) - (if (fx< k 0) - ($oops 'logbit1 "invalid bit index ~s" k) - ($logbit1 k n))] - [(bignum? k) - (if (< k 0) - ($oops 'logbit1 "invalid bit index ~s" k) - ; $logbit1 requires k to be a fixnum - ($logor n (ash 1 k)))] - [else (exactintoops1 'logbit1 k)]) - (exactintoops1 'logbit1 n))) - - (define-library-entry (logtest x y) - (if (if (fixnum? x) - (bignum? y) - (and (bignum? x) - (or (fixnum? y) (bignum? y)))) - ($logtest x y) - (exactintoops2 'logtest x y))) -) - -(let () - (include "io-types.ss") - (define-syntax define-safe/unsafe - (lambda (x) - (syntax-case x () - [(k (name arg ...) e ...) - (with-syntax ([safe-name (construct-name #'k "safe-" #'name)] - [unsafe-name (construct-name #'k "unsafe-" #'name)] - [who (datum->syntax #'k 'who)] - [check (datum->syntax #'k 'check)]) - #'(let () - (define who 'name) - (let () - (define-syntax check (identifier-syntax if)) - (define-library-entry (safe-name arg ...) e ...)) - (let () - (define-syntax check (syntax-rules () [(_ e1 e2 e3) e2])) - (define-library-entry (unsafe-name arg ...) e ...))))]))) - (define-safe/unsafe (get-u8 p) - (check (and (input-port? p) (binary-port? p)) - ((port-handler-get ($port-handler p)) 'get-u8 p) - ($oops who "~s is not a binary input port" p))) - (define-safe/unsafe (get-char p) - (check (and (input-port? p) (textual-port? p)) - ((port-handler-get ($port-handler p)) who p) - ($oops who "~s is not a textual input port" p))) - (define-safe/unsafe (read-char p) - (check (and (input-port? p) (textual-port? p)) - ((port-handler-get ($port-handler p)) who p) - ($oops who "~s is not a textual input port" p))) - (define-safe/unsafe (lookahead-u8 p) - (check (and (input-port? p) (binary-port? p)) - ((port-handler-lookahead ($port-handler p)) 'lookahead-u8 p) - ($oops who "~s is not a binary input port" p))) - (define-safe/unsafe (lookahead-char p) - (check (and (input-port? p) (textual-port? p)) - ((port-handler-lookahead ($port-handler p)) who p) - ($oops who "~s is not a textual input port" p))) - (define-safe/unsafe (peek-char p) - (check (and (input-port? p) (textual-port? p)) - ((port-handler-lookahead ($port-handler p)) who p) - ($oops who "~s is not a textual input port" p))) - (define-safe/unsafe (unget-u8 p x) - (check (and (input-port? p) (binary-port? p)) - (check (or (and (fixnum? x) (fx<= 0 x 255)) (eof-object? x)) - ((port-handler-unget ($port-handler p)) who p x) - ($oops who "~s is not an octet or the eof object" x)) - ($oops who "~s is not a binary input port" p))) - (define-safe/unsafe (unget-char p x) - (check (and (input-port? p) (textual-port? p)) - (check (or (char? x) (eof-object? x)) - ((port-handler-unget ($port-handler p)) who p x) - ($oops who "~s is not an character or the eof object" x)) - ($oops who "~s is not a textual input port" p))) - (define-safe/unsafe (unread-char x p) - (check (and (input-port? p) (textual-port? p)) - (check (or (char? x) (eof-object? x)) - ((port-handler-unget ($port-handler p)) who p x) - ($oops who "~s is not an character or the eof object" x)) - ($oops who "~s is not a textual input port" p))) - (define-safe/unsafe (put-u8 p x) - (check (and (output-port? p) (binary-port? p)) - (check (and (fixnum? x) (fx<= 0 x 255)) - ((port-handler-put ($port-handler p)) who p x) - ($oops who "~s is not an octet" x)) - ($oops who "~s is not a binary output port" p))) - (define-safe/unsafe (put-char p x) - (check (and (output-port? p) (textual-port? p)) - (check (char? x) - ((port-handler-put ($port-handler p)) who p x) - ($oops who "~s is not a character" x)) - ($oops who "~s is not a textual output port" p))) - (define-safe/unsafe (write-char x p) - (check (and (output-port? p) (textual-port? p)) - (check (char? x) - ((port-handler-put ($port-handler p)) who p x) - ($oops who "~s is not a character" x)) - ($oops who "~s is not a textual output port" p))) - (define-safe/unsafe (newline p) - (check (and (output-port? p) (textual-port? p)) - ((port-handler-put ($port-handler p)) who p #\newline) - ($oops who "~s is not a textual output port" p))) - (define-safe/unsafe (port-eof? p) - (check (input-port? p) - (eof-object? ((port-handler-lookahead ($port-handler p)) who p)) - ($oops who "~s is not an input port" p))) - (define-library-entry (put-bytevector bop bv start count) - (define who 'put-bytevector) - (if (or (fx> count max-put-copy) (fx> count (binary-port-output-count bop))) - (let ([put-some (port-handler-put-some ($port-handler bop))]) - (let loop ([start start] [count count]) - (unless (eq? 0 count) - (let ([n (put-some who bop bv start count)]) - (loop (fx+ start n) (fx- count n)))))) - (let ([i (binary-port-output-index bop)]) - ; counting on cp1in generating call to $byte-copy here and - ; $byte-copy foreign procedure to be compiled w/o interrupt - ; trap check in prims.ss. otherwise this won't be safe for - ; multitasking. - (bytevector-copy! bv start (binary-port-output-buffer bop) i count) - (set-binary-port-output-index! bop (fx+ i count))))) - (define-library-entry (put-bytevector-some bop bv start count) - (define who 'put-bytevector-some) - (if (or (fx> count max-put-copy) (fx> count (binary-port-output-count bop))) - (let ([put-some (port-handler-put-some ($port-handler bop))]) - (put-some who bop bv start count)) - (let ([i (binary-port-output-index bop)]) - ; counting on cp1in generating call to $byte-copy here and - ; $byte-copy foreign procedure to be compiled w/o interrupt - ; trap check in prims.ss. otherwise this won't be safe for - ; multitasking. - (bytevector-copy! bv start (binary-port-output-buffer bop) i count) - (set-binary-port-output-index! bop (fx+ i count)) - count))) - (define-library-entry (put-string top st start count) - (define who 'put-string) - (if (or (fx> count max-put-copy) (fx> count (textual-port-output-count top))) - (let ([put-some (port-handler-put-some ($port-handler top))]) - (let loop ([start start] [count count]) - (unless (eq? 0 count) - (let ([n (put-some who top st start count)]) - (loop (fx+ start n) (fx- count n)))))) - (let ([i (textual-port-output-index top)]) - ; counting on cp1in generating call to $byte-copy here and - ; $byte-copy foreign procedure to be compiled w/o interrupt - ; trap check in prims.ss. otherwise this won't be safe for - ; multitasking. - (string-copy! st start (textual-port-output-buffer top) i count) - (set-textual-port-output-index! top (fx+ i count))))) - (define-library-entry (put-string-some top st start count) - (define who 'put-string-some) - (if (or (fx> count max-put-copy) (fx> count (textual-port-output-count top))) - (let ([put-some (port-handler-put-some ($port-handler top))]) - (put-some who top st start count)) - (let ([i (textual-port-output-index top)]) - ; counting on cp1in generating call to $byte-copy here and - ; $byte-copy foreign procedure to be compiled w/o interrupt - ; trap check in prims.ss. otherwise this won't be safe for - ; multitasking. - (string-copy! st start (textual-port-output-buffer top) i count) - (set-textual-port-output-index! top (fx+ i count)) - count))) - (define-library-entry (display-string st top) - (define who 'display-string) - (let ([start 0] [count (string-length st)]) - (if (or (fx> count max-put-copy) (fx> count (textual-port-output-count top))) - (let ([put-some (port-handler-put-some ($port-handler top))]) - (let loop ([start start] [count count]) - (unless (eq? 0 count) - (let ([n (put-some who top st start count)]) - (loop (fx+ start n) (fx- count n)))))) - (let ([i (textual-port-output-index top)]) - ; counting on cp1in generating call to $byte-copy here and - ; $byte-copy foreign procedure to be compiled w/o interrupt - ; trap check in prims.ss. otherwise this won't be safe for - ; multitasking. - (string-copy! st start (textual-port-output-buffer top) i count) - (set-textual-port-output-index! top (fx+ i count)))))) -) - -(define-library-entry ($top-level-value x) - (unless (symbol? x) - ($oops '$top-level-value "~s is not a symbol" x)) - (unless ($top-level-bound? x) - ($oops #f "variable ~:s is not bound" x)) - (#3%$top-level-value x)) - -(define-library-entry (event) - (define (timer) - (if (eq? ($tc-field 'timer-ticks ($tc)) 0) - (let ([handler (timer-interrupt-handler)]) - ($tc-field 'timer-ticks ($tc) #f) - (signal) - (handler)) - (signal))) - (define (signal) - (let ([x ($tc-field 'signal-interrupt-pending ($tc))]) - (if x - (let ([handler $signal-interrupt-handler]) - ($tc-field 'signal-interrupt-pending ($tc) #f) - (keyboard) - (for-each handler ($dequeue-scheme-signals ($tc)))) - (keyboard)))) - (define (keyboard) - (if ($tc-field 'keyboard-interrupt-pending ($tc)) - (let ([handler (keyboard-interrupt-handler)]) - ($tc-field 'keyboard-interrupt-pending ($tc) #f) - (collector) - (handler)) - (collector))) - (define (collector) - (if $collect-request-pending - (let ([handler $collect-rendezvous]) - (restart-timer) - (handler)) - (restart-timer))) - (define (restart-timer) - (cond - [($tc-field 'timer-ticks ($tc)) => - (lambda (t) - (let ([ticks (fxmin t (constant default-timer-ticks))]) - ($tc-field 'timer-ticks ($tc) (fx- t ticks)) - ($tc-field 'something-pending ($tc) #t) - ($set-timer ticks)))] - [else - ($set-timer (constant default-timer-ticks))])) - (if (and (fx= ($tc-field 'disable-count ($tc)) 0) ($tc-field 'something-pending ($tc))) - (begin - ($set-timer (most-positive-fixnum)) - ($tc-field 'something-pending ($tc) #f) - (timer)) - ($set-timer (constant default-timer-ticks)))) - -(define-library-entry (virtual-register idx) - ($oops 'virtual-register "invalid index ~s" idx)) - -(define-library-entry (set-virtual-register! idx) - ($oops 'set-virtual-register! "invalid index ~s" idx)) - -(define-library-entry (map1 f ls) - (let map ([f f] [ls ls]) - (if (null? ls) - '() - (let ((r (cdr ls))) - (if (null? r) - (list (f (car ls))) - ; cdr first to avoid getting sick if f mutates input - (let ([tail (map f (cdr r))]) - (list* (f (car ls)) (f (car r)) tail))))))) - -(define-library-entry (map2 f ls1 ls2) - (let map ([f f] [ls1 ls1] [ls2 ls2]) - (if (null? ls1) - '() - (let ((r1 (cdr ls1))) - (if (null? r1) - (list (f (car ls1) (car ls2))) - (let ((r2 (cdr ls2))) - ; cdr first to avoid getting sick if f mutates input - (let ([tail (map f (cdr r1) (cdr r2))]) - (list* (f (car ls1) (car ls2)) - (f (car r1) (car r2)) - tail)))))))) - -(define-library-entry (map-car ls) - (let map ([ls ls]) - (if (null? ls) - '() - (let ((r (cdr ls))) - (if (null? r) - (list (car (car ls))) - (list* (car (car ls)) (car (car r)) (map (cdr r)))))))) - -(define-library-entry (map-cdr ls) - (let map ([ls ls]) - (if (null? ls) - '() - (let ((r (cdr ls))) - (if (null? r) - (list (cdr (car ls))) - (list* (cdr (car ls)) (cdr (car r)) (map (cdr r)))))))) - -(define-library-entry (map-cons ls1 ls2) - (let map ([ls1 ls1] [ls2 ls2]) - (if (null? ls1) - '() - (let ((r1 (cdr ls1))) - (if (null? r1) - (list (cons (car ls1) (car ls2))) - (let ((r2 (cdr ls2))) - (list* (cons (car ls1) (car ls2)) - (cons (car r1) (car r2)) - (map (cdr r1) (cdr r2))))))))) - -(define-library-entry (for-each1 f ls) - (unless (null? ls) - (let for-each ([x (car ls)] [ls (cdr ls)]) - (if (null? ls) - (f x) - (begin - (f x) - (for-each (car ls) (cdr ls))))))) - -(define-library-entry (for-each2 f ls1 ls2) - (unless (null? ls1) - (let for-each ([x (car ls1)] [ls1 (cdr ls1)] [ls2 ls2]) - (if (null? ls1) - (f x (car ls2)) - (begin - (f x (car ls2)) - (for-each (car ls1) (cdr ls1) (cdr ls2))))))) - -(define-library-entry (andmap1 f ls) - (or (null? ls) - (let andmap ([ls ls]) - (let ([x (car ls)] [ls (cdr ls)]) - (if (null? ls) - (f x) - (and (f x) (andmap ls))))))) - -(define-library-entry (ormap1 f ls) - (and (not (null? ls)) - (let ormap ([ls ls]) - (let ([x (car ls)] [ls (cdr ls)]) - (if (null? ls) - (f x) - (or (f x) (ormap ls))))))) - -(define-library-entry (vector-for-each1 p v) - (let ([n (vector-length v)]) - (unless (fx= n 0) - (let loop ([i 0]) - (let ([j (fx+ i 1)]) - (if (fx= j n) - (p (vector-ref v i)) - (begin - (p (vector-ref v i)) - (loop j)))))))) - -(define-library-entry (vector-for-each2 p u v) - (let ([n (vector-length u)]) - (unless (fx= n 0) - (let loop ([i 0]) - (let ([j (fx+ i 1)]) - (if (fx= j n) - (p (vector-ref u i) (vector-ref v i)) - (begin - (p (vector-ref u i) (vector-ref v i)) - (loop j)))))))) - -(define-library-entry (vector-map1 p v) - (let ([n (vector-length v)]) - (let f ([i (fx- n 1)]) - (if (fx> i 0) - (let ([x1 (p (vector-ref v i))] [x2 (p (vector-ref v (fx- i 1)))]) - (let ([vout (f (fx- i 2))]) - (vector-set! vout i x1) - (vector-set! vout (fx- i 1) x2) - vout)) - (make-vector n (if (fx= i 0) (p (vector-ref v 0)) 0)))))) - -(define-library-entry (vector-map2 p u v) - (let ([n (vector-length u)]) - (let f ([i (fx- n 1)]) - (if (fx> i 0) - (let ([x1 (p (vector-ref u i) (vector-ref v i))] - [x2 (let ([j (fx- i 1)]) - (p (vector-ref u j) (vector-ref v j)))]) - (let ([vout (f (fx- i 2))]) - (vector-set! vout i x1) - (vector-set! vout (fx- i 1) x2) - vout)) - (make-vector n - (if (fx= i 0) - (p (vector-ref u 0) (vector-ref v 0)) - 0)))))) - -(define-library-entry (string-for-each1 p s) - (let ([n (string-length s)]) - (unless (fx= n 0) - (let loop ([i 0]) - (let ([j (fx+ i 1)]) - (if (fx= j n) - (p (string-ref s i)) - (begin - (p (string-ref s i)) - (loop j)))))))) - -(define-library-entry (string-for-each2 p s t) - (let ([n (string-length s)]) - (unless (fx= n 0) - (let loop ([i 0]) - (let ([j (fx+ i 1)]) - (if (fx= j n) - (p (string-ref s i) (string-ref t i)) - (begin - (p (string-ref s i) (string-ref t i)) - (loop j)))))))) - -(define-library-entry (fold-left1 combine nil ls) - (if (null? ls) - nil - (let fold-left ([ls ls] [acc nil]) - (let ([cdrls (cdr ls)]) - (if (null? cdrls) - (combine acc (car ls)) - (fold-left cdrls (combine acc (car ls)))))))) - -(define-library-entry (fold-left2 combine nil ls1 ls2) - (if (null? ls1) - nil - (let fold-left ([ls1 ls1] [ls2 ls2] [acc nil]) - (let ([cdrls1 (cdr ls1)]) - (if (null? cdrls1) - (combine acc (car ls1) (car ls2)) - (fold-left cdrls1 (cdr ls2) - (combine acc (car ls1) (car ls2)))))))) - -(define-library-entry (fold-right1 combine nil ls) - (let fold-right1 ([combine combine] [nil nil] [ls ls]) - (if (null? ls) - nil - ; naturally does cdrs first to avoid mutation sickness - (combine (car ls) (fold-right1 combine nil (cdr ls)))))) - -(define-library-entry (fold-right2 combine nil ls1 ls2) - (let fold-right2 ([combine combine] [nil nil] [ls1 ls1] [ls2 ls2]) - (if (null? ls1) - nil - ; naturally does cdrs first to avoid mutation sickness - (combine (car ls1) (car ls2) - (fold-right2 combine nil (cdr ls1) (cdr ls2)))))) - -(eval-when (compile) -(define-syntax doapply - (syntax-rules () - [(_ p (x ...) ls) (if (null? ls) (p x ...) (doapply p (x ...) ls (ls)))] - [(_ p (x ...) ls (ls1 ... lsn)) - (= (length #'(ls1 ...)) 4) - ($apply p (fx+ (length '(x ...)) (length '(ls1 ...)) (length lsn)) - (list* x ... ls))] - [(_ p (x ...) ls (ls1 ... lsn-1)) - (let ([lsn (cdr lsn-1)]) - (if (null? lsn) - (p x ... (car ls1) ... (car lsn-1)) - (doapply p (x ...) ls (ls1 ... lsn-1 lsn))))])) -) - -(define-library-entry (apply0 p ls) - (doapply p () ls)) - -(define-library-entry (apply1 p x1 ls) - (doapply p (x1) ls)) - -(define-library-entry (apply2 p x1 x2 ls) - (doapply p (x1 x2) ls)) - -(define-library-entry (apply3 p x1 x2 x3 ls) - (doapply p (x1 x2 x3) ls)) - -(define-library-entry (eqv? x y) - (if (eq? x y) - #t - (exclusive-cond - [(flonum? x) (and (flonum? y) ($fleqv? x y))] - [($inexactnum? x) - (and ($inexactnum? y) - ($fleqv? ($inexactnum-real-part x) ($inexactnum-real-part y)) - ($fleqv? ($inexactnum-imag-part x) ($inexactnum-imag-part y)))] - [(bignum? x) (and (bignum? y) (= x y))] - [(ratnum? x) (and (ratnum? y) (= x y))] - [($exactnum? x) (and ($exactnum? y) (= x y))] - [else #f]))) - -(define-library-entry (memv x ls) - (if (or (symbol? x) (#%$immediate? x)) - (memq x ls) - (let memv ([ls ls]) - (and (not (null? ls)) - (if (eqv? (car ls) x) - ls - (let ([ls (cdr ls)]) - (and (not (null? ls)) - (if (eqv? (car ls) x) - ls - (memv (cdr ls)))))))))) - -(define-library-entry (reverse ls) - (let loop ([ls ls] [a '()]) - (if (null? ls) - a - (let ([ls2 (cdr ls)]) - (if (null? ls2) - (cons (car ls) a) - (loop (cdr ls2) (cons* (car ls2) (car ls) a))))))) - -(let () - (include "hashtable-types.ss") - - ;;; eq hashtable operations must be compiled with - ;;; generate-interrupt-trap #f and optimize-level 3 - ;;; so they can't be interrupted by a collection - (let () - (define-syntax lookup-keyval - (syntax-rules () - [(_ ?x ?b succ fail) - (let ([x ?x]) - (let loop ([b ?b]) - (if (fixnum? b) - fail - (let ([keyval ($tlc-keyval b)]) - (if (eq? (car keyval) x) - (succ keyval) - (loop ($tlc-next b)))))))])) - - (define-syntax incr-size! - (syntax-rules () - [(_ h vec) - (let ([size (fx+ (ht-size h) 1)] [n (vector-length vec)]) - (ht-size-set! h size) - (when (and (fx> size n) (fx< n (fxsrl (most-positive-fixnum) 1))) - (adjust! h vec n (fxsll n 1))))])) - - (define-syntax decr-size! - (syntax-rules () - [(_ h vec) - (let ([size (fx- (ht-size h) 1)] [n (vector-length vec)]) - (ht-size-set! h size) - (when (and (fx< size (fxsrl n 2)) (fx> n (ht-minlen h))) - (let ([target (fxmax (fxsll size 2) (ht-minlen h))]) - (let loop ([n2 n]) - (let ([n2 (fxsrl n2 1)]) - (if (fx<= n2 target) - (adjust! h vec n n2) - (loop n2)))))))])) - - (define adjust! - (lambda (h vec1 n1 n2) - (let ([vec2 ($make-eqhash-vector n2)] [mask2 (fx- n2 1)]) - (do ([i1 0 (fx+ i1 1)]) - ((fx= i1 n1)) - (let loop ([b (vector-ref vec1 i1)]) - (unless (fixnum? b) - (let ([next ($tlc-next b)] [keyval ($tlc-keyval b)]) - (let ([i2 (fxlogand ($fxaddress (car keyval)) mask2)]) - ($set-tlc-next! b (vector-ref vec2 i2)) - (vector-set! vec2 i2 b)) - (loop next))))) - (ht-vec-set! h vec2)))) - - (define-library-entry (eq-hashtable-ref h x v) - (lookup-keyval x - (let ([vec (ht-vec h)]) - (vector-ref vec (fxlogand ($fxaddress x) (fx- (vector-length vec) 1)))) - cdr v)) - - (define-library-entry (eq-hashtable-contains? h x) - (lookup-keyval x - (let ([vec (ht-vec h)]) - (vector-ref vec (fxlogand ($fxaddress x) (fx- (vector-length vec) 1)))) - (lambda (x) #t) - #f)) - - (define-library-entry (eq-hashtable-cell h x v) - (let* ([vec (ht-vec h)] - [idx (fxlogand ($fxaddress x) (fx- (vector-length vec) 1))] - [b (vector-ref vec idx)]) - (lookup-keyval x b - values - (let ([keyval (let ([subtype (eq-ht-subtype h)]) - (cond - [(eq? subtype (constant eq-hashtable-subtype-normal)) (cons x v)] - [(eq? subtype (constant eq-hashtable-subtype-weak)) (weak-cons x v)] - [else (ephemeron-cons x v)]))]) - (vector-set! vec idx ($make-tlc h keyval b)) - (incr-size! h vec) - keyval)))) - - (let () - (define do-set! - (lambda (h x v) - (let* ([vec (ht-vec h)] - [idx (fxlogand ($fxaddress x) (fx- (vector-length vec) 1))] - [b (vector-ref vec idx)]) - (lookup-keyval x b - (lambda (keyval) (set-cdr! keyval v)) - (begin - (vector-set! vec idx - ($make-tlc h - (let ([subtype (eq-ht-subtype h)]) - (cond - [(eq? subtype (constant eq-hashtable-subtype-normal)) (cons x v)] - [(eq? subtype (constant eq-hashtable-subtype-weak)) (weak-cons x v)] - [else (ephemeron-cons x v)])) - b)) - (incr-size! h vec)))))) - - (define-library-entry (eq-hashtable-set! h x v) - (do-set! h x v)) - - (define-library-entry (eq-hashtable-update! h x p v) - (let* ([vec (ht-vec h)] - [idx (fxlogand ($fxaddress x) (fx- (vector-length vec) 1))] - [b (vector-ref vec idx)]) - (lookup-keyval x b - (lambda (a) (set-cdr! a (p (cdr a)))) - (do-set! h x (p v)))))) - - (define-library-entry (eq-hashtable-delete! h x) - (let* ([vec (ht-vec h)] - [idx (fxlogand ($fxaddress x) (fx- (vector-length vec) 1))] - [b (vector-ref vec idx)]) - (unless (fixnum? b) - (if (eq? (car ($tlc-keyval b)) x) - (begin - (vector-set! vec idx ($tlc-next b)) - ($set-tlc-next! b #f) - (decr-size! h vec)) - (let loop ([b b]) - (let ([n ($tlc-next b)]) - (unless (fixnum? n) - (if (eq? (car ($tlc-keyval n)) x) - (begin - ($set-tlc-next! b ($tlc-next n)) - ($set-tlc-next! n #f) - (decr-size! h vec)) - (loop n))))))))) - ) - - ; symbol hashtable operations - (let () - (define-syntax incr-size! - (syntax-rules () - [(_ h vec) - (let ([size (fx+ (ht-size h) 1)] [n (vector-length vec)]) - (ht-size-set! h size) - (when (and (fx> size n) (fx< n (fxsrl (most-positive-fixnum) 1))) - (adjust! h vec (fxsll n 1))))])) - - (define-syntax decr-size! - (syntax-rules () - [(_ h vec) - (let ([size (fx- (ht-size h) 1)] [n (vector-length vec)]) - (ht-size-set! h size) - (when (and (fx< size (fxsrl n 2)) (fx> n (ht-minlen h))) - (adjust! h vec (fxsrl n 1))))])) - - (define adjust! - (lambda (h vec1 n2) - (let ([vec2 (make-vector n2 '())] - [mask2 (fx- n2 1)]) - (vector-for-each - (lambda (b) - (for-each - (lambda (a) - (let ([hc (fxlogand ($symbol-hash (car a)) mask2)]) - (vector-set! vec2 hc (cons a (vector-ref vec2 hc))))) - b)) - vec1) - (ht-vec-set! h vec2)))) - - (define-library-entry (symbol-hashtable-ref h x v) - (let ([hc ($symbol-hash x)]) - (if hc - (let ([vec (ht-vec h)]) - (let loop ([b (vector-ref vec (fxlogand hc (fx- (vector-length vec) 1)))]) - (if (null? b) - v - (let ([a (car b)]) - (if (eq? (car a) x) (cdr a) (loop (cdr b))))))) - (pariah v)))) - - (define-library-entry (symbol-hashtable-contains? h x) - (let ([hc ($symbol-hash x)]) - (and hc - (let ([vec (ht-vec h)]) - (let loop ([b (vector-ref vec (fxlogand hc (fx- (vector-length vec) 1)))]) - (and (not (null? b)) - (or (eq? (caar b) x) - (loop (cdr b))))))))) - - (define-library-entry (symbol-hashtable-cell h x v) - (let ([vec (ht-vec h)] [hc ($symbol-hash x)]) - (if hc - (let ([idx (fxlogand hc (fx- (vector-length vec) 1))]) - (let ([bucket (vector-ref vec idx)]) - (let loop ([b bucket]) - (if (null? b) - (let ([a (cons x v)]) - (vector-set! vec idx (cons a bucket)) - (incr-size! h vec) - a) - (let ([a (car b)]) - (if (eq? (car a) x) - a - (loop (cdr b)))))))) - (let ([idx (fxlogand (symbol-hash x) (fx- (vector-length vec) 1))]) - (let ([a (cons x v)]) - (vector-set! vec idx (cons a (vector-ref vec idx))) - (incr-size! h vec) - a))))) - - (define-library-entry (symbol-hashtable-set! h x v) - (let ([vec (ht-vec h)] [hc ($symbol-hash x)]) - (if hc - (let ([idx (fxlogand hc (fx- (vector-length vec) 1))]) - (let ([bucket (vector-ref vec idx)]) - (let loop ([b bucket]) - (if (null? b) - (begin - (vector-set! vec idx (cons (cons x v) bucket)) - (incr-size! h vec)) - (let ([a (car b)]) - (if (eq? (car a) x) (set-cdr! a v) (loop (cdr b)))))))) - (let ([idx (fxlogand (symbol-hash x) (fx- (vector-length vec) 1))]) - (vector-set! vec idx (cons (cons x v) (vector-ref vec idx))) - (incr-size! h vec))))) - - (define-library-entry (symbol-hashtable-update! h x p v) - (let ([vec (ht-vec h)] [hc ($symbol-hash x)]) - (if hc - (let ([idx (fxlogand hc (fx- (vector-length vec) 1))]) - (let ([bucket (vector-ref vec idx)]) - (let loop ([b bucket]) - (if (null? b) - (begin - (vector-set! vec idx (cons (cons x (p v)) bucket)) - (incr-size! h vec)) - (let ([a (car b)]) - (if (eq? (car a) x) - (set-cdr! a (p (cdr a))) - (loop (cdr b)))))))) - (let ([idx (fxlogand (symbol-hash x) (fx- (vector-length vec) 1))]) - (vector-set! vec idx (cons (cons x (p v)) (vector-ref vec idx))) - (incr-size! h vec))))) - - (define-library-entry (symbol-hashtable-delete! h x) - (let ([hc ($symbol-hash x)]) - (when hc - (let ([vec (ht-vec h)]) - (let ([idx (fxlogand hc (fx- (vector-length vec) 1))]) - (let loop ([b (vector-ref vec idx)] [p #f]) - (unless (null? b) - (let ([a (car b)]) - (if (eq? (car a) x) - (begin - (if p (set-cdr! p (cdr b)) (vector-set! vec idx (cdr b))) - (decr-size! h vec)) - (loop (cdr b) b)))))))))) - ) -) - -;;; the routines below may cause significant allocation without any -;;; embedded calls to other trap-checking routines, so we enable -;;; generation-interrupt-trap for them. -(eval-when (compile) (generate-interrupt-trap #t)) - -(define-library-entry (append ls1 ls2) - (let append ([ls1 ls1] [ls2 ls2]) - (if (null? ls1) - ls2 - (let ((cdr-ls1 (cdr ls1))) - (if (null? cdr-ls1) - (cons (car ls1) ls2) - (list* (car ls1) (car cdr-ls1) (append (cdr cdr-ls1) ls2))))))) diff --git a/ta6ob/s/library.ta6ob b/ta6ob/s/library.ta6ob deleted file mode 100644 index f8fe5af..0000000 Binary files a/ta6ob/s/library.ta6ob and /dev/null differ diff --git a/ta6ob/s/machine.def b/ta6ob/s/machine.def deleted file mode 100644 index ae40a2b..0000000 --- a/ta6ob/s/machine.def +++ /dev/null @@ -1,50 +0,0 @@ -;;; ta6ob.def -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(define-constant machine-type (constant machine-type-ta6ob)) -(define-constant architecture 'x86_64) -(define-constant address-bits 64) -(define-constant ptr-bits 64) -(define-constant int-bits 32) -(define-constant short-bits 16) -(define-constant long-bits 64) -(define-constant long-long-bits 64) -(define-constant size_t-bits 64) -(define-constant ptrdiff_t-bits 64) -(define-constant wchar-bits 32) -(define-constant time-t-bits 64) -(define-constant max-float-alignment 8) -(define-constant max-integer-alignment 8) -(define-constant asm-arg-reg-max 5) -(define-constant asm-arg-reg-cnt 3) -(define-constant typedef-ptr "void *") -(define-constant typedef-iptr "long int") -(define-constant typedef-uptr "unsigned long int") -(define-constant typedef-i8 "char") -(define-constant typedef-u8 "unsigned char") -(define-constant typedef-i16 "short") -(define-constant typedef-u16 "unsigned short") -(define-constant typedef-i32 "int") -(define-constant typedef-u32 "unsigned int") -(define-constant typedef-i64 "long") -(define-constant typedef-u64 "unsigned long") -(define-constant typedef-string-char "unsigned int") -(define-constant native-endianness 'little) -(define-constant unaligned-floats #t) -(define-constant unaligned-integers #t) -(define-constant integer-divide-instruction #t) -(define-constant software-floating-point #f) -(define-constant segment-table-levels 3) -(features iconv expeditor pthreads) diff --git a/ta6ob/s/mathprims.ss b/ta6ob/s/mathprims.ss deleted file mode 100644 index 83501ce..0000000 --- a/ta6ob/s/mathprims.ss +++ /dev/null @@ -1,769 +0,0 @@ -;;; mathprims.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -(begin -(eval-when (compile) - - (define-syntax define-relop - (syntax-rules () - [(_ name pred? err not-nan?) - (set! name - (case-lambda - [(x1 x2) (#2%name x1 x2)] - [(x1 x2 x3) (if (#2%name x1 x2) (#2%name x2 x3) (begin (#2%name x2 x3) #f))] - [(x1 x2 . rest) - (let loop ([x1 x1] [x2 x2] [rest rest]) - (if (#2%name x1 x2) - (or (null? rest) (loop x2 (car rest) (cdr rest))) - (let loop ([rest rest]) - (cond - [(null? rest) #f] - [(pred? (car rest)) (loop (cdr rest))] - [else (err 'name (car rest))]))))] - [(x1) - (unless (pred? x1) (err 'name x1)) - (#3%not-nan? x1)]))])) - - (define-syntax define-r6rs-relop ; requires 2+ arguments - (syntax-rules () - [(_ name pred? err) - (set! name - (case-lambda - [(x1 x2) (#2%name x1 x2)] - [(x1 x2 x3) (if (#2%name x1 x2) (#2%name x2 x3) (begin (#2%name x2 x3) #f))] - [(x1 x2 . rest) - (let loop ([x1 x1] [x2 x2] [rest rest]) - (if (#2%name x1 x2) - (or (null? rest) (loop x2 (car rest) (cdr rest))) - (let loop ([rest rest]) - (cond - [(null? rest) #f] - [(pred? (car rest)) (loop (cdr rest))] - [else (err 'name (car rest))]))))]))])) - - (define-syntax define-addop - (syntax-rules () - [(_ name) - (set! name - (case-lambda - [(x1 x2) (#2%name x1 x2)] - [(x1 x2 x3) (#2%name (#2%name x1 x2) x3)] - [(x1 x2 . rest) - (let loop ([x1 x1] [x2 x2] [rest rest]) - (let ([x (#2%name x1 x2)]) - (if (null? rest) x (loop x (car rest) (cdr rest)))))] - [(x1) (#2%name x1)] - [() (#2%name)]))])) - - (define-syntax define-subop - (syntax-rules () - [(_ name pred? err) - (set! name - (case-lambda - [(x1 x2) (#2%name x1 x2)] - [(x1 x2 x3) (#2%name (#2%name x1 x2) x3)] - [(x1) (#2%name x1)] - [(x0 x1 . rest) - (unless (pred? x0) (err 'name x0)) - (let loop ([x0 x0] [x1 x1] [rest rest]) - (unless (pred? x1) (err 'name x1)) - (if (null? rest) - (#3%name x0 x1) - (loop (#3%name x0 x1) (car rest) (cdr rest))))]))])) - - (define-syntax define-generic-subop - (syntax-rules () - [(_ name) - (set! name - (case-lambda - [(x1 x2) (#2%name x1 x2)] - [(x1 x2 x3) (#2%name (#2%name x1 x2) x3)] - [(x1) (#2%name x1)] - [(x0 x1 . rest) - (let loop ([x0 x0] [x1 x1] [rest rest]) - (if (null? rest) - (#2%name x0 x1) - (loop (#2%name x0 x1) (car rest) (cdr rest))))]))])) - - (define-syntax define-cfl-relop - (syntax-rules () - [(_ name pred? err not-nan?) - (set! name - (case-lambda - [(x1 x2) - (unless (pred? x1) (err 'name x1)) - (unless (pred? x2) (err 'name x2)) - (#3%name x1 x2)] - [(x1 x2 x3) - (unless (pred? x1) (err 'name x1)) - (unless (pred? x2) (err 'name x2)) - (unless (pred? x3) (err 'name x3)) - (and (#3%name x1 x2) (#3%name x2 x3))] - [(x1 x2 . rest) - (unless (pred? x1) (err 'name x1)) - (let loop ([x1 x1] [x2 x2] [rest rest]) - (unless (pred? x2) (err 'name x2)) - (if (#3%name x1 x2) - (or (null? rest) (loop x2 (car rest) (cdr rest))) - (let loop ([rest rest]) - (cond - [(null? rest) #f] - [(pred? (car rest)) (loop (cdr rest))] - [else (err 'name (car rest))]))))] - [(x1) - (unless (pred? x1) (err 'name x1)) - (not-nan? x1)]))])) - - (define-syntax define-cfl-addop - (syntax-rules () - [(_ name pred? err) - (set! name - (case-lambda - [(x1 x2) - (unless (pred? x1) (err 'name x1)) - (unless (pred? x2) (err 'name x2)) - (#3%name x1 x2)] - [(x1 x2 x3) - (unless (pred? x1) (err 'name x1)) - (unless (pred? x2) (err 'name x2)) - (unless (pred? x3) (err 'name x3)) - (#3%name (#3%name x1 x2) x3)] - [(x1 x2 . rest) - (unless (pred? x1) (err 'name x1)) - (let loop ([x1 x1] [x2 x2] [rest rest]) - (unless (pred? x2) (err 'name x2)) - (let ([x (#3%name x1 x2)]) - (if (null? rest) x (loop x (car rest) (cdr rest)))))] - [(x1) - (unless (pred? x1) (err 'name x1)) - (#3%name x1)] - [() (name)]))])) - - (define-syntax define-cfl-subop - (syntax-rules () - [(_ name pred? err) - (set! name - (case-lambda - [(x1 x2) - (unless (pred? x1) (err 'name x1)) - (unless (pred? x2) (err 'name x2)) - (#3%name x1 x2)] - [(x1 x2 x3) - (unless (pred? x1) (err 'name x1)) - (unless (pred? x2) (err 'name x2)) - (unless (pred? x3) (err 'name x3)) - (#3%name (#3%name x1 x2) x3)] - [(x1) - (unless (pred? x1) (err 'name x1)) - (#3%name x1)] - [(x0 x1 . rest) - (unless (pred? x0) (err 'name x0)) - (let loop ([x0 x0] [x1 x1] [rest rest]) - (unless (pred? x1) (err 'name x1)) - (if (null? rest) - (#3%name x0 x1) - (loop (#3%name x0 x1) (car rest) (cdr rest))))]))])) -) - -(define 1- (lambda (x) (#2%1- x))) - -(define 1+ (lambda (x) (#2%1+ x))) - -(define sub1 (lambda (x) (#2%sub1 x))) - -(define -1+ (lambda (x) (#2%-1+ x))) - -(define add1 (lambda (x) (#2%add1 x))) - -(define-addop +) -(define-generic-subop -) -(define-addop *) -(define-generic-subop /) - -(define-addop logand) -(define-addop bitwise-and) -(define-addop logior) -(define-addop bitwise-ior) -(define-addop logor) -(define-addop logxor) -(define-addop bitwise-xor) - -(define (lognot x) (#2%lognot x)) -(define (bitwise-not x) (#2%bitwise-not x)) - -(define (logbit? x y) (#2%logbit? x y)) -(define (bitwise-bit-set? x y) (#2%bitwise-bit-set? x y)) -(define (logbit0 x y) (#2%logbit0 x y)) -(define (logbit1 x y) (#2%logbit1 x y)) -(define (logtest x y) (#2%logtest x y)) - -(eval-when (compile) - (define-syntax define-number-relop - (syntax-rules () - [(_ name) - (define name - (case-lambda - [(x1 x2) (#2%name x1 x2)] - [(x1 x2 x3) (if (#2%name x1 x2) (#2%name x2 x3) (begin (#2%name x2 x3) #f))] - [(x1) (begin (#2%name x1 0) #t)] - [(x1 x2 . rest) - (let loop ([x1 x1] [x2 x2] [ls rest]) - (if (or (null? ls) (loop x2 (car ls) (cdr ls))) - (#2%name x1 x2) - (begin (#2%name x1 x2) #f)))]))]))) - -(define-number-relop =) -(define-number-relop <) -(define-number-relop >) -(define-number-relop <=) -(define-number-relop >=) - -(eval-when (compile) - (define-syntax define-r6rs-number-relop ; requires 2+ argument - (syntax-rules () - [(_ r6rs:name name) - (define-who #(r6rs: name) - (case-lambda - [(x1 x2) (#2%r6rs:name x1 x2)] - [(x1 x2 x3) (if (#2%r6rs:name x1 x2) - (#2%r6rs:name x2 x3) - (begin (#2%r6rs:name x2 x3) #f))] - [(x1 x2 . rest) - (let loop ([x1 x1] [x2 x2] [ls rest]) - (if (or (null? ls) (loop x2 (car ls) (cdr ls))) - (#2%r6rs:name x1 x2) - (begin (#2%r6rs:name x1 x2) #f)))]))]))) - -(define-r6rs-number-relop r6rs:= =) -(define-r6rs-number-relop r6rs:< <) -(define-r6rs-number-relop r6rs:> >) -(define-r6rs-number-relop r6rs:<= <=) -(define-r6rs-number-relop r6rs:>= >=) - -(eval-when (compile) (optimize-level 3)) - -(let () - (define flargerr - (lambda (who x) - ($oops who "~s is not a flonum" x))) - - (set! fl-make-rectangular - (lambda (x y) - (unless (flonum? x) (flargerr 'fl-make-rectangular x)) - (unless (flonum? y) (flargerr 'fl-make-rectangular y)) - (#3%fl-make-rectangular x y))) - - (define-addop fl+) - (define-subop fl- flonum? flargerr) - (define-addop fl*) - (define-subop fl/ flonum? flargerr) - - (set! flabs - (lambda (x) - (unless (flonum? x) (flargerr 'flabs x)) - (#3%flabs x))) - - (set! flround - (lambda (x) - (unless (flonum? x) (flargerr 'flround x)) - (#3%flround x))) - - (set! fllp - (lambda (x) - (unless (flonum? x) (flargerr 'fllp x)) - (#3%fllp x))) - - (define-relop fl= flonum? flargerr fl=) - (define-relop fl< flonum? flargerr fl=) - (define-relop fl> flonum? flargerr fl=) - (define-relop fl<= flonum? flargerr fl=) - (define-relop fl>= flonum? flargerr fl=) - (define-r6rs-relop fl=? flonum? flargerr) - (define-r6rs-relop fl? flonum? flargerr) - (define-r6rs-relop fl<=? flonum? flargerr) - (define-r6rs-relop fl>=? flonum? flargerr) - - (set-who! $fleqv? - (lambda (x y) - (unless (flonum? x) (flargerr who x)) - (unless (flonum? y) (flargerr who y)) - (#3%$fleqv? x y))) - - (set-who! $flhash - (lambda (x) - (unless (flonum? x) (flargerr who x)) - (#3%$flhash x))) - - (set-who! $flonum-exponent ; requires optimize-level 3 - (lambda (x) - (unless (flonum? x) (flargerr who x)) - ($flonum-exponent x))) - - (set-who! $flonum-sign ; requires optimize-level 3 - (lambda (x) - (unless (flonum? x) (flargerr who x)) - ($flonum-sign x))) - - (set-who! flonum->fixnum - (let ([flmnf (fixnum->flonum (most-negative-fixnum))] - [flmpf (fixnum->flonum (most-positive-fixnum))]) - (lambda (x) - (unless (flonum? x) (flargerr who x)) - (unless (fl<= flmnf x flmpf) - ($oops who "result for ~s would be outside of fixnum range" x)) - (#3%flonum->fixnum x)))) -) - -(let () - (define fxargerr - (lambda (who x) - ($oops who "~s is not a fixnum" x))) - - (define /zeroerr - (lambda (who) - ($oops who "attempt to divide by zero"))) - - (define fxanserr - (lambda (who . args) - ($impoops who "fixnum overflow computing ~s" (cons who args)))) - - (define-addop fx+) - (define-subop fx- fixnum? fxargerr) - - (set-who! #(r6rs: fx+) (lambda (x y) (#2%r6rs:fx+ x y))) - (set-who! #(r6rs: fx-) - (case-lambda - [(x) (#2%r6rs:fx- x)] - [(x y) (#2%r6rs:fx- x y)])) - - (set! fx1- - (lambda (x) - (#2%fx1- x))) - - (set! fx1+ - (lambda (x) - (#2%fx1+ x))) - - (set! fxzero? - (lambda (x) - (#2%fxzero? x))) - - (set! fx* - (rec fx* - (case-lambda - [(x1 x2) - (if (fixnum? x1) - (if (fixnum? x2) - ; should handle fixnums (avoiding overflow) - (let ([n (* x1 x2)]) - (if (fixnum? n) n (fxanserr 'fx* x1 x2))) - (fxargerr 'fx* x2)) - (fxargerr 'fx* x1))] - [(x1 x2 x3) - (if (fixnum? x1) - (if (fixnum? x2) - (if (fixnum? x3) - ; should handle fixnums (avoiding overflow) - (let ([n (* x1 x2)]) - (if (fixnum? n) - ; should handle fixnums (avoiding overflow) - (let ([n (* n x3)]) - (if (fixnum? n) n (fxanserr 'fx* x1 x2 x3))) - (fxanserr 'fx* x1 x2 x3))) - (fxargerr 'fx* x3)) - (fxargerr 'fx* x2)) - (fxargerr 'fx* x1))] - [(x1) (if (fixnum? x1) x1 (fxargerr 'fx* x1))] - [() 1] - [(x1 . rest) - (let loop ([a x1] [ls rest]) - (if (null? ls) - a - (loop (fx* a (car ls)) (cdr ls))))]))) - - (set-who! #(r6rs: fx*) - (lambda (x1 x2) - (if (fixnum? x1) - (if (fixnum? x2) - ; should handle fixnums (avoiding overflow) - (let ([n (* x1 x2)]) - (if (fixnum? n) n (fxanserr who x1 x2))) - (fxargerr who x2)) - (fxargerr who x1)))) - - (set! fxquotient - (rec fxquotient - (case-lambda - [(x1 x2) - (if (fixnum? x1) - (if (fixnum? x2) - (begin - (when (fx= x2 0) (/zeroerr 'fxquotient)) - (if (and (fx= x2 -1) (fx= x1 (most-negative-fixnum))) - (fxanserr 'fxquotient x1 x2) - (#3%fxquotient x1 x2))) - (fxargerr 'fxquotient x2)) - (fxargerr 'fxquotient x1))] - [(x1 x2 x3) - (if (fixnum? x1) - (if (fixnum? x2) - (if (fixnum? x3) - (begin - (when (fx= x2 0) (/zeroerr 'fxquotient)) - (if (and (fx= x2 -1) (fx= x1 (most-negative-fixnum))) - (fxanserr 'fxquotient x1 x2 x3) - (let ([n (#3%fxquotient x1 x2)]) - (when (fx= x3 0) (/zeroerr 'fxquotient)) - (if (and (fx= x3 -1) (fx= n (most-negative-fixnum))) - (fxanserr 'fxquotient x1 x2 x3) - (#3%fxquotient n x3))))) - (fxargerr 'fxquotient x3)) - (fxargerr 'fxquotient x2)) - (fxargerr 'fxquotient x1))] - [(x1) - (if (fixnum? x1) - (if (fx= x1 0) - (/zeroerr 'fxquotient) - (#3%fxquotient 1 x1)) - (fxargerr 'fxquotient x1))] - [(x1 . rest) - (let loop ([a x1] [ls rest]) - (if (null? ls) - a - (loop (fxquotient a (car ls)) (cdr ls))))]))) - - (set! fx/ - (rec fx/ ;; same as fxquotient---should it be? - (case-lambda - [(x1 x2) - (if (fixnum? x1) - (if (fixnum? x2) - (begin - (when (fx= x2 0) (/zeroerr 'fx/)) - (if (and (fx= x2 -1) (fx= x1 (most-negative-fixnum))) - (fxanserr 'fx/ x1 x2) - (#3%fx/ x1 x2))) - (fxargerr 'fx/ x2)) - (fxargerr 'fx/ x1))] - [(x1 x2 x3) - (if (fixnum? x1) - (if (fixnum? x2) - (if (fixnum? x3) - (begin - (when (fx= x2 0) (/zeroerr 'fx/)) - (if (and (fx= x2 -1) (fx= x1 (most-negative-fixnum))) - (fxanserr 'fx/ x1 x2 x3) - (let ([n (#3%fx/ x1 x2)]) - (when (fx= x3 0) (/zeroerr 'fx/)) - (if (and (fx= x3 -1) (fx= n (most-negative-fixnum))) - (fxanserr 'fx/ x1 x2 x3) - (#3%fx/ n x3))))) - (fxargerr 'fx/ x3)) - (fxargerr 'fx/ x2)) - (fxargerr 'fx/ x1))] - [(x1) - (if (fixnum? x1) - (if (fx= x1 0) - (/zeroerr 'fx/) - (#3%fx/ 1 x1)) - (fxargerr 'fx/ x1))] - [(x1 . rest) - (let loop ([a x1] [ls rest]) - (if (null? ls) - a - (loop (fx/ a (car ls)) (cdr ls))))]))) - - (set! fxabs - (lambda (x) - (unless (fixnum? x) (fxargerr 'fxabs x)) - (when (fx= x (most-negative-fixnum)) (fxanserr 'fxabs x)) - (#3%fxabs x))) - - (define-relop fx= fixnum? fxargerr fx=) - (define-relop fx< fixnum? fxargerr fx=) - (define-relop fx> fixnum? fxargerr fx=) - (define-relop fx<= fixnum? fxargerr fx=) - (define-relop fx>= fixnum? fxargerr fx=) - (define-r6rs-relop fx=? fixnum? fxargerr) - (define-r6rs-relop fx? fixnum? fxargerr) - (define-r6rs-relop fx<=? fixnum? fxargerr) - (define-r6rs-relop fx>=? fixnum? fxargerr) - - (set! $fxu< - (lambda (x y) - (unless (fixnum? x) (fxargerr '$fxu< x)) - (unless (fixnum? y) (fxargerr '$fxu< y)) - (#3%$fxu< x y))) - - (define-addop fxlogand) - (define-addop fxlogior) - (define-addop fxlogor) - (define-addop fxlogxor) - (define-addop fxand) - (define-addop fxior) - (define-addop fxxor) - - (set! fxsll - (lambda (x y) - (#2%fxsll x y))) - - (set! fxarithmetic-shift-left - (lambda (x y) - (#2%fxarithmetic-shift-left x y))) - - (set! fxsrl - (lambda (x y) - (#2%fxsrl x y))) - - (set! fxsra - (lambda (x y) - (#2%fxsra x y))) - - (set! fxarithmetic-shift-right - (lambda (x y) - (#2%fxarithmetic-shift-right x y))) - - (set! fxarithmetic-shift - (lambda (x y) - (#2%fxarithmetic-shift x y))) - - (set! fxlognot - (lambda (x) - (#2%fxlognot x))) - - (set! fxnot - (lambda (x) - (#2%fxnot x))) - - (set! fxlogtest - (lambda (x y) - (#2%fxlogtest x y))) - - (set! fxlogbit? - (lambda (x y) - (#2%fxlogbit? x y))) - - (set! fxbit-set? - (lambda (x y) - (#2%fxbit-set? x y))) - - (set! fxlogbit0 - (lambda (x y) - (#2%fxlogbit0 x y))) - - (set! fxlogbit1 - (lambda (x y) - (#2%fxlogbit1 x y))) - - (set-who! fxcopy-bit - (lambda (n k b) - ; optimize-level 2 handler doesn't kick in unless b=0 or b=1 - (unless (fixnum? n) (fxargerr who n)) - (unless (fixnum? k) (fxargerr who k)) - (unless ($fxu< k (fx- (fixnum-width) 1)) - ($oops who "invalid bit index ~s" k)) - (case b - [(0) (#3%fxlogbit0 k n)] - [(1) (#3%fxlogbit1 k n)] - [else ($oops who "invalid bit value ~s" b)]))) - - (set! fxeven? - (lambda (x) - (#2%fxeven? x))) - - (set! fxodd? - (lambda (x) - (#2%fxodd? x))) - - (set! fxremainder - (lambda (x y) - (unless (fixnum? x) (fxargerr 'fxremainder x)) - (unless (fixnum? y) (fxargerr 'fxremainder y)) - (when (fx= y 0) (/zeroerr 'fxremainder)) - (#3%fxremainder x y))) - - (set! fxmodulo - (lambda (x y) - (unless (fixnum? x) (fxargerr 'fxmodulo x)) - (unless (fixnum? y) (fxargerr 'fxmodulo y)) - (when (fx= y 0) (/zeroerr 'fxmodulo)) - (let ([r (fxremainder x y)]) - (if (if (fxnegative? y) (fxpositive? r) (fxnegative? r)) - (fx+ r y) - r)))) - - (set! fxmin - (case-lambda - [(x y) - (unless (fixnum? x) (fxargerr 'fxmin x)) - (unless (fixnum? y) (fxargerr 'fxmin y)) - (if (fx< y x) y x)] - [(x y z) - (unless (fixnum? x) (fxargerr 'fxmin x)) - (unless (fixnum? y) (fxargerr 'fxmin y)) - (unless (fixnum? z) (fxargerr 'fxmin z)) - (if (fx< y x) - (if (fx< z y) z y) - (if (fx< z x) z x))] - [(x . y) - (unless (fixnum? x) (fxargerr 'fxmin x)) - (let f ([x x] [y y]) - (if (null? y) - x - (f (let ([z (car y)]) - (unless (fixnum? z) (fxargerr 'fxmin z)) - (if (fx< z x) z x)) - (cdr y))))])) - - (set! fxmax - (case-lambda - [(x y) - (unless (fixnum? x) (fxargerr 'fxmax x)) - (unless (fixnum? y) (fxargerr 'fxmax y)) - (if (fx> y x) y x)] - [(x y z) - (unless (fixnum? x) (fxargerr 'fxmax x)) - (unless (fixnum? y) (fxargerr 'fxmax y)) - (unless (fixnum? z) (fxargerr 'fxmax z)) - (if (fx> y x) - (if (fx> z y) z y) - (if (fx> z x) z x))] - [(x . y) - (unless (fixnum? x) (fxargerr 'fxmax x)) - (let f ([x x] [y y]) - (if (null? y) - x - (f (let ([z (car y)]) - (unless (fixnum? z) (fxargerr 'fxmax z)) - (if (fx> z x) z x)) - (cdr y))))])) - - (set! fxnegative? - (lambda (x) - (#2%fxnegative? x))) - - (set! fxpositive? - (lambda (x) - (#2%fxpositive? x))) - - (set! fxnonnegative? - (lambda (x) - (#2%fxnonnegative? x))) - - (set! fxnonpositive? - (lambda (x) - (#2%fxnonpositive? x))) - - (set! fixnum->flonum - (lambda (x) - (unless (fixnum? x) (fxargerr 'fixnum->flonum x)) - (#3%fixnum->flonum x))) - - (set-who! fxlength - (lambda (x) - (if (fixnum? x) - (#3%fxlength x) - (fxargerr who x)))) - - (set-who! fxfirst-bit-set - (lambda (x) - (if (fixnum? x) - (#3%fxfirst-bit-set x) - (fxargerr who x)))) - - (set-who! fxif - (lambda (x y z) - (if (fixnum? x) - (if (fixnum? y) - (if (fixnum? z) - (#3%fxif x y z) - (fxargerr who z)) - (fxargerr who y)) - (fxargerr who x)))) - - (set-who! fxbit-field - (lambda (n start end) - (if (fixnum? n) - (if (and (fixnum? start) ($fxu< start (fixnum-width))) - (if (and (fixnum? end) ($fxu< end (fixnum-width))) - (if (fx<= start end) - (fxsra (fxand n (fxnot (fxsll -1 end))) start) - ($oops who "start index ~s is greater than end index ~s" start end)) - ($oops who "~s is not a valid end index" end)) - ($oops who "~s is not a valid start index" start)) - (fxargerr who n)))) - - (set-who! fxcopy-bit-field - (lambda (n start end m) - (if (fixnum? n) - (if (and (fixnum? start) ($fxu< start (fixnum-width))) - (if (and (fixnum? end) ($fxu< end (fixnum-width))) - (if (fx<= start end) - (if (fixnum? m) - (let ([mask (fx- (fxsll 1 (fx- end start)) 1)]) - (fxior - (fxand n (fxnot (fxsll mask start))) - (fxsll (fxand m mask) start))) - (fxargerr who m)) - ($oops who "start index ~s is greater than end index ~s" start end)) - ($oops who "~s is not a valid end index" end)) - ($oops who "~s is not a valid start index" start)) - (fxargerr who n)))) -) - -;;; The "cfl" operations could be done at level 0 by expanding them out. -;;; They might be more efficient that way since they wouldn't have to -;;; do double flonum checking. - -(define cflonum? - (lambda (x) - (cflonum? x))) - -(let () - -(define noncflonum-error - (lambda (who x) - ($oops who "~s is not a cflonum" x))) - -(set! cfl-real-part - (lambda (z) - (type-case z - [($inexactnum?) ($inexactnum-real-part z)] - [(flonum?) z] - [else (noncflonum-error 'cfl-real-part z)]))) - -(set! cfl-imag-part - (lambda (z) - (type-case z - [($inexactnum?) ($inexactnum-imag-part z)] - [(flonum?) 0.0] - [else (noncflonum-error 'cfl-imag-part z)]))) - -(define-cfl-addop cfl+ cflonum? noncflonum-error) -(define-cfl-addop cfl* cflonum? noncflonum-error) -(define-cfl-subop cfl- cflonum? noncflonum-error) -(define-cfl-subop cfl/ cflonum? noncflonum-error) -(define-cfl-relop cfl= cflonum? noncflonum-error cfl=) - -(set! cfl-conjugate - (lambda (x) - (type-case x - [(cflonum?) (#3%cfl-conjugate x)] - [else (noncflonum-error 'cfl-conjugate x)]))) - -) -) diff --git a/ta6ob/s/mathprims.ta6ob b/ta6ob/s/mathprims.ta6ob deleted file mode 100644 index ff7a3cf..0000000 Binary files a/ta6ob/s/mathprims.ta6ob and /dev/null differ diff --git a/ta6ob/s/mkheader.so b/ta6ob/s/mkheader.so deleted file mode 100644 index d119944..0000000 Binary files a/ta6ob/s/mkheader.so and /dev/null differ diff --git a/ta6ob/s/mkheader.ss b/ta6ob/s/mkheader.ss deleted file mode 100644 index 09c2186..0000000 --- a/ta6ob/s/mkheader.ss +++ /dev/null @@ -1,1004 +0,0 @@ -;;; mkheader.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; requires cmacros.ss -(disable-unbound-warning - mkscheme.h - mkequates.h -) - -(define mkscheme.h) -(define mkequates.h) -(let () - (define op) - (define-syntax pr - (syntax-rules () - ((_ fmt arg ...) (fprintf op fmt arg ...)))) - (define nl - (lambda () - (newline op))) - (define-syntax $ - (syntax-rules () - ((_ x) (constant x)))) - (define-syntax comment - (syntax-rules () - ((_ fmt arg ...) (pr "/* ~a */~%" (format fmt arg ...))))) - (define sanitize - (lambda (x) - (list->string - (fold-right (lambda (x rest) - (case x - [(#\-) (cons #\_ rest)] - [(#\?) (cons #\p rest)] - [(#\>) rest] - [(#\*) (cons #\s rest)] - [else (cons x rest)])) - '() - (string->list (symbol->string x)))))) - (define sanitize-type - (lambda (x) - (list->string - (map (lambda (x) - (case x - [(#\-) #\_] - [else x])) - (string->list (symbol->string x)))))) - (define def - (case-lambda - [(lhs rhs) (pr "#define ~a ~a~%" lhs rhs)] - [(name args rhs) (pr "#define ~a~a ~a~%" name args rhs)])) - (define export - (lambda (tresult name targs) - (pr "EXPORT ~a ~a~a;~%" tresult name targs))) - (define &ref - (lambda (cast x disp) - (format "(~a((uptr)(~a)~:[+~;-~]~d))" cast x (fx< disp 0) (abs disp)))) - (define ref - (lambda (cast x disp) - (format "(*~a)" (&ref cast x disp)))) - (define defref-help - (lambda (ref name struct field) - (cond - [(assq field (getprop struct '*fields* '())) => - (lambda (a) - (apply - (lambda (field type disp len) - (if len - (def (format "~s(x,i)" name) - (format (if (eq? ref &ref) "(~a+i)" "(~a[i])") - (&ref (format "(~a *)" (sanitize-type type)) "x" disp))) - (def (format "~s(x)" name) - (ref (format "(~a *)" (sanitize-type type)) "x" disp)))) - a))] - [else ($oops 'defref-help "undefined field ~s-~s" struct field)]))) - (define defset-help - (lambda (name struct field) - (cond - [(assq field (getprop struct '*fields* '())) => - (lambda (a) - (apply - (lambda (field type disp len) - (unless (eq? type 'ptr) - ($oops 'defset-help "non-ptr type ~s" type)) - (if len - (def (format "~s(x,i,y)" name) - (format "DIRTYSET((~a+i),(y))" - (&ref "(ptr *)" "x" disp))) - (def (format "~s(x,y)" name) - (format "DIRTYSET(~a,(y))" - (&ref "(ptr *)" "x" disp))))) - a))] - [else ($oops 'defset-help "undefined field ~s-~s" struct field)]))) - (define-syntax defref - (syntax-rules () - [(_ name struct field) - (defref-help ref 'name 'struct 'field)])) - (define-syntax definit ; presently same as defref - (syntax-rules () - [(_ name struct field) - (defref name struct field)])) - (define-syntax defset - (syntax-rules () - [(_ name struct field) - (defset-help 'name 'struct 'field)])) - (define access-help - (lambda (arg idx struct field) - (cond - [(assq field (getprop struct '*fields* '())) => - (lambda (a) - (apply - (lambda (field type disp len) - (if (not idx) - (if (not len) - (ref (format "(~a *)" (sanitize-type type)) arg disp) - ($oops 'access "no idx provided for array field ~s-~s" struct field)) - (if len - (format "(~a[~a])" (&ref (format "(~a *)" (sanitize-type type)) arg disp) idx) - ($oops 'access "no idx provided for array field ~s-~s" struct field)))) - a))] - [else ($oops 'access "undefined field ~s-~s" struct field)]))) - (define-syntax access - (syntax-rules () - [(_ arg struct field) - (access-help arg #f 'struct 'field)] - [(_ arg idx struct field) - (access-help arg idx 'struct 'field)])) - (define typep - (lambda (x mask tag) - (if (= mask (constant byte-constant-mask)) - (format "((uptr)(~a)==0x~x)" x tag) - (format "(((uptr)(~a)&0x~x)==0x~x)" x mask tag)))) - (define deftypep - (lambda (name mask tag) - (def name "(x)" (typep "x" mask tag)))) - (define deftotypep - (let ((type-disp (- ($ typemod) ($ type-typed-object)))) - (lambda (name mask tag) - (def name "(x)" - (format "(~a &&\\~% ~a)" - (typep "x" ($ mask-typed-object) ($ type-typed-object)) - (typep (ref "(ptr *)" "x" type-disp) mask tag)))))) - (define scheme-version ; adapted from 7.ss - (let ([n (constant scheme-version)]) - (if (= (logand n 255) 0) - (format "~d.~d" - (ash n -16) - (logand (ash n -8) 255)) - (format "~d.~d.~d" - (ash n -16) - (logand (ash n -8) 255) - (logand n 255))))) - - (set-who! mkscheme.h - (lambda (ofn target-machine) - (fluid-let ([op (open-output-file ofn 'replace)]) - (comment "scheme.h for Chez Scheme Version ~a (~a)" scheme-version target-machine) - - (nl) - (comment "Do not edit this file. It is automatically generated and") - (comment "specifically tailored to the version of Chez Scheme named") - (comment "above. Always be certain that you have the correct scheme.h") - (comment "for the version of Chez Scheme you are using.") - - (nl) - (comment "Warning: Some macros may evaluate arguments more than once.") - - (nl) (comment "Specify declaration of exports.") - (pr "#ifdef _WIN32~%") - (pr "# if __cplusplus~%") - (pr "# ifdef SCHEME_IMPORT~%") - (pr "# define EXPORT extern \"C\" __declspec (dllimport)~%") - (pr "# elif SCHEME_STATIC~%") - (pr "# define EXPORT extern \"C\"~%") - (pr "# else~%") - (pr "# define EXPORT extern \"C\" __declspec (dllexport)~%") - (pr "# endif~%") - (pr "# else~%") - (pr "# ifdef SCHEME_IMPORT~%") - (pr "# define EXPORT extern __declspec (dllimport)~%") - (pr "# elif SCHEME_STATIC~%") - (pr "# define EXPORT extern~%") - (pr "# else~%") - (pr "# define EXPORT extern __declspec (dllexport)~%") - (pr "# endif~%") - (pr "# endif~%") - (pr "#else~%") - (pr "# if __cplusplus~%") - (pr "# define EXPORT extern \"C\"~%") - (pr "# else~%") - (pr "# define EXPORT extern~%") - (pr "# endif~%") - (pr "#endif~%") - - (nl) (comment "Chez Scheme Version and machine type") - (pr "#define VERSION \"~a\"~%" scheme-version) - (pr "#define MACHINE_TYPE \"~a\"~%" target-machine) - - (nl) - (comment "All Scheme objects are of type ptr. Type iptr and") - (comment "uptr are signed and unsigned ints of the same size") - (comment "as a ptr") - (pr "typedef ~a ptr;~%" (constant typedef-ptr)) - (pr "typedef ~a iptr;~%" (constant typedef-iptr)) - (pr "typedef ~a uptr;~%" (constant typedef-uptr)) - - (nl) - (comment "String elements are 32-bit tagged char objects") - (pr "typedef ~a string_char;~%" (constant typedef-string-char)) - - (nl) - (comment "Bytevector elements are 8-bit unsigned \"octets\"") - (pr "typedef unsigned char octet;~%") - - (nl) (comment "Type predicates") - (deftypep "Sfixnump" ($ mask-fixnum) ($ type-fixnum)) - (deftypep "Scharp" ($ mask-char) ($ type-char)) - (deftypep "Snullp" ($ mask-nil) ($ snil)) - (deftypep "Seof_objectp" ($ mask-eof) ($ seof)) - (deftypep "Sbwp_objectp" ($ mask-bwp) ($ sbwp)) - (deftypep "Sbooleanp" ($ mask-boolean) ($ type-boolean)) - - (deftypep "Spairp" ($ mask-pair) ($ type-pair)) - (deftypep "Ssymbolp" ($ mask-symbol) ($ type-symbol)) - (deftypep "Sprocedurep" ($ mask-closure) ($ type-closure)) - (deftypep "Sflonump" ($ mask-flonum) ($ type-flonum)) - - (deftotypep "Svectorp" ($ mask-vector) ($ type-vector)) - (deftotypep "Sfxvectorp" ($ mask-fxvector) ($ type-fxvector)) - (deftotypep "Sbytevectorp" ($ mask-bytevector) ($ type-bytevector)) - (deftotypep "Sstringp" ($ mask-string) ($ type-string)) - (deftotypep "Sbignump" ($ mask-bignum) ($ type-bignum)) - (deftotypep "Sboxp" ($ mask-box) ($ type-box)) - (deftotypep "Sinexactnump" ($ mask-inexactnum) ($ type-inexactnum)) - (deftotypep "Sexactnump" ($ mask-exactnum) ($ type-exactnum)) - (deftotypep "Sratnump" ($ mask-ratnum) ($ type-ratnum)) - - (deftotypep "Sinputportp" ($ mask-input-port) ($ type-input-port)) - (deftotypep "Soutputportp" ($ mask-output-port) ($ type-output-port)) - (deftotypep "Srecordp" ($ mask-record) ($ type-record)) - - (nl) (comment "Accessors") - (def "Sfixnum_value(x)" (format "((iptr)(x)/~d)" ($ fixnum-factor))) - (def "Schar_value(x)" (format "((string_char)((uptr)(x)>>~d))" ($ char-data-offset))) - (def "Sboolean_value(x)" "((x) != Sfalse)") - - (defref Scar pair car) - (defref Scdr pair cdr) - - (defref Sflonum_value flonum data) - - (def "Svector_length(x)" - (format "((iptr)((uptr)~a>>~d))" - (access "x" vector type) - ($ vector-length-offset))) - (defref Svector_ref vector data) - - (def "Sfxvector_length(x)" - (format "((iptr)((uptr)~a>>~d))" - (access "x" fxvector type) - ($ fxvector-length-offset))) - (defref Sfxvector_ref fxvector data) - - (def "Sbytevector_length(x)" - (format "((iptr)((uptr)~a>>~d))" - (access "x" bytevector type) - ($ bytevector-length-offset))) - (defref Sbytevector_u8_ref bytevector data) - (comment "Warning: Sbytevector_data(x) returns a pointer into x.") - (def "Sbytevector_data(x)" "&Sbytevector_u8_ref(x,0)") - - (def "Sstring_length(x)" - (format "((iptr)((uptr)~a>>~d))" - (access "x" string type) - ($ string-length-offset))) - (def "Sstring_ref(x,i)" - (format "Schar_value~a" (access "x" "i" string data))) - - (defref Sunbox box ref) - - (export "iptr" "Sinteger_value" "(ptr)") - (def "Sunsigned_value(x)" "(uptr)Sinteger_value(x)") - (export (constant typedef-i32) "Sinteger32_value" "(ptr)") - (def "Sunsigned32_value(x)" (format "(~a)Sinteger32_value(x)" (constant typedef-u32))) - (export (constant typedef-i64) "Sinteger64_value" "(ptr)") - (def "Sunsigned64_value(x)" (format "(~a)Sinteger64_value(x)" (constant typedef-u64))) - - (nl) (comment "Mutators") - (export "void" "Sset_box" "(ptr, ptr)") - (export "void" "Sset_car" "(ptr, ptr)") - (export "void" "Sset_cdr" "(ptr, ptr)") - (def "Sstring_set(x,i,c)" - (format "((void)(~a = (string_char)(uptr)Schar(c)))" - (access "x" "i" string data))) - (def "Sfxvector_set(x,i,n)" "((void)(Sfxvector_ref(x,i) = (n)))") - (def "Sbytevector_u8_set(x,i,n)" "((void)(Sbytevector_u8_ref(x,i) = (n)))") - (export "void" "Svector_set" "(ptr, iptr, ptr)") - - (nl) (comment "Constructors") - (def "Sfixnum(x)" (format "((ptr)(uptr)((x)*~d))" ($ fixnum-factor))) - (def "Schar(x)" - (format "((ptr)(uptr)((x)<<~d|0x~x))" - ($ char-data-offset) - ($ type-char))) - (def "Snil" (format "((ptr)0x~x)" ($ snil))) - (def "Strue" (format "((ptr)0x~x)" ($ strue))) - (def "Sfalse" (format "((ptr)0x~x)" ($ sfalse))) - (def "Sboolean(x)" "((x)?Strue:Sfalse)") - (def "Sbwp_object" (format "((ptr)0x~x)" ($ sbwp))) - (def "Seof_object" (format "((ptr)0x~x)" ($ seof))) - (def "Svoid" (format "((ptr)0x~x)" ($ svoid))) - - (export "ptr" "Scons" "(ptr, ptr)") - (export "ptr" "Sstring_to_symbol" "(const char *)") - (export "ptr" "Ssymbol_to_string" "(ptr)") - (export "ptr" "Sflonum" "(double)") - (export "ptr" "Smake_vector" "(iptr, ptr)") - (export "ptr" "Smake_fxvector" "(iptr, ptr)") - (export "ptr" "Smake_bytevector" "(iptr, int)") - (export "ptr" "Smake_string" "(iptr, int)") - (export "ptr" "Smake_uninitialized_string" "(iptr)") - (export "ptr" "Sstring" "(const char *)") - (export "ptr" "Sstring_of_length" "(const char *, iptr)") - (export "ptr" "Sstring_utf8" "(const char*, iptr)") - (export "ptr" "Sbox" "(ptr)") - (export "ptr" "Sinteger" "(iptr)") - (export "ptr" "Sunsigned" "(uptr)") - (export "ptr" "Sinteger32" (format "(~a)" (constant typedef-i32))) - (export "ptr" "Sunsigned32" (format "(~a)" (constant typedef-u32))) - (export "ptr" "Sinteger64" (format "(~a)" (constant typedef-i64))) - (export "ptr" "Sunsigned64" (format "(~a)" (constant typedef-u64))) - - (nl) (comment "Miscellaneous") - (export "ptr" "Stop_level_value" "(ptr)") - (export "void" "Sset_top_level_value" "(ptr, ptr)") - (export "void" "Slock_object" "(ptr)") - (export "void" "Sunlock_object" "(ptr)") - (export "int" "Slocked_objectp" "(ptr)") - (export "void" "Sforeign_symbol" "(const char *, void *)") - (export "void" "Sregister_symbol" "(const char *, void *)") - - (nl) (comment "Support for calls into Scheme") - (export "ptr" "Scall0" "(ptr)") - (export "ptr" "Scall1" "(ptr, ptr)") - (export "ptr" "Scall2" "(ptr, ptr, ptr)") - (export "ptr" "Scall3" "(ptr, ptr, ptr, ptr)") - (export "void" "Sinitframe" "(iptr)") - (export "void" "Sput_arg" "(iptr, ptr)") - (export "ptr" "Scall" "(ptr, iptr)") - (comment "Warning: Sforeign_callable_entry_point(x) returns a pointer into x.") - (def "Sforeign_callable_entry_point(x)" - (&ref "(void (*)(void))" "x" ($ code-data-disp))) - (def "Sforeign_callable_code_object(x)" - (&ref "(ptr)" "x" (- ($ code-data-disp)))) - - (nl) (comment "Customization support.") - (export "const char *" "Skernel_version" "(void)") - (export "void" "Sretain_static_relocation" "(void)") - (export "void" "Sset_verbose" "(int)") - (export "void" "Sscheme_init" "(void (*)(void))") - (export "void" "Sregister_boot_file" "(const char *)") - (export "void" "Sregister_boot_file_fd" "(const char *, int fd)") - (export "void" "Sregister_heap_file" "(const char *)") - (export "void" "Scompact_heap" "(void)") - (export "void" "Ssave_heap" "(const char *, int)") - (export "void" "Sbuild_heap" "(const char *, void (*)(void))") - (export "void" "Senable_expeditor" "(const char *)") - (export "int" "Sscheme_start" "(int, const char *[])") - (export "int" "Sscheme_script" "(const char *, int, const char *[])") - (export "int" "Sscheme_program" "(const char *, int, const char *[])") - (export "void" "Sscheme_deinit" "(void)") - - (when-feature pthreads - (nl) (comment "Thread support.") - (export "int" "Sactivate_thread" "(void)") - (export "void" "Sdeactivate_thread" "(void)") - (export "int" "Sdestroy_thread" "(void)") - ) - - (when-feature windows - (nl) (comment "Windows support.") - (pr "#include ~%") - (export "char *" "Sgetenv" "(const char *)") - (export "wchar_t *" "Sutf8_to_wide" "(const char *)") - (export "char *" "Swide_to_utf8" "(const wchar_t *)") - ) - - (nl) (comment "Features.") - (for-each - (lambda (x) (pr "#define FEATURE_~@:(~a~)~%" (sanitize x))) - (feature-list)) - - (nl) (comment "Locking macros.") - (constant-case architecture - [(x86) - (if-feature windows - ;; Using compiler intrinsics on 32-bit Windows because the inline - ;; assembler does not support anonymous labels, and using named - ;; labels leads to label name conflicts if SPINLOCK is used more - ;; than once in the same C procedure. - (begin - (pr "#define INITLOCK(addr) (*((long *) addr) = 0)~%") - - (nl) - (pr "#define SPINLOCK(addr) \\~%") - (pr "{ \\~%") - (pr " while (_InterlockedExchange(addr, 1) != 0) { \\~%") - (pr " while(*((long *) addr) != 0); \\~%") - (pr " } \\~%") - (pr "} while(0) ~%") - - (nl) - (pr "#define UNLOCK(addr) (*((long *) addr) = 0)~%") - - (nl) - (pr "#define LOCKED_INCR(addr, res) (res = (-1 == _InterlockedExchangeAdd(addr, 1)))~%") - - (nl) - (pr "#define LOCKED_DECR(addr, res) (res = (1 == _InterlockedExchangeAdd(addr, -1)))~%")) - (begin - (pr "#define INITLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"movl $0, (%0)\"\\~%") - (pr " : \\~%") - (pr " : \"r\" (addr) \\~%") - (pr " : \"memory\")~%") - - (nl) - (pr "#define SPINLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"0:\\n\\t\"\\~%") - (pr " \"movl $1, %%eax\\n\\t\"\\~%") - (pr " \"xchgl (%0), %%eax\\n\\t\"\\~%") - (pr " \"cmpl $0, %%eax\\n\\t\"\\~%") - (pr " \"je 2f\\n\\t\"\\~%") - (pr " \"1:\\n\\t\"\\~%") - (pr " \"pause\\n\\t\"\\~%") - (pr " \"cmpl $0, (%0)\\n\\t\"\\~%") - (pr " \"je 0b\\n\\t\"\\~%") - (pr " \"jmp 1b\\n\\t\"\\~%") - (pr " \"2:\"\\~%") - (pr " : \\~%") - (pr " : \"r\" (addr) \\~%") - (pr " : \"eax\", \"flags\", \"memory\")~%") - - (nl) - (pr "#define UNLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"movl $0, (%0)\"\\~%") - (pr " : \\~%") - (pr " : \"r\" (addr) \\~%") - (pr " : \"memory\")~%") - - (nl) - (pr "#define LOCKED_INCR(addr, ret) \\~%") - (pr " __asm__ __volatile__ (\"lock; incl (%1)\\n\\t\"\\~%") - (pr " \"sete %b0\\n\\t\"\\~%") - (pr " \"movzx %b0, %0\\n\\t\"\\~%") - (pr " : \"=q\" (ret) \\~%") - (pr " : \"r\" (addr) \\~%") - (pr " : \"flags\", \"memory\")~%") - - (nl) - (pr "#define LOCKED_DECR(addr, ret) \\~%") - (pr " __asm__ __volatile__ (\"lock; decl (%1)\\n\\t\"\\~%") - (pr " \"sete %b0\\n\\t\"\\~%") - (pr " \"movzx %b0, %0\\n\\t\"\\~%") - (pr " : \"=q\" (ret) \\~%") - (pr " : \"r\" (addr) \\~%") - (pr " : \"flags\", \"memory\")~%")))] - [(x86_64) - (if-feature windows - ;; Visual C for 64-bit Windows does not support inline assembler, so we are using - ;; intrinsics here instead. At /O2, VC seems to produced assembly - ;; code similar to our hand-code assembler. - ;; Note that using the Acquire or Release version of these functions (or the - ;; equivalent _acq or _rel versions of the intrinsics) produces calls to the - ;; intrinsic rather than the inlined assembly produced by the intrinsics used here, - ;; despite the documentation indicating the Acquire and Release vesions produce - ;; better performing code. - (begin - (pr "#define INITLOCK(addr) (*((long long *) addr) = 0)~%") - - (nl) - (pr "#define SPINLOCK(addr) \\~%") - (pr "{ \\~%") - (pr " while (_InterlockedExchange64(addr, 1) != 0) { \\~%") - (pr " while(*((long long *) addr) != 0); \\~%") - (pr " } \\~%") - (pr "} while(0) ~%") - - (nl) - (pr "#define UNLOCK(addr) (*((long long *) addr) = 0)~%") - - (nl) - (pr "#define LOCKED_INCR(addr, res) (res = (-1 == _InterlockedExchangeAdd64(addr, 1)))~%") - - (nl) - (pr "#define LOCKED_DECR(addr, res) (res = (1 == _InterlockedExchangeAdd64(addr, -1)))~%")) - (begin - (pr "#define INITLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"movq $0, (%0)\"\\~%") - (pr " : \\~%") - (pr " : \"r\" (addr) \\~%") - (pr " : \"memory\")~%") - - (nl) - (pr "#define SPINLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"0:\\n\\t\"\\~%") - (pr " \"movq $1, %%rax\\n\\t\"\\~%") - (pr " \"xchgq (%0), %%rax\\n\\t\"\\~%") - (pr " \"cmpq $0, %%rax\\n\\t\"\\~%") - (pr " \"je 2f\\n\\t\"\\~%") - (pr " \"1:\\n\\t\"\\~%") - (pr " \"pause\\n\\t\"\\~%") - (pr " \"cmpq $0, (%0)\\n\\t\"\\~%") - (pr " \"je 0b\\n\\t\"\\~%") - (pr " \"jmp 1b\\n\\t\"\\~%") - (pr " \"2:\"\\~%") - (pr " : \\~%") - (pr " : \"r\" (addr) \\~%") - (pr " : \"rax\", \"flags\", \"memory\")~%") - - (nl) - (pr "#define UNLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"movq $0, (%0)\"\\~%") - (pr " : \\~%") - (pr " : \"r\" (addr) \\~%") - (pr " :\"memory\")~%") - - (nl) - (pr "#define LOCKED_INCR(addr, ret) \\~%") - (pr " __asm__ __volatile__ (\"lock; incq (%1)\\n\\t\"\\~%") - (pr " \"sete %b0\\n\\t\"\\~%") - (pr " \"movzx %b0, %0\\n\\t\"\\~%") - (pr " : \"=q\" (ret) \\~%") - (pr " : \"r\" (addr) \\~%") - (pr " : \"flags\", \"memory\")~%") - - (nl) - (pr "#define LOCKED_DECR(addr, ret) \\~%") - (pr " __asm__ __volatile__ (\"lock; decq (%1)\\n\\t\"\\~%") - (pr " \"sete %b0\\n\\t\"\\~%") - (pr " \"movzx %b0, %0\\n\\t\"\\~%") - (pr " : \"=q\" (ret) \\~%") - (pr " : \"r\" (addr) \\~%") - (pr " : \"flags\", \"memory\")~%")))] - [(ppc32) - (pr "#define INITLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"li %%r0, 0\\n\\t\"\\~%") - (pr " \"stw %%r0, 0(%0)\\n\\t\"\\~%") - (pr " : \\~%") - (pr " : \"b\" (addr)\\~%") - (pr " :\"memory\", \"r0\")~%") - - (nl) - (pr "#define SPINLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"0:\\n\\t\"\\~%") ; top: - (pr " \"lwarx %%r0, 0, %0\\n\\t\"\\~%") ; start lock acquisition - (pr " \"cmpwi %%r0, 0\\n\\t\"\\~%") ; see if someone already owns the lock - (pr " \"bne 1f\\n\\t\"\\~%") ; if so, go to our try_again loop - (pr " \"li %%r0, 1\\n\\t\"\\~%") ; attempt to store the value 1 - (pr " \"stwcx. %%r0, 0, %0\\n\\t\"\\~%") ; - (pr " \"beq 2f\\n\\t\"\\~%") ; if we succeed, we own the lock - (pr " \"1:\\n\\t\"\\~%") ; again: - (pr " \"isync\\n\\t\"\\~%") ; sync things to pause the processor - (pr " \"lwz %%r0, 0(%0)\\n\\t\"\\~%") ; try a non-reserved load to see if we are likely to succeed - (pr " \"cmpwi %%r0, 0\\n\\t\"\\~%") ; if it is = 0, try to acquire at start - (pr " \"beq 0b\\n\\t\"\\~%") ; - (pr " \"b 1b\\n\\t\"\\~%") ; otherwise loop through the try again - (pr " \"2:\\n\\t\"\\~%") ; done: - (pr " : \\~%") - (pr " : \"b\" (addr)\\~%") - (pr " : \"cc\", \"memory\", \"r0\")~%") - - (nl) - (pr "#define UNLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"li %%r0, 0\\n\\t\"\\~%") - (pr " \"stw %%r0, 0(%0)\\n\\t\"\\~%") - (pr " : \\~%") - (pr " : \"b\" (addr)\\~%") - (pr " :\"memory\", \"r0\")~%") - - (nl) - (pr "#define LOCKED_INCR(addr, ret) \\~%") - (pr " __asm__ __volatile__ (\"li %0, 0\\n\\t\"\\~%") - (pr " \"0:\\n\\t\"\\~%") - (pr " \"lwarx %%r12, 0, %1\\n\\t\"\\~%") - (pr " \"addi %%r12, %%r12, 1\\n\\t\"\\~%") - (pr " \"stwcx. %%r12, 0, %1\\n\\t\"\\~%") - (pr " \"bne 0b\\n\\t\"\\~%") - (pr " \"cmpwi %%r12, 0\\n\\t\"\\~%") - (pr " \"bne 1f\\n\\t\"\\~%") - (pr " \"li %0, 1\\n\\t\"\\~%") - (pr " \"1:\\n\\t\"\\~%") - (pr " : \"=&r\" (ret)\\~%") - (pr " : \"r\" (addr)\\~%") - (pr " : \"cc\", \"memory\", \"r12\")~%") - - (nl) - (pr "#define LOCKED_DECR(addr, ret) \\~%") - (pr " __asm__ __volatile__ (\"li %0, 0\\n\\t\"\\~%") - (pr " \"0:\\n\\t\"\\~%") - (pr " \"lwarx %%r12, 0, %1\\n\\t\"\\~%") - (pr " \"addi %%r12, %%r12, -1\\n\\t\"\\~%") - (pr " \"stwcx. %%r12, 0, %1\\n\\t\"\\~%") - (pr " \"bne 0b\\n\\t\"\\~%") - (pr " \"cmpwi %%r12, 0\\n\\t\"\\~%") - (pr " \"bne 1f\\n\\t\"\\~%") - (pr " \"li %0, 1\\n\\t\"\\~%") - (pr " \"1:\\n\\t\"\\~%") - (pr " : \"=&r\" (ret)\\~%") - (pr " : \"r\" (addr)\\~%") - (pr " : \"cc\", \"memory\", \"r12\")~%")] - [(arm32) - (pr "#define INITLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"mov r12, #0\\n\\t\"\\~%") - (pr " \"str r12, [%0, #0]\\n\\t\"\\~%") - (pr " : \\~%") - (pr " : \"r\" (addr)\\~%") - (pr " :\"memory\", \"r12\")~%") - - (nl) - (pr "#define SPINLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"0:\\n\\t\"\\~%") - (pr " \"ldrex r12, [%0, #0]\\n\\t\"\\~%") - (pr " \"cmp r12, #0\\n\\t\"\\~%") - (pr " \"bne 1f\\n\\t\"\\~%") - (pr " \"mov r12, #1\\n\\t\"\\~%") - (pr " \"strex r11, r12, [%0]\\n\\t\"\\~%") - (pr " \"cmp r11, #0\\n\\t\"\\~%") - (pr " \"beq 2f\\n\\t\"\\~%") - (pr " \"1:\\n\\t\"\\~%") - (pr " \"ldr r12, [%0, #0]\\n\\t\"\\~%") - (pr " \"cmp r12, #0\\n\\t\"\\~%") - (pr " \"beq 0b\\n\\t\"\\~%") - (pr " \"b 1b\\n\\t\"\\~%") - (pr " \"2:\\n\\t\"\\~%") - (pr " : \\~%") - (pr " : \"r\" (addr)\\~%") - (pr " : \"cc\", \"memory\", \"r12\", \"r11\")~%") - - (nl) - (pr "#define UNLOCK(addr) \\~%") - (pr " __asm__ __volatile__ (\"mov r12, #0\\n\\t\"\\~%") - (pr " \"str r12, [%0, #0]\\n\\t\"\\~%") - (pr " : \\~%") - (pr " : \"r\" (addr)\\~%") - (pr " :\"memory\", \"r12\")~%") - - (nl) - (pr "#define LOCKED_INCR(addr, ret) \\~%") - (pr " __asm__ __volatile__ (\"mov %0, #0\\n\\t\"\\~%") - (pr " \"0:\\n\\t\"\\~%") - (pr " \"ldrex r12, [%1, #0]\\n\\t\"\\~%") - (pr " \"add r12, r12, #1\\n\\t\"\\~%") - (pr " \"strex r11, r12, [%1]\\n\\t\"\\~%") - (pr " \"cmp r11, #0\\n\\t\"\\~%") - (pr " \"bne 0b\\n\\t\"\\~%") - (pr " \"cmp r12, #0\\n\\t\"\\~%") - (pr " \"moveq %0, #1\\n\\t\"\\~%") - (pr " : \"=&r\" (ret)\\~%") - (pr " : \"r\" (addr)\\~%") - (pr " : \"cc\", \"memory\", \"r12\", \"r11\")~%") - - (nl) - (pr "#define LOCKED_DECR(addr, ret) \\~%") - (pr " __asm__ __volatile__ (\"mov %0, #0\\n\\t\"\\~%") - (pr " \"0:\\n\\t\"\\~%") - (pr " \"ldrex r12, [%1, #0]\\n\\t\"\\~%") - (pr " \"sub r12, r12, #1\\n\\t\"\\~%") - (pr " \"strex r11, r12, [%1]\\n\\t\"\\~%") - (pr " \"cmp r11, #0\\n\\t\"\\~%") - (pr " \"bne 0b\\n\\t\"\\~%") - (pr " \"cmp r12, #0\\n\\t\"\\~%") - (pr " \"moveq %0, #1\\n\\t\"\\~%") - (pr " : \"=&r\" (ret)\\~%") - (pr " : \"r\" (addr)\\~%") - (pr " : \"cc\", \"memory\", \"r12\", \"r11\")~%")] - [else - ($oops who "asm locking code is not yet defined for ~s" (constant architecture))])))) - - (set! mkequates.h - (lambda (ofn) - (fluid-let ([op (open-output-file ofn 'replace)]) - (comment "equates.h for Chez Scheme Version ~a" scheme-version) - - (nl) - (comment "Do not edit this file. It is automatically generated and") - (comment "specifically tailored to the version of Chez Scheme named") - (comment "above. Always be certain that you have the correct version") - (comment "of this file for the version of Chez Scheme you are using.") - - (nl) - (comment "Warning: Some macros may evaluate arguments more than once.") - - (nl) - (comment "Integer typedefs") - (pr "typedef ~a I8;~%" (constant typedef-i8)) - (pr "typedef ~a U8;~%" (constant typedef-u8)) - (pr "typedef ~a I16;~%" (constant typedef-i16)) - (pr "typedef ~a U16;~%" (constant typedef-u16)) - (pr "typedef ~a I32;~%" (constant typedef-i32)) - (pr "typedef ~a U32;~%" (constant typedef-u32)) - (pr "typedef ~a I64;~%" (constant typedef-i64)) - (pr "typedef ~a U64;~%" (constant typedef-u64)) - - (nl) - (comment "constants from cmacros.ss") - (for-each - (lambda (x) - (cond - [(getprop x '*constant* #f) => - (lambda (k) - (let ([type (getprop x '*constant-ctype* #f)]) - (def (sanitize x) - (if (or (fixnum? k) (bignum? k)) - (if (< k 0) - (if (or (not type) (eq? type 'int)) - (format "-0x~x" (- k)) - (format "(~s)-0x~x" type (- k))) - (if (or (not type) (eq? type 'int)) - (format "0x~x" k) - (format "(~s)0x~x" type k))) - (if (not type) - (if (eq? k #f) - "0" - (if (eq? k #t) - "1" - (format "~s" k))) - (format "(~s)~s" type k))))))])) - (sort (lambda (x y) - (stringstring x) (symbol->string y))) - (oblist))) - (nl) - (comment "constants from declare-c-entries") - (for-each - (lambda (x) - (cond - [($sgetprop x '*c-entry* #f) => - (lambda (k) - (def (format "CENTRY_~a" (sanitize x)) k))])) - (sort (lambda (x y) - (stringstring x) (symbol->string y))) - (oblist))) - - (nl) - (comment "displacements for records") - (let () - (define print-field-disps - (lambda (prefix rtd) - (let-values ([(pm mpm flds size) - ((let () (include "layout.ss") compute-field-offsets) - 'mkheader - (fx- (constant typemod) (constant type-typed-object)) - (cons '(immutable scheme-object rtd) (csv7:record-type-field-decls rtd)))]) - (for-each - (lambda (fld) - (def (format "~a_~a_disp" prefix (sanitize (fld-name fld))) - (fld-byte fld))) - flds)))) - (print-field-disps "eq_hashtable" (let () (include "hashtable-types.ss") (record-type-descriptor eq-ht))) - (print-field-disps "symbol_hashtable" (let () (include "hashtable-types.ss") (record-type-descriptor symbol-ht))) - (print-field-disps "code_info" (let () (include "types.ss") (record-type-descriptor code-info)))) - - (nl) - (comment "predicates") - (deftypep "Simmediatep" ($ mask-immediate) ($ type-immediate)) - (deftotypep "Sportp" ($ mask-port) ($ type-port)) - (deftotypep "Scodep" ($ mask-code) ($ type-code)) - - (nl) - (comment "structure accessors") - - (definit INITCAR pair car) - (definit INITCDR pair cdr) - (defset SETCAR pair car) - (defset SETCDR pair cdr) - - (defref BOXTYPE box type) - (definit INITBOXREF box ref) - (defset SETBOXREF box ref) - - (defref EPHEMERONNEXT ephemeron next) - (definit INITEPHEMERONNEXT ephemeron next) - (defref EPHEMERONTRIGGERNEXT ephemeron trigger-next) - (definit INITEPHEMERONTRIGGERNEXT ephemeron trigger-next) - - (defref TLCTYPE tlc type) - (defref TLCKEYVAL tlc keyval) - (defref TLCHT tlc ht) - (defref TLCNEXT tlc next) - (definit INITTLCKEYVAL tlc keyval) - (definit INITTLCHT tlc ht) - (definit INITTLCNEXT tlc next) - (defset SETTLCNEXT tlc next) - - (defref SYMVAL symbol value) - (defref SYMPVAL symbol pvalue) - (defref SYMPLIST symbol plist) - (defref SYMNAME symbol name) - (defref SYMSPLIST symbol splist) - (defref SYMHASH symbol hash) - - (definit INITSYMVAL symbol value) - (definit INITSYMPVAL symbol pvalue) - (definit INITSYMPLIST symbol plist) - (definit INITSYMNAME symbol name) - (definit INITSYMSPLIST symbol splist) - (definit INITSYMHASH symbol hash) - - (defset SETSYMVAL symbol value) - (defset SETSYMPVAL symbol pvalue) - (defset SETSYMPLIST symbol plist) - (defset SETSYMNAME symbol name) - (defset SETSYMSPLIST symbol splist) - (defset SETSYMHASH symbol hash) - - (defref VECTTYPE vector type) - - (definit INITVECTIT vector data) - (defset SETVECTIT vector data) - - (defref FXVECTOR_TYPE fxvector type) - (defref FXVECTIT fxvector data) - - (defref BYTEVECTOR_TYPE bytevector type) - (defref BVIT bytevector data) - - (defref INEXACTNUM_TYPE inexactnum type) - (defref INEXACTNUM_REAL_PART inexactnum real) - (defref INEXACTNUM_IMAG_PART inexactnum imag) - - (defref EXACTNUM_TYPE exactnum type) - (defref EXACTNUM_REAL_PART exactnum real) - (defref EXACTNUM_IMAG_PART exactnum imag) - - (defref RATTYPE ratnum type) - (defref RATNUM ratnum numerator) - (defref RATDEN ratnum denominator) - - (defref CLOSENTRY closure code) - (defref CLOSIT closure data) - - (defref FLODAT flonum data) - - (defref PORTTYPE port type) - (defref PORTNAME port name) - (defref PORTHANDLER port handler) - (defref PORTINFO port info) - (defref PORTOCNT port ocount) - (defref PORTOLAST port olast) - (defref PORTOBUF port obuffer) - (defref PORTICNT port icount) - (defref PORTILAST port ilast) - (defref PORTIBUF port ibuffer) - - (defref STRTYPE string type) - (defref STRIT string data) - - (defref BIGTYPE bignum type) - (defref BIGIT bignum data) - - (defref CODETYPE code type) - (defref CODELEN code length) - (defref CODERELOC code reloc) - (defref CODENAME code name) - (defref CODEARITYMASK code arity-mask) - (defref CODEFREE code closure-length) - (defref CODEINFO code info) - (defref CODEPINFOS code pinfo*) - (defref CODEIT code data) - - (defref RELOCSIZE reloc-table size) - (defref RELOCCODE reloc-table code) - (defref RELOCIT reloc-table data) - - (defref CONTSTACK continuation stack) - (defref CONTLENGTH continuation stack-length) - (defref CONTCLENGTH continuation stack-clength) - (defref CONTLINK continuation link) - (defref CONTRET continuation return-address) - (defref CONTWINDERS continuation winders) - - (defref RTDCOUNTSTYPE rtd-counts type) - (defref RTDCOUNTSTIMESTAMP rtd-counts timestamp) - (defref RTDCOUNTSIT rtd-counts data) - - (defref RECORDDESCPARENT record-type parent) - (defref RECORDDESCSIZE record-type size) - (defref RECORDDESCPM record-type pm) - (defref RECORDDESCMPM record-type mpm) - (defref RECORDDESCNAME record-type name) - (defref RECORDDESCFLDS record-type flds) - (defref RECORDDESCFLAGS record-type flags) - (defref RECORDDESCUID record-type uid) - (defref RECORDDESCCOUNTS record-type counts) - - (defref RECORDINSTTYPE record type) - (defref RECORDINSTIT record data) - - ; derived accessors - (def "CLOSCODE(p)" "((ptr)((uptr)CLOSENTRY(p)-code_data_disp))") - (def "CODEENTRYPOINT(x)" "((ptr)((uptr)(x)+code_data_disp))") - (def "SETCLOSCODE(p,x)" "(CLOSENTRY(p) = CODEENTRYPOINT(x))") - - (def "SYMCODE(p)" "((ptr)((uptr)SYMPVAL(p)-code_data_disp))") - (def "INITSYMCODE(p,x)" "(INITSYMPVAL(p) = CODEENTRYPOINT(x))") - (def "SETSYMCODE(p,x)" "SETSYMPVAL(p,CODEENTRYPOINT(x))") - - (def "BIGLEN(x)" "((iptr)((uptr)BIGTYPE(x) >> bignum_length_offset))") - (def "BIGSIGN(x)" "((BIGTYPE(x) & mask_bignum_sign) >> bignum_sign_offset)") - (def "SETBIGLENANDSIGN(x,xl,xs)" - "BIGTYPE(x) = (uptr)(xl) << bignum_length_offset | (xs) << bignum_sign_offset | type_bignum") - - (def "CLOSLEN(p)" "CODEFREE(CLOSCODE(p))") - - (defref GUARDIANOBJ guardian-entry obj) - (defref GUARDIANREP guardian-entry rep) - (defref GUARDIANTCONC guardian-entry tconc) - (defref GUARDIANNEXT guardian-entry next) - - (definit INITGUARDIANOBJ guardian-entry obj) - (definit INITGUARDIANREP guardian-entry rep) - (definit INITGUARDIANTCONC guardian-entry tconc) - (definit INITGUARDIANNEXT guardian-entry next) - - (defref FORWARDMARKER forward marker) - (defref FORWARDADDRESS forward address) - - (defref CACHEDSTACKSIZE cached-stack size) - (defref CACHEDSTACKLINK cached-stack link) - - (defref RPHEADERFRAMESIZE rp-header frame-size) - (defref RPHEADERLIVEMASK rp-header livemask) - (defref RPHEADERTOPLINK rp-header toplink) - - (nl) - (comment "machine types") - (pr "#define machine_type_names ") - (pr "{~{\"~a\"~^, ~}}~%" - (let ([v (make-vector (constant machine-type-limit) 'undefined)]) - (for-each (lambda (a) (vector-set! v (car a) (cdr a))) (constant machine-type-alist)) - (vector->list v))) - - (nl) - (comment "allocation-space names") - (pr "#define alloc_space_names ") - (pr "~{\"~a\"~^, ~}~%" (constant space-cname-list)) - - (nl) - (comment "allocation-space characters") - (pr "#define alloc_space_chars ") - (pr "~{\'~a\'~^, ~}~%" (constant space-char-list)) - - (nl) - (comment "threads") - (defref THREADTC thread tc) - - (nl) - (comment "thread-context data") - (let () - (define-syntax alpha - (let () - (define CSAFE - (lambda (sym) - (string->symbol - (list->string - (map char-upcase - (remv #\- (string->list (symbol->string sym)))))))) - (let ([tc-field-list (sort - (lambda (x y) - (stringstring x) (symbol->string y))) - tc-field-list)]) - (with-syntax ([(param ...) - (map (lambda (x) (datum->syntax #'* x)) - tc-field-list)] - [(PARAM ...) - (map (lambda (x) (datum->syntax #'* x)) - (map CSAFE tc-field-list))]) - (lambda (x) - #'(begin (defref PARAM tc param) ...)))))) - alpha) - - ; get ARGREGS for free from above; prefer ARGREG - (defref ARGREG tc arg-regs) - (defref VIRTREG tc virtual-registers) - - (nl) - (comment "library entries we access from C code") - (def "library_nonprocedure_code" - (libspec-index (lookup-libspec nonprocedure-code))) - (def "library_dounderflow" - (libspec-index (lookup-libspec dounderflow))) - - ))) -) diff --git a/ta6ob/s/nanopass.so b/ta6ob/s/nanopass.so deleted file mode 100644 index d75c629..0000000 Binary files a/ta6ob/s/nanopass.so and /dev/null differ diff --git a/ta6ob/s/nanopass/helpers.so b/ta6ob/s/nanopass/helpers.so deleted file mode 100644 index cf048e4..0000000 Binary files a/ta6ob/s/nanopass/helpers.so and /dev/null differ diff --git a/ta6ob/s/nanopass/implementation-helpers.chezscheme.so b/ta6ob/s/nanopass/implementation-helpers.chezscheme.so deleted file mode 100644 index 63b691b..0000000 Binary files a/ta6ob/s/nanopass/implementation-helpers.chezscheme.so and /dev/null differ diff --git a/ta6ob/s/nanopass/language-helpers.so b/ta6ob/s/nanopass/language-helpers.so deleted file mode 100644 index ecd12d1..0000000 Binary files a/ta6ob/s/nanopass/language-helpers.so and /dev/null differ diff --git a/ta6ob/s/nanopass/language-node-counter.so b/ta6ob/s/nanopass/language-node-counter.so deleted file mode 100644 index 0e617f7..0000000 Binary files a/ta6ob/s/nanopass/language-node-counter.so and /dev/null differ diff --git a/ta6ob/s/nanopass/language.so b/ta6ob/s/nanopass/language.so deleted file mode 100644 index a8320fe..0000000 Binary files a/ta6ob/s/nanopass/language.so and /dev/null differ diff --git a/ta6ob/s/nanopass/meta-parser.so b/ta6ob/s/nanopass/meta-parser.so deleted file mode 100644 index 3a489c3..0000000 Binary files a/ta6ob/s/nanopass/meta-parser.so and /dev/null differ diff --git a/ta6ob/s/nanopass/meta-syntax-dispatch.so b/ta6ob/s/nanopass/meta-syntax-dispatch.so deleted file mode 100644 index db67373..0000000 Binary files a/ta6ob/s/nanopass/meta-syntax-dispatch.so and /dev/null differ diff --git a/ta6ob/s/nanopass/nano-syntax-dispatch.so b/ta6ob/s/nanopass/nano-syntax-dispatch.so deleted file mode 100644 index 9c41ee1..0000000 Binary files a/ta6ob/s/nanopass/nano-syntax-dispatch.so and /dev/null differ diff --git a/ta6ob/s/nanopass/parser.so b/ta6ob/s/nanopass/parser.so deleted file mode 100644 index bcf2e84..0000000 Binary files a/ta6ob/s/nanopass/parser.so and /dev/null differ diff --git a/ta6ob/s/nanopass/pass.so b/ta6ob/s/nanopass/pass.so deleted file mode 100644 index 26df5db..0000000 Binary files a/ta6ob/s/nanopass/pass.so and /dev/null differ diff --git a/ta6ob/s/nanopass/records.so b/ta6ob/s/nanopass/records.so deleted file mode 100644 index 53df66c..0000000 Binary files a/ta6ob/s/nanopass/records.so and /dev/null differ diff --git a/ta6ob/s/nanopass/syntaxconvert.so b/ta6ob/s/nanopass/syntaxconvert.so deleted file mode 100644 index 56f07cf..0000000 Binary files a/ta6ob/s/nanopass/syntaxconvert.so and /dev/null differ diff --git a/ta6ob/s/nanopass/unparser.so b/ta6ob/s/nanopass/unparser.so deleted file mode 100644 index b8008f0..0000000 Binary files a/ta6ob/s/nanopass/unparser.so and /dev/null differ diff --git a/ta6ob/s/newhash.ss b/ta6ob/s/newhash.ss deleted file mode 100644 index 227050b..0000000 --- a/ta6ob/s/newhash.ss +++ /dev/null @@ -1,1257 +0,0 @@ -;;; newhash.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -#| -Documentation notes: -- hashtable-copy can create immutable weak eq hashtables. an immutable weak - hashtable is immutable in the sense that it cannot be modified by - hashtable-set! or hashtable-update!, but the disappearance of key, val - pairs can be detected with hashtable-size, hashtable-keys, and - hashtable-entries. -- symbols are collectable, so weak hash tables should not be used to create - permanent associations with symbols as keys -|# - -#| -; csv7: -(define make-hash-table) ; weakflag -(define hash-table?) ; x -(define put-hash-table!) ; hashtable key obj -(define get-hash-table) ; hashtable key default -(define remove-hash-table!) ; hashtable key -(define hash-table-map) ; hashtable proc -(define hash-table-for-each) ; hashtable proc - -;;; r6rs: -(define make-eq-hashtable) ; [k], k >= 0 -(define make-eqv-hashtable) ; [k], k >= 0 -(define make-hashtable) ; hashproc equivproc [k], k >= 0 -(define hashtable?) ; x -(define hashtable-size) ; hashtable -(define hashtable-ref) ; hashtable key default -(define hashtable-set!) ; hashtable key obj -(define hashtable-delete!) ; hashtable key -(define hashtable-contains?) ; hashtable key -(define hashtable-update!) ; hashtable key proc default -(define hashtable-copy) ; hashtable [mutableflag] -(define hashtable-clear!) ; hashtable [k], k >= 0 -(define hashtable-keys) ; hashtable -(define hashtable-entries) ; hashtable -(define hashtable-cells) ; hashtable -(define hashtable-equivalence-function) ; hashtable -(define hashtable-hash-function) ; hashtable -(define hashtable-mutable?) ; hashtable -(define equal-hash) ; obj -(define string-hash) ; string -(define string-ci-hash) ; string -(define symbol-hash) ; symbol - -;;; other generic hash operators -(define hashtable-cell) -(define hashtable-weak?) ; hashtable -(define hashtable-ephemeron?) ; hashtable - -;;; eq-hashtable operators -(define make-weak-eq-hashtable) ; [k], k >= 0 -(define eq-hashtable-ref) ; eq-hashtable key default -(define eq-hashtable-contains?) ; eq-hashtable key -(define eq-hashtable-set!) ; eq-hashtable key obj -(define eq-hashtable-update!) ; eq-hashtable key proc default -(define eq-hashtable-cell) ; eq-hashtable key default -(define eq-hashtable-delete!) ; eq-hashtable key -(define eq-hashtable-weak?) ; eq-hashtable -(define eq-hashtable-ephemeron?) ; eq-hashtable - -;;; eq-hashtable operators -(define make-symbol-hashtable) ; [k], k >= 0 -(define symbol-hashtable-ref) ; symbol-hashtable key default -(define symbol-hashtable-contains?) ; symbol-hashtable key -(define symbol-hashtable-set!) ; symbol-hashtable key obj -(define symbol-hashtable-update!) ; symbol-hashtable key proc default -(define symbol-hashtable-cell) ; symbol-hashtable key default -(define symbol-hashtable-delete!) ; symbol-hashtable key - -;;; eqv-hashtable operators -(define make-weak-eqv-hashtable) ; [k], k >= 0 - -;;; unsafe eq-hashtable operators -(define $make-eq-hashtable) ; fxminlen subtype, fxminlen = 2^n, n >= 0 -(define $eq-hashtable-keys) ; eq-hashtable -(define $eq-hashtable-values) ; eq-hashtable -(define $eq-hashtable-entries) ; eq-hashtable -(define $eq-hashtable-cells) ; eq-hashtable -(define $eq-hashtable-copy) ; eq-hashtable [mutableflag] -(define $eq-hashtable-clear!) ; eq-hashtable [fxminlen] - -;;; inspection -(define $hashtable-veclen) -(define $hashtable-report) -|# - -(let () - (include "hashtable-types.ss") - - (define do-hash - (lambda (hash x mask who) - ; NB: the hash function should return a nonnegative exact integer. - ; NB: we check only that it returns an exact integer, i.e., extend the semantics to - ; NB: allow negative exact integers. - (let ([i (hash x)]) - (cond - [(fixnum? i) (fxlogand i mask)] - [(bignum? i) (logand i mask)] - [else ($oops who "invalid hash-function ~s return value ~s for ~s" hash i x)])))) - - (define size->minlen - (lambda (who k) - (define maxbits (fx- (fixnum-width) 4)) - (cond - [(and (fixnum? k) (fx>= k 0)) - (fxmax 8 (fxsll 1 (fxmin maxbits (fxlength (fx- k 1)))))] - [(and (bignum? k) (>= k 0)) (fxsll 1 maxbits)] - [else ($oops who "invalid size argument ~s" k)]))) - - (define $gen-hashtable-ref - (lambda (h x v who) - (let ([vec (ht-vec h)] [equiv? (gen-ht-equiv? h)]) - (let loop ([b (vector-ref vec (do-hash (gen-ht-hash h) x (fx- (vector-length vec) 1) who))]) - (if (null? b) - v - (let ([a (car b)]) - (if (equiv? (car a) x) (cdr a) (loop (cdr b))))))))) - - (define $gen-hashtable-contains? - (lambda (h x who) - (let ([vec (ht-vec h)] [equiv? (gen-ht-equiv? h)]) - (let loop ([b (vector-ref vec (do-hash (gen-ht-hash h) x (fx- (vector-length vec) 1) who))]) - (and (not (null? b)) - (or (equiv? (caar b) x) - (loop (cdr b)))))))) - - (module ($gen-hashtable-set! $gen-hashtable-update! $gen-hashtable-cell $gen-hashtable-delete!) - (define-syntax incr-size! - (syntax-rules () - [(_ h vec who) - (let ([size (fx+ (ht-size h) 1)] [n (vector-length vec)]) - (ht-size-set! h size) - (when (and (fx> size n) (fx< n (fxsrl (most-positive-fixnum) 1))) - (adjust! h vec (fxsll n 1) who)))])) - - (define-syntax decr-size! - (syntax-rules () - [(_ h vec who) - (let ([size (fx- (ht-size h) 1)] [n (vector-length vec)]) - (ht-size-set! h size) - (when (and (fx< size (fxsrl n 2)) (fx> n (ht-minlen h))) - (adjust! h vec (fxsrl n 1) who)))])) - - (define adjust! - (lambda (h vec1 n2 who) - (let ([vec2 (make-vector n2 '())] - [mask2 (fx- n2 1)] - [hash (gen-ht-hash h)]) - (vector-for-each - (lambda (b) - (for-each - (lambda (a) - (let ([hc (do-hash hash (car a) mask2 who)]) - (vector-set! vec2 hc (cons a (vector-ref vec2 hc))))) - b)) - vec1) - (ht-vec-set! h vec2)))) - - (define $gen-hashtable-set! - (lambda (h x v who) - (let ([vec (ht-vec h)] [equiv? (gen-ht-equiv? h)]) - (let ([idx (do-hash (gen-ht-hash h) x (fx- (vector-length vec) 1) who)]) - (let ([bucket (vector-ref vec idx)]) - (let loop ([b bucket]) - (if (null? b) - (begin - (vector-set! vec idx (cons (cons x v) bucket)) - (incr-size! h vec who)) - (let ([a (car b)]) - (if (equiv? (car a) x) (set-cdr! a v) (loop (cdr b))))))))))) - - (define $gen-hashtable-update! - (lambda (h x p v who) - (let ([vec (ht-vec h)] [equiv? (gen-ht-equiv? h)]) - (let ([idx (do-hash (gen-ht-hash h) x (fx- (vector-length vec) 1) who)]) - (let ([bucket (vector-ref vec idx)]) - (let loop ([b bucket]) - (if (null? b) - (begin - (vector-set! vec idx (cons (cons x (p v)) bucket)) - (incr-size! h vec who)) - (let ([a (car b)]) - (if (equiv? (car a) x) - (set-cdr! a (p (cdr a))) - (loop (cdr b))))))))))) - - (define $gen-hashtable-cell - (lambda (h x v who) - (let ([vec (ht-vec h)] [equiv? (gen-ht-equiv? h)]) - (let ([idx (do-hash (gen-ht-hash h) x (fx- (vector-length vec) 1) who)]) - (let ([bucket (vector-ref vec idx)]) - (let loop ([b bucket]) - (if (null? b) - (let ([a (cons x v)]) - (vector-set! vec idx (cons a bucket)) - (incr-size! h vec who) - a) - (let ([a (car b)]) - (if (equiv? (car a) x) - a - (loop (cdr b))))))))))) - - (define $gen-hashtable-delete! - (lambda (h x who) - (let ([vec (ht-vec h)] [equiv? (gen-ht-equiv? h)]) - (let ([idx (do-hash (gen-ht-hash h) x (fx- (vector-length vec) 1) who)]) - (let loop ([b (vector-ref vec idx)] [p #f]) - (unless (null? b) - (let ([a (car b)]) - (if (equiv? (car a) x) - (begin - (if p (set-cdr! p (cdr b)) (vector-set! vec idx (cdr b))) - (decr-size! h vec who)) - (loop (cdr b) b)))))))))) - - (module ($gen-hashtable-copy $symbol-hashtable-copy) - (define copy-hashtable-vector - (lambda (h) - (let* ([vec1 (ht-vec h)] - [n (vector-length vec1)] - [vec2 (make-vector n '())]) - (do ([i 0 (fx+ i 1)]) - ((fx= i n)) - (vector-set! vec2 i - (map (lambda (a) (cons (car a) (cdr a))) - (vector-ref vec1 i)))) - vec2))) - - (define $gen-hashtable-copy - (lambda (h mutable?) - (make-gen-ht 'generic mutable? (copy-hashtable-vector h) (ht-minlen h) (ht-size h) - (gen-ht-hash h) (gen-ht-equiv? h)))) - - (define $symbol-hashtable-copy - (lambda (h mutable?) - (make-symbol-ht 'symbol mutable? (copy-hashtable-vector h) (ht-minlen h) (ht-size h) - (symbol-ht-equiv? h))))) - - (define $ht-hashtable-clear! - (lambda (h minlen) - (ht-vec-set! h (make-vector minlen '())) - (ht-minlen-set! h minlen) - (ht-size-set! h 0))) - - (define $ht-hashtable-keys - (lambda (h max-sz) - (let ([size (fxmin max-sz (ht-size h))]) - (let ([keys (make-vector size)] - [vec (ht-vec h)]) - (let ([n (vector-length vec)]) - (let f ([i 0] [ikey 0]) - (unless (or (fx= i n) (fx= ikey size)) - (let g ([b (vector-ref vec i)] [ikey ikey]) - (if (or (null? b) (fx= ikey size)) - (f (fx+ i 1) ikey) - (begin - (vector-set! keys ikey (caar b)) - (g (cdr b) (fx+ ikey 1)))))))) - keys)))) - - (define $ht-hashtable-values - (lambda (h max-sz) - (let ([size (fxmin max-sz (ht-size h))]) - (let ([vals (make-vector size)] - [vec (ht-vec h)]) - (let ([n (vector-length vec)]) - (let f ([i 0] [ival 0]) - (unless (or (fx= i n) (fx= ival size)) - (let g ([b (vector-ref vec i)] [ival ival]) - (if (or (null? b) (fx= ival size)) - (f (fx+ i 1) ival) - (begin - (vector-set! vals ival (cdar b)) - (g (cdr b) (fx+ ival 1)))))))) - vals)))) - - (define $ht-hashtable-entries - (lambda (h max-sz) - (let ([size (fxmin max-sz (ht-size h))]) - (let ([keys (make-vector size)] - [vals (make-vector size)] - [vec (ht-vec h)]) - (let ([n (vector-length vec)]) - (let f ([i 0] [ikey 0]) - (unless (or (fx= i n) (fx= ikey size)) - (let g ([b (vector-ref vec i)] [ikey ikey]) - (if (or (null? b) (fx= ikey size)) - (f (fx+ i 1) ikey) - (let ([a (car b)]) - (vector-set! keys ikey (car a)) - (vector-set! vals ikey (cdr a)) - (g (cdr b) (fx+ ikey 1)))))))) - (values keys vals))))) - - (define $ht-hashtable-cells - (lambda (h max-sz) - (let ([size (fxmin max-sz (ht-size h))]) - (let ([cells (make-vector size)] - [vec (ht-vec h)]) - (let ([n (vector-length vec)]) - (let f ([i 0] [icell 0]) - (unless (or (fx= i n) (fx= icell size)) - (let g ([b (vector-ref vec i)] [icell icell]) - (if (or (null? b) (fx= icell size)) - (f (fx+ i 1) icell) - (let ([a (car b)]) - (vector-set! cells icell a) - (g (cdr b) (fx+ icell 1)))))))) - cells)))) - - (define eqv-generic? - (lambda (x) - ; all numbers except fixnums must go through generic hashtable - (or (flonum? x) (bignum? x) (ratnum? x) ($exactnum? x) ($inexactnum? x)))) - - (define $eqv-hashtable-ref - (lambda (h x v who) - (if (eqv-generic? x) - ($gen-hashtable-ref (eqv-ht-genht h) x v who) - (#3%eq-hashtable-ref (eqv-ht-eqht h) x v)))) - - (define $eqv-hashtable-contains? - (lambda (h x who) - (if (eqv-generic? x) - ($gen-hashtable-contains? (eqv-ht-genht h) x who) - (#3%eq-hashtable-contains? (eqv-ht-eqht h) x)))) - - (define $eqv-hashtable-set! - (lambda (h x v who) - (if (eqv-generic? x) - ($gen-hashtable-set! (eqv-ht-genht h) x v who) - (#3%eq-hashtable-set! (eqv-ht-eqht h) x v)))) - - (define $eqv-hashtable-update! - (lambda (h x p v who) - (if (eqv-generic? x) - ($gen-hashtable-update! (eqv-ht-genht h) x p v who) - (#3%eq-hashtable-update! (eqv-ht-eqht h) x p v)))) - - (define $eqv-hashtable-cell - (lambda (h x v who) - (if (eqv-generic? x) - ($gen-hashtable-cell (eqv-ht-genht h) x v who) - (#3%eq-hashtable-cell (eqv-ht-eqht h) x v)))) - - (define $eqv-hashtable-delete! - (lambda (h x who) - (if (eqv-generic? x) - ($gen-hashtable-delete! (eqv-ht-genht h) x who) - (#3%eq-hashtable-delete! (eqv-ht-eqht h) x)))) - - (define $eqv-hashtable-copy - (lambda (h mutable?) - (make-eqv-ht 'eqv mutable? - ($eq-hashtable-copy (eqv-ht-eqht h) mutable?) - ($gen-hashtable-copy (eqv-ht-genht h) mutable?)))) - - (module ($eqv-hashtable-keys $eqv-hashtable-values $eqv-hashtable-entries $eqv-hashtable-cells) - (define vector-append - (lambda (v1 v2) - (let ([n1 (vector-length v1)] [n2 (vector-length v2)]) - (if (fx= n1 0) - v2 - (if (fx= n2 0) - v1 - (let ([v (make-vector (fx+ n1 n2))]) - (do ([i 0 (fx+ i 1)]) - ((fx= i n1)) - (vector-set! v i (vector-ref v1 i))) - (do ([i 0 (fx+ i 1)] [j n1 (fx+ j 1)]) - ((fx= i n2)) - (vector-set! v j (vector-ref v2 i))) - v)))))) - (define $eqv-hashtable-keys - (lambda (h max-sz) - (let* ([keys1 ($eq-hashtable-keys (eqv-ht-eqht h) max-sz)] - [keys2 ($ht-hashtable-keys (eqv-ht-genht h) (fx- max-sz (vector-length keys1)))]) - (vector-append keys1 keys2)))) - (define $eqv-hashtable-values - (lambda (h max-sz) - (let* ([vals1 ($eq-hashtable-values (eqv-ht-eqht h) max-sz)] - [vals2 ($ht-hashtable-values (eqv-ht-genht h) (fx- max-sz (vector-length vals1)))]) - (vector-append vals1 vals2)))) - (define $eqv-hashtable-entries - (lambda (h max-sz) - (let*-values ([(keys1 vals1) ($eq-hashtable-entries (eqv-ht-eqht h) max-sz)] - [(keys2 vals2) ($ht-hashtable-entries (eqv-ht-genht h) (fx- max-sz (vector-length keys1)))]) - (values - (vector-append keys1 keys2) - (vector-append vals1 vals2))))) - (define $eqv-hashtable-cells - (lambda (h max-sz) - (let* ([cells1 ($eq-hashtable-cells (eqv-ht-eqht h) max-sz)] - [cells2 ($ht-hashtable-cells (eqv-ht-genht h) (fx- max-sz (vector-length cells1)))]) - (vector-append cells1 cells2))))) - - (define number-hash - (lambda (z) - (cond - [(fixnum? z) (if (fx< z 0) (fxnot z) z)] - [(flonum? z) ($flhash z)] - [(bignum? z) (modulo z (most-positive-fixnum))] - [(ratnum? z) (number-hash (+ (* (numerator z) 5) (denominator z)))] - [else (logxor (lognot (number-hash (real-part z))) (number-hash (imag-part z)))]))) - - (set! $make-eq-hashtable ; assumes minlen is a power of two >= 1 - (lambda (minlen subtype) - (make-eq-ht 'eq #t ($make-eqhash-vector minlen) minlen 0 subtype))) - - (set-who! $hashtable-veclen - (lambda (h) - (unless (xht? h) ($oops who "~s is not a hashtable" h)) - (case (xht-type h) - [(eqv) (values (vector-length (ht-vec (eqv-ht-eqht h))) (vector-length (ht-vec (eqv-ht-genht h))))] - [else (vector-length (ht-vec h))]))) - - (set-who! $ht-veclen - (lambda (h) - (unless (ht? h) ($oops who "~s is not an ht" h)) - (vector-length (ht-vec h)))) - - (set-who! $ht-minlen - (lambda (h) - (unless (ht? h) ($oops who "~s is not an ht" h)) - (ht-minlen h))) - - (let () - (define report - (lambda (h bucket-length) - (define (rnd n) (/ (round (* (inexact n) 100)) 100)) - (let ([vec (ht-vec h)]) - (let ([n (vector-length vec)]) - (let f ([i 0] [cnt 0] [m 0] [ss 0]) - (if (= i n) - (let ([mean (/ cnt n)]) - (printf - "size, count, max, mean, std = ~s, ~s, ~s, ~s, ~s~%" - n cnt m (rnd mean) - (rnd (* (sqrt (- (/ ss n) (* mean mean))))))) - (let ([k (bucket-length (vector-ref vec i))]) - (f (+ i 1) (+ cnt k) (max k m) (+ ss (* k k)))))))))) - (define eq-bucket-length - (lambda (b) - (if (fixnum? b) 0 (fx1+ (eq-bucket-length ($tlc-next b)))))) - (set-who! $hashtable-report - (lambda (h) - (unless (xht? h) ($oops who "~s is not a hashtable" h)) - (case (xht-type h) - [(eq) (report h eq-bucket-length)] - [(eqv) - (report (eqv-ht-eqht h) eq-bucket-length) - (report (eqv-ht-genht h) length)] - [else (report h length)])))) - - ; csv7 interface - (set! make-hash-table - (case-lambda - [() ($make-eq-hashtable (constant hashtable-default-size) (constant eq-hashtable-subtype-normal))] - [(weak?) ($make-eq-hashtable (constant hashtable-default-size) - (if weak? - (constant eq-hashtable-subtype-weak) - (constant eq-hashtable-subtype-normal)))])) - - (set! hash-table? - (lambda (x) - (eq-ht? x))) - - (set-who! put-hash-table! - (lambda (h x v) - (unless (eq-ht? h) ($oops who "~s is not an eq hashtable" h)) - (unless (xht-mutable? h) ($oops who "~s is not mutable" h)) - (#3%eq-hashtable-set! h x v))) - - (set-who! get-hash-table - (lambda (h x d) - (unless (eq-ht? h) ($oops who "~s is not an eq hashtable" h)) - (#3%eq-hashtable-ref h x d))) - - (set-who! remove-hash-table! - (lambda (h x) - (unless (eq-ht? h) ($oops who "~s is not an eq hashtable" h)) - (unless (xht-mutable? h) ($oops who "~s is not mutable" h)) - (#3%eq-hashtable-delete! h x))) - - (set-who! hash-table-map - (lambda (h p) - (unless (eq-ht? h) ($oops who "~s is not an eq hashtable" h)) - (unless (procedure? p) ($oops who "~s is not a procedure" p)) - (let-values ([(keys vals) ($eq-hashtable-entries h (most-positive-fixnum))]) - (let f ([i (vector-length keys)] [ls '()]) - (if (fx= i 0) - ls - (let ([i (fx- i 1)]) - (f i (cons (p (vector-ref keys i) (vector-ref vals i)) ls)))))))) - - (set-who! hash-table-for-each - (lambda (h p) - (unless (eq-ht? h) ($oops who "~s is not an eq hashtable" h)) - (unless (procedure? p) ($oops who "~s is not a procedure" p)) - (let-values ([(keys vals) ($eq-hashtable-entries h (most-positive-fixnum))]) - (vector-for-each p keys vals)))) - - (set-who! make-eq-hashtable - (case-lambda - [() ($make-eq-hashtable (constant hashtable-default-size) (constant eq-hashtable-subtype-normal))] - [(k) ($make-eq-hashtable (size->minlen who k) (constant eq-hashtable-subtype-normal))])) - - (set-who! make-weak-eq-hashtable - (case-lambda - [() ($make-eq-hashtable (constant hashtable-default-size) (constant eq-hashtable-subtype-weak))] - [(k) ($make-eq-hashtable (size->minlen who k) (constant eq-hashtable-subtype-weak))])) - - (set-who! make-ephemeron-eq-hashtable - (case-lambda - [() ($make-eq-hashtable (constant hashtable-default-size) (constant eq-hashtable-subtype-ephemeron))] - [(k) ($make-eq-hashtable (size->minlen who k) (constant eq-hashtable-subtype-ephemeron))])) - - (let () - (define $make-hashtable - (lambda (minlen hash equiv?) - (if (and (eq? hash symbol-hash) - (or (eq? equiv? eq?) - (eq? equiv? symbol=?) - (eq? equiv? eqv?) - (eq? equiv? equal?))) - (make-symbol-ht 'symbol #t (make-vector minlen '()) minlen 0 equiv?) - (make-gen-ht 'generic #t (make-vector minlen '()) minlen 0 hash equiv?)))) - (define $make-eqv-hashtable - (lambda (minlen subtype) - (make-eqv-ht 'eqv #t - ($make-eq-hashtable minlen subtype) - ($make-hashtable minlen number-hash eqv?)))) - (set-who! make-hashtable - (case-lambda - [(hash equiv?) - (unless (procedure? hash) ($oops who "~s is not a procedure" hash)) - (unless (procedure? equiv?) ($oops who "~s is not a procedure" equiv?)) - ($make-hashtable (constant hashtable-default-size) hash equiv?)] - [(hash equiv? k) - (unless (procedure? hash) ($oops who "~s is not a procedure" hash)) - (unless (procedure? equiv?) ($oops who "~s is not a procedure" equiv?)) - ($make-hashtable (size->minlen who k) hash equiv?)])) - (set-who! make-eqv-hashtable - (case-lambda - [() ($make-eqv-hashtable (constant hashtable-default-size) (constant eq-hashtable-subtype-normal))] - [(k) ($make-eqv-hashtable (size->minlen who k) (constant eq-hashtable-subtype-normal))])) - (set-who! make-weak-eqv-hashtable - (case-lambda - [() ($make-eqv-hashtable (constant hashtable-default-size) (constant eq-hashtable-subtype-weak))] - [(k) ($make-eqv-hashtable (size->minlen who k) (constant eq-hashtable-subtype-weak))])) - (set-who! make-ephemeron-eqv-hashtable - (case-lambda - [() ($make-eqv-hashtable (constant hashtable-default-size) (constant eq-hashtable-subtype-ephemeron))] - [(k) ($make-eqv-hashtable (size->minlen who k) (constant eq-hashtable-subtype-ephemeron))]))) - - (set! eq-hashtable-ref - (lambda (h x v) - (unless (eq-ht? h) - ($oops 'eq-hashtable-ref "~s is not an eq hashtable" h)) - (#3%eq-hashtable-ref h x v))) - - (set! eq-hashtable-contains? - (lambda (h x) - (unless (eq-ht? h) - ($oops 'eq-hashtable-contains? "~s is not an eq hashtable" h)) - (#3%eq-hashtable-contains? h x))) - - (set! eq-hashtable-set! - (lambda (h x v) - (unless (eq-ht? h) - ($oops 'eq-hashtable-set! "~s is not an eq hashtable" h)) - (unless (xht-mutable? h) - ($oops 'eq-hashtable-set! "~s is not mutable" h)) - (#3%eq-hashtable-set! h x v))) - - (set! eq-hashtable-update! - (lambda (h x p v) - (unless (eq-ht? h) - ($oops 'eq-hashtable-update! "~s is not an eq hashtable" h)) - (unless (xht-mutable? h) - ($oops 'eq-hashtable-update! "~s is not mutable" h)) - (unless (procedure? p) - ($oops 'eq-hashtable-update! "~s is not a procedure" p)) - (#3%eq-hashtable-update! h x p v))) - - (set! eq-hashtable-cell - (lambda (h x v) - (unless (eq-ht? h) - ($oops 'eq-hashtable-cell "~s is not an eq hashtable" h)) - (#3%eq-hashtable-cell h x v))) - - (set! eq-hashtable-delete! - (lambda (h x) - (unless (eq-ht? h) - ($oops 'eq-hashtable-delete! "~s is not an eq hashtable" h)) - (unless (xht-mutable? h) - ($oops 'eq-hashtable-delete! "~s is not mutable" h)) - (#3%eq-hashtable-delete! h x))) - - (set-who! eq-hashtable-weak? - (lambda (h) - (unless (eq-ht? h) ($oops who "~s is not an eq hashtable" h)) - (eq? (constant eq-hashtable-subtype-weak) (eq-ht-subtype h)))) - - (set-who! eq-hashtable-ephemeron? - (lambda (h) - (unless (eq-ht? h) ($oops who "~s is not an eq hashtable" h)) - (eq? (constant eq-hashtable-subtype-ephemeron) (eq-ht-subtype h)))) - - (set-who! hashtable-weak? - (lambda (h) - (unless (xht? h) ($oops who "~s is not a hashtable" h)) - (case (xht-type h) - [(eq) (eq? (constant eq-hashtable-subtype-weak) (eq-ht-subtype h))] - [(eqv) (eq? (constant eq-hashtable-subtype-weak) (eq-ht-subtype (eqv-ht-eqht h)))] - [else #f]))) - - (set-who! hashtable-ephemeron? - (lambda (h) - (unless (xht? h) ($oops who "~s is not a hashtable" h)) - (case (xht-type h) - [(eq) (eq? (constant eq-hashtable-subtype-ephemeron) (eq-ht-subtype h))] - [(eqv) (eq? (constant eq-hashtable-subtype-ephemeron) (eq-ht-subtype (eqv-ht-eqht h)))] - [else #f]))) - - (set-who! symbol-hashtable-ref - (lambda (h x v) - (unless (symbol-ht? h) ($oops who "~s is not a symbol hashtable" h)) - (unless (symbol? x) ($oops who "~s is not a symbol" x)) - (#3%symbol-hashtable-ref h x v))) - - (set-who! symbol-hashtable-contains? - (lambda (h x) - (unless (symbol-ht? h) ($oops who "~s is not a symbol hashtable" h)) - (unless (symbol? x) ($oops who "~s is not a symbol" x)) - (#3%symbol-hashtable-contains? h x))) - - (set-who! symbol-hashtable-set! - (lambda (h x v) - (unless (symbol-ht? h) ($oops who "~s is not a symbol hashtable" h)) - (unless (symbol? x) ($oops who "~s is not a symbol" x)) - (unless (xht-mutable? h) ($oops who "~s is not mutable" h)) - (#3%symbol-hashtable-set! h x v))) - - (set-who! symbol-hashtable-update! - (lambda (h x p v) - (unless (symbol-ht? h) ($oops who "~s is not a symbol hashtable" h)) - (unless (symbol? x) ($oops who "~s is not a symbol" x)) - (unless (xht-mutable? h) ($oops who "~s is not mutable" h)) - (unless (procedure? p) - ($oops who "~s is not a procedure" p)) - (#3%symbol-hashtable-update! h x p v))) - - (set-who! symbol-hashtable-cell - (lambda (h x v) - (unless (symbol-ht? h) ($oops who "~s is not a symbol hashtable" h)) - (unless (symbol? x) ($oops who "~s is not a symbol" x)) - (#3%symbol-hashtable-cell h x v))) - - (set-who! symbol-hashtable-delete! - (lambda (h x) - (unless (symbol-ht? h) ($oops who "~s is not a symbol hashtable" h)) - (unless (symbol? x) ($oops who "~s is not a symbol" x)) - (unless (xht-mutable? h) ($oops who "~s is not mutable" h)) - (#3%symbol-hashtable-delete! h x))) - - (set-who! hashtable-ref - (lambda (h x v) - (unless (xht? h) - ($oops who "~s is not a hashtable" h)) - (case (xht-type h) - [(eq) (#3%eq-hashtable-ref h x v)] - [(symbol) - (unless (symbol? x) ($oops 'symbol-hash "~s is not a symbol" x)) - (#3%symbol-hashtable-ref h x v)] - [(eqv) ($eqv-hashtable-ref h x v who)] - [else ($gen-hashtable-ref h x v who)]))) - - (set-who! hashtable-contains? - (lambda (h x) - (unless (xht? h) - ($oops who "~s is not a hashtable" h)) - (case (xht-type h) - [(eq) (#3%eq-hashtable-contains? h x)] - [(symbol) - (unless (symbol? x) ($oops 'symbol-hash "~s is not a symbol" x)) - (#3%symbol-hashtable-contains? h x)] - [(eqv) ($eqv-hashtable-contains? h x who)] - [else ($gen-hashtable-contains? h x who)]))) - - (set-who! hashtable-set! - (lambda (h x v) - (unless (xht? h) - ($oops who "~s is not a hashtable" h)) - (unless (xht-mutable? h) - ($oops who "~s is not mutable" h)) - (case (xht-type h) - [(eq) (#3%eq-hashtable-set! h x v)] - [(symbol) - (unless (symbol? x) ($oops 'symbol-hash "~s is not a symbol" x)) - (#3%symbol-hashtable-set! h x v)] - [(eqv) ($eqv-hashtable-set! h x v who)] - [else ($gen-hashtable-set! h x v who)]))) - - (set-who! hashtable-update! - (lambda (h x p v) - (unless (xht? h) - ($oops who "~s is not a hashtable" h)) - (unless (xht-mutable? h) - ($oops who "~s is not mutable" h)) - (unless (procedure? p) - ($oops who "~s is not a procedure" p)) - (case (xht-type h) - [(eq) (#3%eq-hashtable-update! h x p v)] - [(symbol) - (unless (symbol? x) ($oops 'symbol-hash "~s is not a symbol" x)) - (#3%symbol-hashtable-update! h x p v)] - [(eqv) ($eqv-hashtable-update! h x p v who)] - [else ($gen-hashtable-update! h x p v who)]))) - - (set-who! hashtable-cell - (lambda (h x v) - (unless (xht? h) - ($oops who "~s is not a hashtable" h)) - (case (xht-type h) - [(eq) (#3%eq-hashtable-cell h x v)] - [(symbol) - (unless (symbol? x) ($oops 'symbol-hash "~s is not a symbol" x)) - (#3%symbol-hashtable-cell h x v)] - [(eqv) ($eqv-hashtable-cell h x v who)] - [else ($gen-hashtable-cell h x v who)]))) - - (set-who! hashtable-delete! - (lambda (h x) - (unless (xht? h) - ($oops who "~s is not a hashtable" h)) - (unless (xht-mutable? h) - ($oops who "~s is not mutable" h)) - (case (xht-type h) - [(eq) (#3%eq-hashtable-delete! h x)] - [(symbol) - (unless (symbol? x) ($oops 'symbol-hash "~s is not a symbol" x)) - (#3%symbol-hashtable-delete! h x)] - [(eqv) ($eqv-hashtable-delete! h x who)] - [else ($gen-hashtable-delete! h x who)]))) - - (set! hashtable-copy - (rec hashtable-copy - (case-lambda - [(h) (hashtable-copy h #f)] - [(h mutable?) - (unless (xht? h) - ($oops 'hashtable-copy "~s is not a hashtable" h)) - (case (xht-type h) - [(eq) ($eq-hashtable-copy h (and mutable? #t))] - [(symbol) ($symbol-hashtable-copy h (and mutable? #t))] - [(eqv) ($eqv-hashtable-copy h (and mutable? #t))] - [else ($gen-hashtable-copy h (and mutable? #t))])]))) - - (set-who! hashtable-clear! - (let () - (case-lambda - [(h) - (unless (xht? h) - ($oops who "~s is not a hashtable" h)) - (unless (xht-mutable? h) - ($oops who "~s is not mutable" h)) - (case (xht-type h) - [(eq) ($eq-hashtable-clear! h (ht-minlen h))] - [(eqv) - (let ([h (eqv-ht-eqht h)]) ($eq-hashtable-clear! h (ht-minlen h))) - (let ([h (eqv-ht-genht h)]) ($ht-hashtable-clear! h (ht-minlen h)))] - [else ($ht-hashtable-clear! h (ht-minlen h))])] - [(h k) - (unless (xht? h) - ($oops who "~s is not a hashtable" h)) - (unless (xht-mutable? h) - ($oops who "~s is not mutable" h)) - (let ([minlen (size->minlen who k)]) - (case (xht-type h) - [(eq) ($eq-hashtable-clear! h minlen)] - [(eqv) - ($eq-hashtable-clear! (eqv-ht-eqht h) minlen) - ($ht-hashtable-clear! (eqv-ht-genht h) minlen)] - [else ($ht-hashtable-clear! h minlen)]))]))) - - (let () - (define (invalid-length who max-sz) - ($oops who "~s is not a valid length" max-sz)) - (define (invalid-table who h) - ($oops who "~s is not a hashtable" h)) - - (define-syntax hashtable-content-dispatch - (syntax-rules () - [(_ who $eq-hashtable-content $eqv-hashtable-content $ht-hashtable-content) - (let () - (define (dispatch h max-sz) - (unless (xht? h) (invalid-table who h)) - (case (xht-type h) - [(eq) ($eq-hashtable-content h max-sz)] - [(eqv) ($eqv-hashtable-content h max-sz)] - [else ($ht-hashtable-content h max-sz)])) - (case-lambda - [(h max-sz) - (cond - [(fixnum? max-sz) - (unless (fx>= max-sz 0) (invalid-length who max-sz)) - (dispatch h max-sz)] - [(bignum? max-sz) - (unless (>= max-sz 0) (invalid-length who max-sz)) - (dispatch h (most-positive-fixnum))] - [else (invalid-length who max-sz)])] - [(h) (dispatch h (most-positive-fixnum))]))])) - - (set-who! hashtable-keys - (hashtable-content-dispatch who - $eq-hashtable-keys - $eqv-hashtable-keys - $ht-hashtable-keys)) - - (set-who! #(r6rs: hashtable-keys) - (lambda (h) - (unless (xht? h) (invalid-table who h)) - (case (xht-type h) - [(eq) ($eq-hashtable-keys h (most-positive-fixnum))] - [(eqv) ($eqv-hashtable-keys h (most-positive-fixnum))] - [else ($ht-hashtable-keys h (most-positive-fixnum))]))) - - (set-who! hashtable-values - (hashtable-content-dispatch who - $eq-hashtable-values - $eqv-hashtable-values - $ht-hashtable-values)) - - (set-who! hashtable-entries - (hashtable-content-dispatch who - $eq-hashtable-entries - $eqv-hashtable-entries - $ht-hashtable-entries)) - - (set-who! #(r6rs: hashtable-entries) - (lambda (h) - (unless (xht? h) (invalid-table who h)) - (case (xht-type h) - [(eq) ($eq-hashtable-entries h (most-positive-fixnum))] - [(eqv) ($eqv-hashtable-entries h (most-positive-fixnum))] - [else ($ht-hashtable-entries h (most-positive-fixnum))]))) - - (set-who! hashtable-cells - (hashtable-content-dispatch who - $eq-hashtable-cells - $eqv-hashtable-cells - $ht-hashtable-cells))) - - (set! hashtable-size - (lambda (h) - (unless (xht? h) ($oops 'hashtable-size "~s is not a hashtable" h)) - (if (eq? (xht-type h) 'eqv) - (fx+ (ht-size (eqv-ht-eqht h)) - (ht-size (eqv-ht-genht h))) - (ht-size h)))) - - (set! hashtable-mutable? - (lambda (h) - (unless (xht? h) - ($oops 'hashtable-mutable? "~s is not a hashtable" h)) - (xht-mutable? h))) - - (set! hashtable? - (lambda (x) - (xht? x))) - - (set! eq-hashtable? - (lambda (x) - (eq-ht? x))) - - (set! symbol-hashtable? - (lambda (x) - (symbol-ht? x))) - - (set-who! $hashtable-size->minlen - (lambda (k) - (size->minlen who k))) - - (set-who! hashtable-hash-function - (lambda (h) - (unless (xht? h) ($oops who "~s is not an eq hashtable" h)) - (case (xht-type h) - [(eq eqv) #f] - [(symbol) symbol-hash] - [else (gen-ht-hash h)]))) - - (set-who! hashtable-equivalence-function - (lambda (h) - (unless (xht? h) ($oops who "~s is not an eq hashtable" h)) - (case (xht-type h) - [(eq) eq?] - [(symbol) (symbol-ht-equiv? h)] - [(eqv) eqv?] - [else (gen-ht-equiv? h)]))) - - (let () - (define (hcabs hc) (if (fx< hc 0) (fxnot hc) hc)) - - (define (update hc k) - (fxlogxor (#3%fx+ (#3%fxsll hc 2) hc) k)) - - (define bytevector-hash - (lambda (bv) - (define (bvupdate hc bv i) - (update hc (bytevector-u8-ref bv i))) - (let ([n (bytevector-length bv)]) - (if (fx<= n 16) - (do ([i 0 (fx+ i 1)] [hc 440697712 (bvupdate hc bv i)]) - ((fx= i n) (hcabs hc))) - (do ([i 0 (fx+ i 1)] - [hc 440697712 (bvupdate hc bv i)]) - ((fx= i 5) - (do ([i (fx- n 5) (fx+ i 1)] - [hc hc (bvupdate hc bv i)]) - ((fx= i n) - (let ([stride (fxsrl n 4)]) - (do ([i 5 (fx+ i stride)] - [hc hc (bvupdate hc bv i)]) - ((fx>= i n) (hcabs hc)))))))))))) - - (set-who! string-hash - (lambda (s) - (define (strupdate hc s i) - (update hc (char->integer (string-ref s i)))) - (unless (string? s) ($oops who "~s is not a string" s)) - (let ([n (string-length s)]) - (if (fx<= n 16) - (do ([i 0 (fx+ i 1)] [hc 523658599 (strupdate hc s i)]) - ((fx= i n) (hcabs hc))) - (do ([i 0 (fx+ i 1)] - [hc 523658599 (strupdate hc s i)]) - ((fx= i 5) - (do ([i (fx- n 5) (fx+ i 1)] - [hc hc (strupdate hc s i)]) - ((fx= i n) - (let ([stride (fxsrl n 4)]) - (do ([i 5 (fx+ i stride)] - [hc hc (strupdate hc s i)]) - ((fx>= i n) (hcabs hc)))))))))))) - - (set-who! string-ci-hash - (lambda (s) - (define (charupdate hc c) (update hc (char->integer c))) - (unless (string? s) ($oops who "~s is not a string" s)) - (let ([n (string-length s)]) - (let f ([i 0] [hc 523658599]) - (if (fx= i n) - (hcabs hc) - (let g ([c* ($string-char-foldcase (string-ref s i))] [hc hc]) - (if (char? c*) - (f (fx+ i 1) (charupdate hc c*)) - (g (cdr c*) (charupdate hc (car c*)))))))))) - - (set-who! symbol-hash - (lambda (x) - (unless (symbol? x) ($oops who "~s is not a symbol" x)) - (or ($symbol-hash x) - (and (gensym? x) (begin (gensym->unique-string x) ($symbol-hash x))) - ($oops who "symbol hash is not set for ~s" x)))) - - (set-who! equal-hash - (lambda (x) - (define (f x hc i) - (let ([i (fx- i 1)]) - (cond - [(fx<= i 0) (values hc 0)] - [(pair? x) - (let ([i/2 (fxsrl (fx+ i 1) 1)]) - (let-values ([(hc i^) (f (car x) (update hc 119001092) i/2)]) - (f (cdr x) hc (fx+ (fx- i i/2) i^))))] - [(vector? x) - (let ([n (vector-length x)] [hc (update hc 513566316)]) - (if (fx= n 0) - (values hc i) - (let g ([j 0] [hc hc] [i i]) - (if (or (fx= j n) (fx= i 0)) - (values hc i) - (let ([i/2 (fxsrl (fx+ i 1) 1)]) - (let-values ([(hc i^) (f (vector-ref x j) hc i/2)]) - (g (fx+ j 1) hc (fx+ (fx- i i/2) i^))))))))] - [(null? x) (values (update hc 496904691) i)] - [(box? x) (f (unbox x) (update hc 410225874) i)] - [(symbol? x) (values (update hc (symbol-hash x)) i)] - [(string? x) (values (update hc (string-hash x)) i)] - [(number? x) (values (update hc (number-hash x)) i)] - [(bytevector? x) (values (update hc (bytevector-hash x)) i)] - [(boolean? x) (values (update hc (if x 336200167 307585980)) i)] - [(char? x) (values (update hc (char->integer x)) i)] - [(and ($record? x) ($record-hash-procedure x)) - => (lambda (rec-hash) - (let ([new-i i]) - (let ([sub-hc (rec-hash - x - (lambda (v) - (if (fx<= new-i 0) - 0 - (let-values ([(sub-hc sub-i) (f v 0 i)]) - (set! new-i sub-i) - sub-hc))))]) - (let ([hc (update hc (if (fixnum? sub-hc) - sub-hc - (modulo (abs sub-hc) (greatest-fixnum))))]) - (values hc new-i)))))] - [else (values (update hc 120634730) i)]))) - (let-values ([(hc i) (f x 523658599 64)]) - (hcabs hc))))) - - (record-writer (type-descriptor hashtable) - (lambda (x p wr) - (display "#" p))) - - (record-writer (type-descriptor eq-ht) - (lambda (x p wr) - (display "#" p))) - - (record-writer (type-descriptor eqv-ht) - (lambda (x p wr) - (display "#" p))) -) - -;;; eq hashtable operations must be compiled with -;;; generate-interrupt-trap #f and optimize-level 3 -;;; so they can't be interrupted by a collection -;;; see also library routines in library.ss -(eval-when (compile) - (generate-interrupt-trap #f) - (optimize-level 3)) - -(let () - (include "hashtable-types.ss") - - (set! $eq-hashtable-keys - (lambda (h max-sz) - (let ([vec (ht-vec h)] [size (fxmin max-sz (ht-size h))]) - (let ([n (vector-length vec)] [keys (make-vector size)]) - (let outer ([i 0] [j 0]) - (if (or (fx= i n) (fx= j size)) - keys - (let inner ([b (vector-ref vec i)] [j j]) - (if (or (fixnum? b) (fx= j size)) - (outer (fx+ i 1) j) - (let ([keyval ($tlc-keyval b)]) - (vector-set! keys j (car keyval)) - (inner ($tlc-next b) (fx+ j 1))))))))))) - - (set! $eq-hashtable-values - (lambda (h max-sz) - (let ([vec (ht-vec h)] [size (fxmin max-sz (ht-size h))]) - (let ([n (vector-length vec)] [vals (make-vector size)]) - (let outer ([i 0] [j 0]) - (if (or (fx= i n) (fx= j size)) - vals - (let inner ([b (vector-ref vec i)] [j j]) - (if (or (fixnum? b) (fx= j size)) - (outer (fx+ i 1) j) - (let ([keyval ($tlc-keyval b)]) - (vector-set! vals j (cdr keyval)) - (inner ($tlc-next b) (fx+ j 1))))))))))) - - (set! $eq-hashtable-entries - (lambda (h max-sz) - (let ([vec (ht-vec h)] [size (fxmin max-sz (ht-size h))]) - (let ([n (vector-length vec)] - [keys (make-vector size)] - [vals (make-vector size)]) - (let outer ([i 0] [j 0]) - (if (or (fx= i n) (fx= j size)) - (values keys vals) - (let inner ([b (vector-ref vec i)] [j j]) - (if (or (fixnum? b) (fx= j size)) - (outer (fx+ i 1) j) - (let ([keyval ($tlc-keyval b)]) - (vector-set! keys j (car keyval)) - (vector-set! vals j (cdr keyval)) - (inner ($tlc-next b) (fx+ j 1))))))))))) - - (set! $eq-hashtable-cells - (lambda (h max-sz) - (let ([vec (ht-vec h)] [size (fxmin max-sz (ht-size h))]) - (let ([n (vector-length vec)] [cells (make-vector size)]) - (let outer ([i 0] [j 0]) - (if (or (fx= i n) (fx= j size)) - cells - (let inner ([b (vector-ref vec i)] [j j]) - (if (or (fixnum? b) (fx= j size)) - (outer (fx+ i 1) j) - (let ([keyval ($tlc-keyval b)]) - (vector-set! cells j keyval) - (inner ($tlc-next b) (fx+ j 1))))))))))) - - (set! $eq-hashtable-copy - (lambda (h1 mutable?) - (let ([subtype (eq-ht-subtype h1)]) - (let* ([vec1 (ht-vec h1)] - [n (vector-length vec1)] - [vec2 ($make-eqhash-vector n)] - [h2 (make-eq-ht 'eq mutable? vec2 (ht-minlen h1) (ht-size h1) subtype)]) - (let outer ([i 0]) - (if (fx= i n) - h2 - (begin - (vector-set! vec2 i - (let inner ([b (vector-ref vec1 i)]) - (if (fixnum? b) - b - ($make-tlc h2 - (let* ([keyval ($tlc-keyval b)] [key (car keyval)] [val (cdr keyval)]) - (cond - [(eq? subtype (constant eq-hashtable-subtype-normal)) (cons key val)] - [(eq? subtype (constant eq-hashtable-subtype-weak)) (weak-cons key val)] - [else (ephemeron-cons key val)])) - (inner ($tlc-next b)))))) - (outer (fx+ i 1))))) - h2)))) - - (set! $eq-hashtable-clear! - (lambda (h minlen) - (let* ([vec (ht-vec h)] [n (vector-length vec)]) - (do ([i 0 (fx+ i 1)]) - ((fx= i n)) - (let loop ([b (vector-ref vec i)]) - (if (fixnum? b) - (vector-set! vec i i) - (let ([next ($tlc-next b)]) - ($set-tlc-next! b #f) - (loop next))))) - (ht-size-set! h 0) - (unless (fx= n minlen) - (ht-vec-set! h ($make-eqhash-vector minlen)))))) - - (let () - ;; An equal/hash mapping contains an equal or hash procedure (or #f) - ;; plus the rtd where the procedure was installed. It also has a weak - ;; list of uids for child rtds that have inherited the setting, in - ;; case the rtd's setting changes. - (define-record-type equal/hash - (fields maybe-proc rtd (mutable inheritors)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (maybe-proc rtd) - (new maybe-proc rtd '()))))) - - (let () - (define (get-equal/hash who rtd key) - (unless (record-type-descriptor? rtd) - ($oops who "~s is not a record-type descriptor" rtd)) - (let ([e/h ($sgetprop (record-type-uid rtd) key #f)]) - (and e/h - (eq? (equal/hash-rtd e/h) rtd) - (equal/hash-maybe-proc e/h)))) - (define (set-equal/hash! who rtd key proc) - (unless (record-type-descriptor? rtd) - ($oops who "~s is not a record-type descriptor" rtd)) - (unless (or (not proc) (procedure? proc)) - ($oops who "~s is not a procedure or #f" proc)) - (with-tc-mutex - (let* ([uid (record-type-uid rtd)] - [old-e/h ($sgetprop uid key #f)]) - ;; Remove the old record from anywhere that it's inherited, - ;; and a later lookup will re-inherit: - (when old-e/h - (for-each - (lambda (uid) - (unless (bwp-object? uid) - (when (eq? ($sgetprop uid key #f) old-e/h) - ($sremprop uid key)))) - (equal/hash-inheritors old-e/h))) - (if proc - ($sputprop uid key (make-equal/hash proc rtd)) - ($sremprop uid key))))) - (set-who! record-type-equal-procedure - (case-lambda - [(rtd) (get-equal/hash who rtd 'equal-proc)] - [(rtd equal-proc) (set-equal/hash! who rtd 'equal-proc equal-proc)])) - (set-who! record-type-hash-procedure - (case-lambda - [(rtd) (get-equal/hash who rtd 'hash-proc)] - [(rtd hash-proc) (set-equal/hash! who rtd 'hash-proc hash-proc)]))) - - (let () - ;; Gets an `equal/hash` record for the given rtd, finding - ;; it from a parent rtd and caching if necessary: - (define (lookup-equal/hash record key) - (let* ([rtd ($record-type-descriptor record)] [uid (record-type-uid rtd)]) - ; Get out quick w/o mutex if equal/hash record is present - (or ($sgetprop uid key #f) - (with-tc-mutex - (let f ([uid uid] [rtd rtd]) - ;; Double-check first time around to avoid a race - (or ($sgetprop uid key #f) - (let ([parent-rtd (record-type-parent rtd)]) - (if parent-rtd - ;; Cache parent's value, and register as an inheritor: - (let ([e/h (f (record-type-uid parent-rtd) parent-rtd)]) - (equal/hash-inheritors-set! e/h (weak-cons uid (equal/hash-inheritors e/h))) - ($sputprop uid key e/h) - e/h) - ;; Cache an empty `equal/hash` record: - (let ([e/h (make-equal/hash #f rtd)]) - ($sputprop uid key e/h) - e/h))))))))) - (let () - (define (lookup-equal-procedure record1 record2) - (let ([e/h (lookup-equal/hash record1 'equal-proc)]) - (let ([proc (equal/hash-maybe-proc e/h)]) - (if proc - (and - (eq? (equal/hash-rtd (lookup-equal/hash record2 'equal-proc)) (equal/hash-rtd e/h)) - proc) - (let ([default-proc (default-record-equal-procedure)]) - (and default-proc - (not (equal/hash-maybe-proc (lookup-equal/hash record2 'equal-proc))) - default-proc)))))) - (set-who! $record-equal-procedure - (lambda (record1 record2) - (lookup-equal-procedure record1 record2))) - (set-who! record-equal-procedure - (lambda (record1 record2) - (unless ($record? record1) ($oops who "~s is not a record" record1)) - (unless ($record? record2) ($oops who "~s is not a record" record2)) - (lookup-equal-procedure record1 record2)))) - (let () - (define (lookup-hash-procedure record) - (or (equal/hash-maybe-proc (lookup-equal/hash record 'hash-proc)) - (default-record-hash-procedure))) - (set-who! $record-hash-procedure - (lambda (record) - (lookup-hash-procedure record))) - (set-who! record-hash-procedure - (lambda (record) - (unless ($record? record) ($oops who "~s is not a record" record)) - (lookup-hash-procedure record)))))) -) diff --git a/ta6ob/s/newhash.ta6ob b/ta6ob/s/newhash.ta6ob deleted file mode 100644 index 18614ef..0000000 Binary files a/ta6ob/s/newhash.ta6ob and /dev/null differ diff --git a/ta6ob/s/np-languages.ss b/ta6ob/s/np-languages.ss deleted file mode 100644 index 396729a..0000000 --- a/ta6ob/s/np-languages.ss +++ /dev/null @@ -1,1075 +0,0 @@ -;;; np-languages.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -#!chezscheme -(module np-languages () - (export sorry! var? var-index var-index-set! prelex->uvar make-tmp make-assigned-tmp - make-unspillable make-cpvar make-restricted-unspillable - uvar? uvar-name uvar-type uvar-source - uvar-referenced? uvar-referenced! uvar-assigned? uvar-assigned! - uvar-was-closure-ref? uvar-was-closure-ref! - uvar-unspillable? uvar-spilled? uvar-spilled! uvar-local-save? uvar-local-save! - uvar-seen? uvar-seen! uvar-loop? uvar-loop! uvar-poison? uvar-poison! - uvar-in-prefix? uvar-in-prefix! - uvar-location uvar-location-set! - uvar-move* uvar-move*-set! - uvar-conflict* - uvar-ref-weight uvar-ref-weight-set! uvar-save-weight uvar-save-weight-set! - uvar-live-count uvar-live-count-set! - uvar - fv-offset - var-spillable-conflict* var-spillable-conflict*-set! - var-unspillable-conflict* var-unspillable-conflict*-set! - uvar-degree uvar-degree-set! - uvar-info-lambda uvar-info-lambda-set! - uvar-iii uvar-iii-set! - ur? - block make-block block? block-label block-effect* block-src* block-pseudo-src block-in-link* block-flags - block-label-set! block-effect*-set! block-src*-set! block-pseudo-src-set! block-in-link*-set! block-flags-set! - block-live-in block-live-in-set! block-fp-offset block-fp-offset-set! - block-depth block-depth-set! block-loop-headers block-loop-headers-set! - block-weight block-weight-set! - block-index block-index-set! - block-pariah! block-seen! block-finished! block-return-point! block-repeater! block-loop-header! - block-pariah? block-seen? block-finished? block-return-point? block-repeater? block-loop-header? - L1 unparse-L1 L2 unparse-L2 L3 unparse-L3 L4 unparse-L4 - L4.5 unparse-L4.5 L4.75 unparse-L4.75 L4.875 unparse-L4.875 - L5 unparse-L5 L6 unparse-L6 L7 unparse-L7 - L9 unparse-L9 L9.5 unparse-L9.5 L9.75 unparse-L9.75 - L10 unparse-L10 L10.5 unparse-L10.5 L11 unparse-L11 - L11.5 unparse-L11.5 L12 unparse-L12 L13 unparse-L13 L13.5 unparse-L13.5 L14 unparse-L14 - L15a unparse-L15a L15b unparse-L15b L15c unparse-L15c L15d unparse-L15d - L15e unparse-L15e - L16 unparse-L16 - info null-info - live-info make-live-info live-info-live live-info-live-set! live-info-useless live-info-useless-set! - primitive-pure? primitive-type primitive-handler primitive-handler-set! - %primitive value-primitive? pred-primitive? effect-primitive? - fv? $make-fv make-reg reg? reg-name reg-tc-disp reg-callee-save? reg-mdinfo - reg-precolored reg-precolored-set! - label? label-name - libspec-label? make-libspec-label libspec-label-libspec libspec-label-live-reg* - local-label? make-local-label - local-label-func local-label-func-set! - local-label-offset local-label-offset-set! - local-label-iteration local-label-iteration-set! - local-label-block local-label-block-set! - local-label-overflow-check local-label-overflow-check-set! - local-label-trap-check local-label-trap-check-set! - direct-call-label? make-direct-call-label - direct-call-label-referenced direct-call-label-referenced-set! - Lsrc Lsrc? Ltype Ltype? unparse-Ltype unparse-Lsrc - lookup-primref primref? primref-level primref-name primref-flags primref-arity - preinfo-src preinfo-sexpr preinfo-lambda-name preinfo-lambda-flags preinfo-lambda-libspec - prelex-name prelex-name-set!) - - (import (nanopass)) - (include "base-lang.ss") - - ; r6rs says a quote subform should be a datum, not must be a datum - ; chez scheme allows a quote subform to be any value - (define datum? (lambda (x) #t)) - - (define-record-type var - (fields (mutable index) (mutable spillable-conflict*) (mutable unspillable-conflict*)) - (nongenerative) - (protocol (lambda (new) (lambda () (new #f #f #f))))) - - (define-record-type (fv $make-fv fv?) - (parent var) - (fields offset) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (offset) - ((pargs->new) offset))))) - - (module () - (record-writer (record-type-descriptor fv) - (lambda (x p wr) - (fprintf p "fv~s" (fv-offset x))))) - - (define-record-type reg - (parent var) - (fields name mdinfo tc-disp callee-save? (mutable precolored)) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (name mdinfo tc-disp callee-save?) - ((pargs->new) name mdinfo tc-disp callee-save? #f))))) - - (module () - (record-writer (record-type-descriptor reg) - (lambda (x p wr) - (write (reg-name x) p)))) - - (define-syntax define-flag-field - (lambda (exp) - (syntax-case exp () - ((_k type-name field (flag mask) ...) - (let () - (define getter-name - (lambda (f) - (construct-name #'_k #'type-name "-" f "?"))) - (define setter-name - (lambda (f) - (construct-name #'_k #'type-name "-" f "!"))) - (with-syntax ([field-ref (construct-name #'_k #'type-name "-" #'field)] - [field-set! (construct-name #'_k #'type-name "-" #'field "-set!")] - [(flag-ref ...) (map getter-name #'(flag ...))] - [(flag-set! ...) (map setter-name #'(flag ...))] - [f->m (construct-name #'_k #'type-name "-" #'field "-mask")]) - #'(begin - (define-flags f->m (flag mask) ...) - (define flag-ref - (lambda (x) - (any-set? (f->m flag) (field-ref x)))) - ... - (define flag-set! - (lambda (x bool) - (field-set! x - (let ([flags (field-ref x)]) - (if bool - (set-flags (f->m flag) flags) - (reset-flags (f->m flag) flags)))))) - ...))))))) - - (define-flag-field uvar flags - (referenced #b00000000001) - (assigned #b00000000010) - (unspillable #b00000000100) - (spilled #b00000001000) - (seen #b00000010000) - (was-closure-ref #b00000100000) - (loop #b00001000000) - (in-prefix #b00010000000) - (local-save #b00100000000) - (poison #b01000000000) - ) - - (define-record-type (uvar $make-uvar uvar?) - (parent var) - (fields - name - source - type - conflict* - (mutable flags) - (mutable info-lambda) - (mutable location) - (mutable move*) - (mutable degree) - (mutable iii) ; inspector info index - (mutable ref-weight) ; must be a fixnum! - (mutable save-weight) ; must be a fixnum! - (mutable live-count) ; must be a fixnum! - ) - (nongenerative) - (sealed #t) - (protocol - (lambda (pargs->new) - (lambda (name source type conflict* flags) - ((pargs->new) name source type conflict* flags #f #f '() #f #f 0 0 0))))) - (define prelex->uvar - (lambda (x) - ($make-uvar (prelex-name x) (prelex-source x) 'ptr '() - (if (prelex-referenced x) - (if (prelex-assigned x) - (uvar-flags-mask referenced assigned) - (uvar-flags-mask referenced)) - (if (prelex-assigned x) - (uvar-flags-mask assigned) - (uvar-flags-mask)))))) - (define make-tmp - (case-lambda - [(name) (make-tmp name 'ptr)] - [(name type) ($make-uvar name #f type '() (uvar-flags-mask referenced))])) - (define make-assigned-tmp - (case-lambda - [(name) (make-assigned-tmp name 'ptr)] - [(name type) ($make-uvar name #f type '() (uvar-flags-mask referenced assigned))])) - (define make-unspillable - (lambda (name) - ($make-uvar name #f 'ptr '() (uvar-flags-mask referenced unspillable)))) - (define make-cpvar - (lambda () - (include "types.ss") - ;; NB: cpsymbol is not a source object. Why is it put into the uvar-source field? - ($make-uvar 'cp cpsymbol 'ptr '() (uvar-flags-mask referenced)))) - (define make-restricted-unspillable - (lambda (name conflict*) - ($make-uvar name #f 'uptr conflict* (uvar-flags-mask referenced assigned unspillable)))) - - (module () - (record-writer (record-type-descriptor uvar) - (lambda (x p wr) - (write (lookup-unique-uvar x) p)))) - - (define lookup-unique-uvar - (let ([ht (make-eq-hashtable)]) - (lambda (x) - (or (eq-hashtable-ref ht x #f) - (let ([sym (gensym (symbol->string (uvar-name x)))]) - (eq-hashtable-set! ht x sym) - sym))))) - - (define-record-type info (nongenerative)) - - (define null-info (make-info)) - - (module () - (record-writer (record-type-descriptor info) - (lambda (x p wr) - (fprintf p "#")))) - - (define-record-type label - (nongenerative) - (fields name)) - - (define-record-type libspec-label - (parent label) - (nongenerative) - (sealed #t) - (fields libspec live-reg*) - (protocol - (lambda (pargs->new) - (lambda (name libspec live-reg*) - ((pargs->new name) libspec live-reg*))))) - - ; TODO: need better abstraction for reusing record fields for - ; different purposes in different passes. - (define-record-type local-label - (parent label) - (nongenerative) - (fields (mutable func) (mutable offset) (mutable iteration) (mutable block) - ; following used by place-overflow-and-trap-check pass - (mutable overflow-check) (mutable trap-check)) - (protocol - (lambda (pargs->new) - (lambda (name) - ((pargs->new name) #f #f #f #f 'no 'no))))) - - (define-record-type direct-call-label - (parent local-label) - (nongenerative) - (sealed #t) - (fields (mutable referenced)) - (protocol - (lambda (pargs->new) - (lambda (name) - ((pargs->new name) #f))))) - - (module () - (define lookup-unique-label - (let ([ht (make-eq-hashtable)]) - (lambda (x) - (or (eq-hashtable-ref ht x #f) - (let ([sym (gensym (symbol->string (label-name x)))]) - (eq-hashtable-set! ht x sym) - sym))))) - (record-writer (record-type-descriptor local-label) - (lambda (x p wr) - (write (lookup-unique-label x) p))) - (record-writer (record-type-descriptor libspec-label) - (lambda (x p wr) - (write (label-name x) p)))) - - (define maybe-var? - (lambda (x) - (or (eq? x #f) (var? x)))) - - (define maybe-label? - (lambda (x) - (or (eq? x #f) (label? x)))) - - ; language to replace prelex with uvar, create info records out of some of the complex - ; records, and make sure other record types have been discarded. also formally sets up - ; CaseLambdaClause as entry point for language. - (define-language L1 - (terminals - (uvar (x)) - (datum (d)) - (source-object (src)) - (info (info)) - (fixnum (interface)) - (primref (pr)) - ) - (entry CaseLambdaExpr) - (Expr (e body) - le - x - pr - (quote d) - (call info e0 e1 ...) => (e0 e1 ...) - (if e0 e1 e2) - (seq e0 e1) - (set! x e) - (letrec ([x le] ...) body) - (moi) => "moi" - (foreign info e) - (fcallable info e) - (profile src) => (profile) - (pariah) - ) - (CaseLambdaExpr (le) - (case-lambda info cl ...) => (case-lambda cl ...) - ) - (CaseLambdaClause (cl) - (clause (x* ...) interface body) - )) - - ; from this point on, if a uvar x is bound to a lambda expression le by letrec, - ; (uvar-info-lambda x) must be equal to le's info-lambda - - ; introducing let - (define-language L2 (extends L1) - (entry CaseLambdaExpr) - (Expr (e body) - (+ (let ([x e] ...) body)))) - - ; removes moi; also adds name to info-lambda & info-foreign - (define-language L3 (extends L2) - (entry CaseLambdaExpr) - (Expr (e body) - (- (moi)))) - - ; removes assignable indefinite-extent variables from the language - (define-language L4 (extends L3) - (entry CaseLambdaExpr) - (Expr (e body) - (- (set! x e)))) - - ; introducing mvlet, and mvcall - (define-language L4.5 (extends L4) - (terminals - (+ (maybe-label (mdcl)))) - (entry CaseLambdaExpr) - (Expr (e body) - (- (call info e0 e1 ...)) - (+ (call info mdcl e0 e1 ...) => (call mdcl e0 e1 ...) - (mvcall info e1 e2) => (mvcall e1 e2) - (mvlet e ((x** ...) interface* body*) ...)))) - - ; removes foreign, adds foreign-call, updates fcallable - (define-language L4.75 (extends L4.5) - (entry CaseLambdaExpr) - (terminals - (+ (label (l)))) - (Expr (e body) - (- (foreign info e) - (fcallable info e)) - (+ (label l body) - (foreign-call info e e* ...) - (fcallable info)))) - - ; adds loop form - (define-language L4.875 (extends L4.75) - (entry CaseLambdaExpr) - (Expr (e body) - (+ (loop x (x* ...) body) => (loop x body)))) - - ; moves all case lambda expressions into rhs of letrec - (define-language L5 (extends L4.875) - (entry CaseLambdaExpr) - (Expr (e body) - (- le))) - - ; replaces letrec with labels and closures forms - (define-language L6 (extends L5) - (terminals - (+ (maybe-var (mcp)))) - (entry CaseLambdaExpr) - (Expr (e body) - (- (letrec ([x le] ...) body)) - (+ (closures ([x* (x** ...) le*] ...) body))) - (CaseLambdaClause (cl) - (- (clause (x* ...) interface body)) - (+ (clause (x* ...) mcp interface body)))) - - ; move labels to top level and expands closures forms to more primitive operations - (define-language L7 (extends L6) - (terminals - (- (uvar (x)) - (fixnum (interface))) - (+ (var (x)) - (primitive (prim)) ; moved up one language to support closure instrumentation - (fixnum (interface offset)) - (immediate (imm)))) - (entry Program) - (Program (prog) - (+ (labels ([l* le*] ...) l) => (labels ([l* le*] ...) (l)))) - (CaseLambdaExpr (le) - (+ (fcallable info l) => (fcallable info l))) - (Lvalue (lvalue) - (+ x - (mref e1 e2 imm))) - (Expr (e body) - (- x - (fcallable info) - (closures ([x* (x** ...) le*] ...) body) - (call info mdcl e0 e1 ...)) - (+ lvalue - (alloc info e) => (alloc info e) - (literal info) => info - (label-ref l offset) - (immediate imm) => imm - ; moved up one language to support closure instrumentation - (inline info prim e* ...) => (inline info prim e* ...) - (call info mdcl (maybe e0) e1 ...) => (call mdcl e0 e1 ...) - (set! lvalue e) - ; these two forms are added here so expand-inline handlers can expand into them - (values info e* ...) - (goto l)))) - - (define-record-type primitive - (fields name type pure? (mutable handler)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (name type pure?) - (new name type pure? (lambda args (sorry! name "no primitive handler defined"))))))) - - (module () - (record-writer (record-type-descriptor primitive) - (lambda (x p wr) - (fprintf p "~s" (primitive-name x))))) - - (define value-primitive? - (lambda (x) - (and (primitive? x) - (eq? (primitive-type x) 'value)))) - - (define pred-primitive? - (lambda (x) - (and (primitive? x) - (eq? (primitive-type x) 'pred)))) - - (define effect-primitive? - (lambda (x) - (and (primitive? x) - (eq? (primitive-type x) 'effect)))) - - (define-syntax declare-primitive - (lambda (x) - (syntax-case x () - [(_ name type pure?) - (with-syntax ([%name (construct-name #'name "%" #'name)]) - #'(begin - (define %name (make-primitive 'name 'type pure?)) - (export %name)))]))) - - (define-syntax %primitive - (lambda (x) - (syntax-case x () - [(_ name) - (let ([a (syntax->annotation #'name)] - [sym (string->symbol (format "%~a" (datum name)))]) - (datum->syntax #'name - (if a (make-annotation sym (annotation-source a) sym) sym)))]))) - - (declare-primitive asmlibcall! effect #f) - (declare-primitive c-call effect #f) - (declare-primitive c-simple-call effect #f) - (declare-primitive c-simple-return effect #f) - (declare-primitive deactivate-thread effect #f) ; threaded version only - (declare-primitive fl* effect #f) - (declare-primitive fl+ effect #f) - (declare-primitive fl- effect #f) - (declare-primitive fl/ effect #f) - (declare-primitive fldl effect #f) ; x86 - (declare-primitive flds effect #f) ; x86 - (declare-primitive flsqrt effect #f) ; not implemented for some ppc32 (so we don't use it) - (declare-primitive flt effect #f) - (declare-primitive inc-cc-counter effect #f) - (declare-primitive inc-profile-counter effect #f) - (declare-primitive invoke-prelude effect #f) - (declare-primitive keep-live effect #f) - (declare-primitive load-double effect #f) - (declare-primitive load-double->single effect #f) - (declare-primitive load-single effect #f) - (declare-primitive load-single->double effect #f) - (declare-primitive locked-decr! effect #f) - (declare-primitive locked-incr! effect #f) - (declare-primitive pause effect #f) - (declare-primitive push effect #f) - (declare-primitive pop-multiple effect #f) ; arm - (declare-primitive push-multiple effect #f) ; arm - (declare-primitive remember effect #f) - (declare-primitive restore-flrv effect #f) - (declare-primitive restore-lr effect #f) ; ppc - (declare-primitive save-flrv effect #f) - (declare-primitive save-lr effect #f) ; ppc - (declare-primitive store effect #f) - (declare-primitive store-double effect #f) - (declare-primitive store-single effect #f) - (declare-primitive store-single->double effect #f) - (declare-primitive store-with-update effect #f) ; ppc - (declare-primitive unactivate-thread effect #f) ; threaded version only - (declare-primitive vpush-multiple effect #f) ; arm - (declare-primitive vpop-multiple effect #f) ; arm - (declare-primitive cas effect #f) - - (declare-primitive < pred #t) - (declare-primitive <= pred #t) - (declare-primitive > pred #t) - (declare-primitive >= pred #t) - (declare-primitive condition-code pred #t) - (declare-primitive eq? pred #t) - (declare-primitive fl< pred #t) - (declare-primitive fl<= pred #t) - (declare-primitive fl= pred #t) - (declare-primitive lock! pred #f) - (declare-primitive logtest pred #t) - (declare-primitive log!test pred #t) - (declare-primitive type-check? pred #t) - (declare-primitive u< pred #t) - - (declare-primitive - value #t) - (declare-primitive / value #t) - (declare-primitive + value #t) - (declare-primitive +/ovfl value #f) - (declare-primitive +/carry value #f) - (declare-primitive -/ovfl value #f) - (declare-primitive -/eq value #f) - (declare-primitive asmlibcall value #f) - (declare-primitive fstpl value #f) ; x86 only - (declare-primitive fstps value #f) ; x86 only - (declare-primitive get-double value #t) ; x86_64 - (declare-primitive get-tc value #f) ; threaded version only - (declare-primitive activate-thread value #f) ; threaded version only - (declare-primitive lea1 value #t) - (declare-primitive lea2 value #t) - (declare-primitive load value #t) - (declare-primitive logand value #t) - (declare-primitive logor value #t) - (declare-primitive logxor value #t) - (declare-primitive lognot value #t) - (declare-primitive move value #t) - (declare-primitive * value #t) - (declare-primitive */ovfl value #f) - (declare-primitive pop value #f) - (declare-primitive read-performance-monitoring-counter value #t) ; on x86/x86_64 actually side-effects edx/rdx - (declare-primitive read-time-stamp-counter value #t) ; on x86/x86_64 actually side-effects edx/rdx - (declare-primitive sext8 value #t) - (declare-primitive sext16 value #t) - (declare-primitive sext32 value #t) ; 64-bit only - (declare-primitive sll value #t) - (declare-primitive srl value #t) - (declare-primitive sra value #t) - (declare-primitive trunc value #t) - (declare-primitive zext8 value #t) - (declare-primitive zext16 value #t) - (declare-primitive zext32 value #t) ; 64-bit only - - (define immediate? - (let ([low (- (bitwise-arithmetic-shift-left 1 (fx- (constant ptr-bits) 1)))] - [high (- (bitwise-arithmetic-shift-left 1 (constant ptr-bits)) 1)]) - (if (and (eqv? (constant most-negative-fixnum) (most-negative-fixnum)) - (eqv? (constant most-positive-fixnum) (most-positive-fixnum))) - (lambda (x) (or (fixnum? x) (and (bignum? x) (<= low x high)))) - (lambda (x) (and (or (fixnum? x) (bignum? x)) (<= low x high)))))) - - (define imm->ptr - (lambda (x) - (cond - [(= x (constant sfalse)) #f] - [(= x (constant strue)) #t] - [(= x (constant svoid)) (void)] - [(= x (constant snil)) '()] - [(= x (constant seof)) #!eof] - [(= x (constant sunbound)) ($unbound-object)] - [(= x (constant sbwp)) #!bwp] - [(= (logand x (constant mask-fixnum)) (constant type-fixnum)) - (ash (- x (constant type-fixnum)) (- (constant fixnum-offset)))] - [(= (logand x (constant mask-char)) (constant type-char)) - (integer->char (/ (- x (constant type-char)) (constant char-factor)))] - [else ($oops 'cpnanopass-internal "imm->ptr got unrecognized immediate: ~s" x)]))) - - ; specifies the representation for simple scheme constants: #t, #f, (void), - ; '(), (eof-object), ($unbound-object), #!bwp, characters, and fixnums as - ; scheme-object ptrs and inlines primitive calls - (define-language L9 (extends L7) - (entry Program) - (terminals - (- (datum (d)) - (primref (pr))) - (+ (symbol (sym)))) - (CaseLambdaExpr (le) - (+ (hand-coded sym))) - (Expr (e body) - (- (quote d) - pr))) - - ; determine where we should be placing interrupt and overflow - (define-language L9.5 (extends L9) - (entry Program) - (terminals - (+ (boolean (ioc)))) - (Expr (e body) - (+ (trap-check ioc e) - (overflow-check e)))) - - ; remove the loop form - (define-language L9.75 (extends L9.5) - (entry Program) - (Expr (e body) - (- (loop x (x* ...) body)))) - - ; bindings are replaced with combination of a locals form and a series of set! - ; expressions; value is broken into three categories: Triv, Rhs, and Expr. Triv - ; expressions can appear as arguments to call and inline, or in any Rhs or Tail - ; location, and are considered simple enough for the instruction selector to handle. - ; Rhs expressions can appear on the right-hand-side of a set! or anywhere arbitrary - ; Exprs can appear. Exprs appear in the body of a case-lambda clause. - (define-language L10 (extends L9.75) - (terminals - (+ (uvar (local)))) - (entry Program) - (CaseLambdaClause (cl) - (- (clause (x* ...) mcp interface body)) - (+ (clause (x* ...) (local* ...) mcp interface body))) - (Lvalue (lvalue) - (- (mref e1 e2 imm)) - (+ (mref x1 x2 imm))) - (Triv (t) - (+ lvalue - (literal info) => info - (immediate imm) => (quote imm) - (label-ref l offset))) - (Rhs (rhs) - (+ t - (call info mdcl (maybe t0) t1 ...) => (call mdcl t0 t1 ...) - (alloc info t) => (alloc info t) - (inline info prim t* ...) => (inline info prim t* ...) - (mvcall info e t) => (mvcall e t) - (foreign-call info t t* ...))) - (Expr (e body) - (- lvalue - (values info e* ...) - (literal info) - (immediate imm) - (label-ref l offset) - (call info mdcl (maybe e0) e1 ...) - (inline info prim e* ...) - (alloc info e) - (let ([x e] ...) body) - (set! lvalue e) - (mvcall info e1 e2) - (foreign-call info e e* ...)) - (+ rhs - (values info t* ...) - (set! lvalue rhs)))) - - (define-language L10.5 (extends L10) - (entry Program) - (Rhs (rhs) - (- (call info mdcl (maybe t0) t1 ...) - (mvcall info e t)) - (+ (mvcall info mdcl (maybe t0) t1 ... (t* ...)) => (mvcall mdcl t0 t1 ... (t* ...)))) - (Expr (e body) - (- (mvlet e ((x** ...) interface* body*) ...)) - (+ (mvset info (mdcl (maybe t0) t1 ...) (t* ...) ((x** ...) interface* l*) ...) => - (mvset (mdcl t0 t1 ...) (t* ...) ((x** ...) interface* l*) ...) - (mlabel e (l* e*) ...)))) - - ; expressions are normalized into Tail, Pred, or Effect context; primrefs - ; are converted into inline expressions; make-closure, - ; closure-ref, and closure-set! are converted into inline calls; numbers and - ; labels used as arguments to make-closure, closure-ref, and closure-set! are - ; marked as literals so they will not be turned into scheme constants again. - (define-language L11 (extends L10.5) - (terminals - (- (primitive (prim))) - (+ (value-primitive (value-prim)) - (pred-primitive (pred-prim)) - (effect-primitive (effect-prim)))) - (entry Program) - (CaseLambdaClause (cl) - (- (clause (x* ...) (local* ...) mcp interface body)) - (+ (clause (x* ...) (local* ...) mcp interface tlbody))) - (Rhs (rhs) - (- (inline info prim t* ...)) - (+ (inline info value-prim t* ...) => (inline info value-prim t* ...))) - (Expr (e body) - (- rhs - (label l body) - (set! lvalue rhs) - (if e0 e1 e2) - (seq e0 e1) - (mvset info (mdcl (maybe t0) t1 ...) (t* ...) ((x** ...) interface* l*) ...) - (values info t* ...) - (goto l) - (mlabel e (l* e*) ...) - (pariah) - (trap-check ioc e) - (overflow-check e) - (profile src))) - (Tail (tl tlbody) - (+ rhs - (if p0 tl1 tl2) - (seq e0 tl1) - (values info t* ...) => (values t* ...) - (goto l))) - (Pred (p pbody) - (+ (true) => #t - (false) => #f - (inline info pred-prim t* ...) => (inline info pred-prim t* ...) - (if p0 p1 p2) - (seq e0 p1) - (goto l) - (mlabel p (l* p*) ...))) - (Effect (e ebody) - (+ (nop) - (label l) - (goto l) - (pariah) - (trap-check ioc) - (overflow-check) - (profile src) => (profile) - (set! lvalue rhs) - (inline info effect-prim t* ...) => (inline info effect-prim t* ...) - (if p0 e1 e2) - (seq e0 e1) - (mvset info (mdcl (maybe t0) t1 ...) (t* ...) ((x** ...) interface* l*) ...) => - (mvset (mdcl t0 t1 ...) (t* ...) ((x** ...) interface* l*) ...) - (mvcall info mdcl (maybe t0) t1 ... (t* ...)) => (mvcall mdcl t0 t1 ... (t* ...)) - (foreign-call info t t* ...) - (tail tl)))) - - (define-language L11.5 (extends L11) - (entry Program) - (terminals - (- (boolean (ioc)))) - (Effect (e body) - (- (trap-check ioc)))) - - (define-language L12 (extends L11.5) - (terminals - (- (fixnum (interface offset)) - (label (l))) - (+ (fixnum (fixed-args offset)) - (label (l dcl)))) - (entry Program) - (CaseLambdaExpr (le) - (- (case-lambda info cl ...)) - (+ (lambda info (local* ...) tlbody) => (lambda (local* ...) tlbody))) - (CaseLambdaClause (cl) - (- (clause (x* ...) (local* ...) mcp interface tlbody))) - (Tail (tl tlbody) - (+ (entry-point (x* ...) dcl mcp tlbody))) - (Effect (e ebody) - (- (mvset info (mdcl (maybe t0) t1 ...) (t* ...) ((x** ...) interface* l*) ...)) - (+ (do-rest fixed-args) - (mvset info (mdcl (maybe t0) t1 ...) (t* ...) ((x** ...) ...) ebody) - ; mventry-point and mverror-point can appear only within an mvset ebody - ; ideally, grammar would reflect this - (mventry-point (x* ...) l) - (mverror-point)))) - - (define exact-integer? - (lambda (x) - (and (integer? x) (exact? x)))) - - ; calling conventions are imposed; clauses no longer have formals (they are - ; now locals set by arguments from argument registers and frame); calls no - ; longer have arguments; case-lambda is responsible for dispatching to correct - ; clause, even when the game is being played - (define-language L13 - (terminals - (fixnum (max-fv offset)) - (fv (fv)) - (reg (reg)) - (var (x nfv cnfv var)) - (uvar (local)) - (effect-primitive (effect-prim)) - (pred-primitive (pred-prim)) - (value-primitive (value-prim)) - (immediate (imm fs)) - (exact-integer (lpm)) - (info (info)) - (maybe-label (mrvl)) - (label (l rpl)) - (source-object (src)) - (symbol (sym))) - (Program (prog) - (labels ([l* le*] ...) l) => (letrec ([l* le*] ...) (l))) - (CaseLambdaExpr (le) - (lambda info max-fv (local* ...) tlbody) => (lambda (local* ...) tlbody) - (hand-coded sym)) - (Lvalue (lvalue) - x - (mref x1 x2 imm)) - (Triv (t) - lvalue - (literal info) => info - (immediate imm) => imm - (label-ref l offset)) - (Rhs (rhs) - t - (alloc info t) => (alloc info t) - (inline info value-prim t* ...) => (inline info value-prim t* ...)) - (Pred (p pbody) - (inline info pred-prim t* ...) => (inline info pred-prim t* ...) - (true) - (false) - (if p0 p1 p2) - (seq e0 p1) - (goto l) - (mlabel p (l* p*) ...)) - (Effect (e ebody) - (overflow-check) - (overflood-check) - (fcallable-overflow-check) - (new-frame info rpl* ... rpl) - (return-point info rpl mrvl (cnfv* ...)) - (rp-header mrvl fs lpm) - (remove-frame info) - (restore-local-saves info) - (shift-arg reg imm info) - (set! lvalue rhs) - (inline info effect-prim t* ...) => (inline info effect-prim t* ...) - (nop) - (pariah) - (if p0 e1 e2) - (seq e0 e1) - (label l) - (goto l) - (tail tl) - (profile src) => (profile) - (check-live reg* ...)) - (Tail (tl tlbody) - (jump t (var* ...)) - (joto l (nfv* ...)) - (asm-return reg* ...) - (asm-c-return info reg* ...) - (if p0 tl1 tl2) - (seq e0 tl1) - (goto l))) - - (define-language L13.5 (extends L13) - (terminals - (- (symbol (sym)))) - (entry Program) - (CaseLambdaExpr (le) - (- (hand-coded sym)))) - - (define-language L14 (extends L13.5) - (entry Program) - (Rhs (rhs) - (- (alloc info t)))) - - (define-record-type block - (fields - (mutable label) - (mutable effect*) - (mutable src*) - (mutable pseudo-src) - (mutable in-link*) - (mutable flags) - (mutable fp-offset) - (mutable live-in) - (mutable depth) - (mutable loop-headers) - (mutable index) - (mutable weight)) - (nongenerative) - (protocol - (lambda (new) - (lambda () - (new #f '() '() #f '() (block-flags-mask) #f 'uninitialized 0 #f #f #f))))) - - (define-flag-field block flags - (pariah #b000001) - (seen #b000010) - (finished #b000100) - (return-point #b001000) - (repeater #b010000) - (loop-header #b100000)) - - (define-record-type live-info - (nongenerative) - (sealed #t) - (fields - (mutable live) - (mutable useless)) - (protocol - (lambda (new) - (case-lambda - [() (new 'uninitialized #f)] - [(live) (new live #f)])))) - - (module () - (record-writer (record-type-descriptor live-info) - (lambda (x p wr) - (if (eq? (live-info-live x) 'uninitialized) - (display-string "#" p) - (fprintf p "#" (live-info-live x)))))) - - (define-language L15a - (terminals - (var (x cnfv var)) - (reg (reg)) - (uvar (local)) - (effect-primitive (effect-prim)) - (pred-primitive (pred-prim)) - (value-primitive (value-prim)) - (immediate (imm fs)) - (exact-integer (lpm)) - (live-info (live-info)) - (info (info)) - (label (l rpl)) - (maybe-label (mrvl)) - (fixnum (max-fv offset)) - (block (block entry-block))) - (Program (pgm) - (labels ([l* le*] ...) l) => (letrec ([l* le*] ...) (l))) - (CaseLambdaExpr (le) - (lambda info max-fv (local* ...) (entry-block* ...) (block* ...)) => (lambda (local* ...) (entry-block* ...) (block* ...))) - (Dummy (dumdum) (dummy)) - (Lvalue (lvalue) - x - (mref x1 x2 imm)) - (Triv (t) - lvalue - (literal info) => info - (immediate imm) => imm - (label-ref l offset)) - (Rhs (rhs) - t - (inline info value-prim t* ...)) - (Pred (p) - (inline live-info info pred-prim t* ...)) - (Effect (e) - (overflow-check live-info) - (overflood-check live-info) - (fcallable-overflow-check live-info) - (return-point info rpl mrvl (cnfv* ...)) - (rp-header mrvl fs lpm) - (remove-frame live-info info) - (restore-local-saves live-info info) - (shift-arg live-info reg imm info) - (set! live-info lvalue rhs) - (inline live-info info effect-prim t* ...) - (check-live live-info reg* ...)) - (Tail (tl) - (goto l) - (jump live-info t (var* ...)) - (asm-return reg* ...) - (asm-c-return info reg* ...))) - - (define-language L15b (extends L15a) - (terminals - (- (var (x cnfv var)) - (reg (reg)) - (label (l rpl))) - (+ (var (x var)) - (label (l)))) - (Effect (e) - (- (remove-frame live-info info) - (restore-local-saves live-info info) - (return-point info rpl mrvl (cnfv* ...)) - (shift-arg live-info reg imm info) - (check-live live-info reg* ...)) - (+ (fp-offset live-info imm))) - (Tail (tl) - (- (jump live-info t (var* ...)) - (asm-return reg* ...) - (asm-c-return info reg* ...)) - (+ (jump live-info t) - (asm-return) - (asm-c-return info)))) - - (define ur? - (lambda (x) - (or (reg? x) (uvar? x)))) - - (define-language L15c (extends L15b) - (terminals - (- (var (x var))) - (+ (ur (x)))) - ; NB: base and index are really either regs or (mref %sfp %zero imm) - (Lvalue (lvalue) - (- (mref x1 x2 imm)) - (+ (mref lvalue1 lvalue2 imm))) - (Effect (e) - (- (fp-offset live-info imm)))) - - (define-language L15d (extends L15c) - (terminals - (- (pred-primitive (pred-prim)) - (value-primitive (value-prim)) - (effect-primitive (effect-prim))) - (+ (procedure (proc)) => $procedure-name)) - (entry Program) - (Lvalue (lvalue) - (- (mref lvalue1 lvalue2 imm)) - (+ (mref x1 x2 imm))) - (Rhs (rhs) - (- (inline info value-prim t* ...)) - (+ (asm info proc t* ...) => (asm proc t* ...))) - (Effect (e) - (- (inline live-info info effect-prim t* ...) - (overflow-check live-info) - (overflood-check live-info) - (fcallable-overflow-check live-info)) - (+ (asm info proc t* ...) => (asm proc t* ...) - (move-related x1 x2) - (overflow-check p e* ...))) - (Pred (p pbody) - (- (inline live-info info pred-prim t* ...)) - (+ (asm info proc t* ...) => (asm proc t* ...))) - (Tail (tl) - (- (jump live-info t)) - (+ (jump t)))) - - (define-language L15e (extends L15d) - (terminals - (- (ur (x))) - (+ (reg (x)))) - (entry Program) - (CaseLambdaExpr (le) - (- (lambda info max-fv (local* ...) (entry-block* ...) (block* ...))) - (+ (lambda info (entry-block* ...) (block* ...)) => (lambda (entry-block* ...) (block* ...)))) - (Effect (e) - (- (set! live-info lvalue rhs) - (move-related x1 x2)) - (+ (set! lvalue rhs)))) - - (define-language L16 (extends L15e) - (entry Program) - (Effect (e) - (- (overflow-check p e* ...)))) - - (meta-cond - [(not (eqv? (optimize-level) 3)) - (pretty-format 'define-language - '(alt - (_ var #f ('terminals #f x ...) #f (_ _ #f ...) ...) - (_ var ('extends x) #f ('definitions #f x ...) #f ('terminals #f x ...) #f (_ _ #f ...) ...) - (_ var #f ('definitions #f x ...) #f ('terminals #f x ...) #f (_ _ #f ...) ...) - (_ var ('extends x) #f ('terminals #f x ...)) - (_ var ('extends x) #f ('terminals #f x ...) #f (_ _ #f ...) ...) - (_ var ('extends x) #f (_ _ #f ...) ...))) - (pretty-format 'labels '(_ ([bracket x e] 0 ...) #f e ...)) - (pretty-format 'blocks '(_ #f [bracket (x ...) 0 e] ...))]) - - (primitive-handler-set! %keep-live - (lambda (info x) - (with-output-language (L15d Effect) - `(asm ,info ,(lambda (code*) code*))))) -) diff --git a/ta6ob/s/pdhtml.ss b/ta6ob/s/pdhtml.ss deleted file mode 100644 index 7b58384..0000000 --- a/ta6ob/s/pdhtml.ss +++ /dev/null @@ -1,1538 +0,0 @@ -;;; pdhtml.ss -;;; Copyright 1984-2017 Cisco Systems, Inc. -;;; -;;; Licensed under the Apache License, Version 2.0 (the "License"); -;;; you may not use this file except in compliance with the License. -;;; You may obtain a copy of the License at -;;; -;;; http://www.apache.org/licenses/LICENSE-2.0 -;;; -;;; Unless required by applicable law or agreed to in writing, software -;;; distributed under the License is distributed on an "AS IS" BASIS, -;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -;;; See the License for the specific language governing permissions and -;;; limitations under the License. - -;;; NOTES: -;;; - fixed bug in define-tags: moved (void) end of text ... to start -;;; -;;; - to change palette to use white background with colorized text: -;;; (profile-palette -;;; (vector-map -;;; (lambda (p) (cons "white" (car p))) -;;; (profile-palette))) - -;;; profile-dump-html suggestions from Oscar: -;;; -;;; We could probably build a table mapping source regions to procedure names -;;; in enough cases to actually be useful. If so, showing procedure name instead -;;; of line/char position would help the user get a high-level perspective on the -;;; profile results. Right now the user has to synthesize that perspective by -;;; remembering where each link led. -;;; -;;; Within the file view window, it would be nice to have a way to scan quickly -;;; through the hot spots within that file (we have some obscenely large source -;;; files at work). Perhaps you could reprise the profile spectrum horizontally -;;; in a short frame at the top of the window and rig it so that dragging, scroll -;;; wheel, or clicking on a color cycles through the regions tagged with that col> -;;; -;;; With a large range of profile counts to compress into a fairly small -;;; spectrum, it might be nice if there were a way to zoom into a range by -;;; clicking on the legend, either in the overview window or the file window. -;;; Reallocating the color map could be confusing with multiple windows open, -;;; but perhaps there's some javascript way to rig all the other colors to -;;; desaturate when you zoom into a range in one window. Perhaps intensity -;;; could be used to show the sub-ranges in varying shades of the main legend -;;; color. -;;; -;;; I notice that the profile annotations on the when expressions start at the te> -;;; expression rather than the start of the when. Yet the if expression annotati> -;;; starts at the beginning of the if expression and extends to the closing paren. -;;; Not sure if that made any sense, basically I'm trying to say that the "(when" -;;; itself (and closing paren) isn't colored the same as the test part. -;;; I don't remember exactly how we handled source annotations during wrapping and -;;; unwrapping, but it seems offhand that it might make sense to wrap the input -;;; source annotation around the transformer output so that the source info for t> -;;; when expression is transferred to the generated if expression. - -(begin -(let () - (include "types.ss") - (module (make-tracker tracker-profile-ct) - (define-record-type tracker - (nongenerative) - (fields profile-ct))) - (define-record-type cc - (nongenerative) - (fields (mutable cookie) (mutable total) (mutable current) (mutable preceding))) - (define-record-type (source-table $make-source-table $source-table?) - (nongenerative) - (sealed #t) - (opaque #t) - (fields ht) - (protocol - (lambda (new) - (lambda () - (define sfd-hash - (lambda (sfd) - (source-file-descriptor-crc sfd))) - (define sfd=? - (lambda (sfd1 sfd2) - (and (fx= (source-file-descriptor-crc sfd1) (source-file-descriptor-crc sfd2)) - (= (source-file-descriptor-length sfd1) (source-file-descriptor-length sfd2)) - (string=? (source-file-descriptor-name sfd1) (source-file-descriptor-name sfd2))))) - (new (make-hashtable sfd-hash sfd=?)))))) - (define *local-profile-trackers* '()) - (define op+ car) - (define op- cdr) - (define count+ (constant-case ptr-bits [(32) +] [(64) fx+])) - (define count- (constant-case ptr-bits [(32) -] [(64) fx-])) - (define count< (constant-case ptr-bits [(32) <] [(64) fx<])) - (define get-counter-list (foreign-procedure "(cs)s_profile_counters" () ptr)) - (define release-counters (foreign-procedure "(cs)s_profile_release_counters" () ptr)) - - (define rblock-count - (lambda (rblock) - (let sum ((op (rblock-op rblock))) - (if (profile-counter? op) - (profile-counter-count op) - ; using #3%fold-left in case the #2% versions are profiled - (#3%fold-left - (lambda (a op) (count- a (sum op))) - (#3%fold-left (lambda (a op) (count+ a (sum op))) 0 (op+ op)) - (op- op)))))) - - (define profile-counts - ; like profile-dump but returns ((count . (src ...)) ...) - (case-lambda - [() (profile-counts (get-counter-list))] - [(counter*) - ; disabling interrupts so we don't sum part of the counters for a block before - ; an interrupt and the remaining counters after the interrupt, which can lead - ; to inaccurate (and possibly negative) counts. we could disable interrupts just - ; around the body of rblock-count to shorten the windows during which interrupts - ; are disabled, but doing it here incurs less overhead - (with-interrupts-disabled - (fold-left - (lambda (r x) - (fold-left - (lambda (r rblock) - (cons (cons (rblock-count rblock) (rblock-srecs rblock)) r)) - r (cdr x))) - '() counter*))])) - - (define (snapshot who uncleared-count* cleared-count*) - (lambda (tracker) - (define cookie (cons 'vanilla 'wafer)) - ; set current corresponding to each src to a total of its counts - (let ([incr-current - (lambda (count.src*) - (let ([count (car count.src*)]) - (for-each - (lambda (src) - (let ([a ($source-table-cell (tracker-profile-ct tracker) src #f)]) - (when (count< count 0) (errorf who "negative profile count ~s for ~s" count src)) - (let ([cc (cdr a)]) - (if cc - (if (eq? (cc-cookie cc) cookie) - (cc-current-set! cc (count+ (cc-current cc) count)) - (begin - (cc-cookie-set! cc cookie) - (cc-current-set! cc count))) - (set-cdr! a (make-cc cookie 0 count 0)))))) - (cdr count.src*))))]) - (for-each incr-current uncleared-count*) - (for-each incr-current cleared-count*)) - ; then increment total of each affected cc by the delta between current and preceding - (source-table-for-each - (lambda (src cc) - (when (eq? (cc-cookie cc) cookie) - (let ([current (cc-current cc)]) - (let ([delta (count- current (cc-preceding cc))]) - (unless (eqv? delta 0) - (when (count< delta 0) (errorf who "total profile count for ~s dropped from ~s to ~s" src (cc-preceding cc) current)) - (cc-total-set! cc (count+ (cc-total cc) delta)) - (cc-preceding-set! cc current)))))) - (tracker-profile-ct tracker)) - ; then reduce preceding by cleared counts - (for-each - (lambda (count.src*) - (let ([count (car count.src*)]) - (for-each - (lambda (src) - (let ([a ($source-table-cell (tracker-profile-ct tracker) src #f)]) - (let ([cc (cdr a)]) - (if cc - (cc-preceding-set! cc (count- (cc-preceding cc) count)) - (set-cdr! a (make-cc cookie 0 0 0)))))) - (cdr count.src*)))) - cleared-count*))) - - (define adjust-trackers! - (lambda (who uncleared-counter* cleared-counter*) - (let ([local-tracker* *local-profile-trackers*]) - (unless (null? local-tracker*) - (let ([uncleared-count* (profile-counts uncleared-counter*)] - [cleared-count* (profile-counts cleared-counter*)]) - (let ([snapshot (snapshot who uncleared-count* cleared-count*)]) - (for-each snapshot local-tracker*))))))) - - (define $source-table-contains? - (lambda (st src) - (let ([src-ht (hashtable-ref (source-table-ht st) (source-sfd src) #f)]) - (and src-ht (hashtable-contains? src-ht src))))) - - (define $source-table-ref - (lambda (st src default) - (let ([src-ht (hashtable-ref (source-table-ht st) (source-sfd src) #f)]) - (if src-ht (hashtable-ref src-ht src default) default)))) - - (define $source-table-cell - (lambda (st src default) - (define same-sfd-src-hash - (lambda (src) - (source-bfp src))) - (define same-sfd-src=? - (lambda (src1 src2) - (and (= (source-bfp src1) (source-bfp src2)) - (= (source-efp src1) (source-efp src2))))) - (let ([src-ht (let ([a (hashtable-cell (source-table-ht st) (source-sfd src) #f)]) - (or (cdr a) - (let ([src-ht (make-hashtable same-sfd-src-hash same-sfd-src=?)]) - (set-cdr! a src-ht) - src-ht)))]) - (hashtable-cell src-ht src default)))) - - (define $source-table-delete! - (lambda (st src) - (let ([ht (source-table-ht st)] [sfd (source-sfd src)]) - (let ([src-ht (hashtable-ref ht sfd #f)]) - (when src-ht - (hashtable-delete! src-ht src) - (when (fx= (hashtable-size src-ht) 0) - (hashtable-delete! ht sfd))))))) - - (define source-table-for-each - (lambda (p st) - (vector-for-each - (lambda (src-ht) - (let-values ([(vsrc vcount) (hashtable-entries src-ht)]) - (vector-for-each p vsrc vcount))) - (hashtable-values (source-table-ht st))))) - - (set-who! profile-clear - (lambda () - (define clear-links - (lambda (op) - (if (profile-counter? op) - (profile-counter-count-set! op 0) - (begin - (for-each clear-links (op+ op)) - (for-each clear-links (op- op)))))) - (let ([counter* (get-counter-list)]) - (adjust-trackers! who '() counter*) - (for-each - (lambda (x) - (for-each - (lambda (node) (clear-links (rblock-op node))) - (cdr x))) - counter*)))) - - (set-who! profile-release-counters - (lambda () - ; release-counters prunes out (and hands back) the released counters - (let* ([dropped-counter* (release-counters)] - [kept-counter* (get-counter-list)]) - (adjust-trackers! who kept-counter* dropped-counter*)))) - - (set-who! profile-dump - ; like profile-counts but returns ((src . count) ...), which requires more allocation - ; profile-dump could use profile-counts but that would require even more allocation - (lambda () - ; could disable interrupts just around each call to rblock-count, but doing it here incurs less overhead - (with-interrupts-disabled - (fold-left - (lambda (r x) - (fold-left - (lambda (r rblock) - (let ([count (rblock-count rblock)]) - (fold-left - (lambda (r src) - (cons (cons src count) r)) - r (rblock-srecs rblock)))) - r (cdr x))) - '() (get-counter-list))))) - - (set-who! make-source-table - (lambda () - ($make-source-table))) - - (set-who! source-table? - (lambda (x) - ($source-table? x))) - - (set-who! source-table-size - (lambda (st) - (unless ($source-table? st) ($oops who "~s is not a source table" st)) - (let ([vsrc-ht (hashtable-values (source-table-ht st))]) - (let ([n (vector-length vsrc-ht)]) - (do ([i 0 (fx+ i 1)] [size 0 (fx+ size (hashtable-size (vector-ref vsrc-ht i)))]) - ((fx= i n) size)))))) - - (set-who! source-table-contains? - (lambda (st src) - (unless ($source-table? st) ($oops who "~s is not a source table" st)) - (unless (source? src) ($oops who "~s is not a source object" src)) - ($source-table-contains? st src))) - - (set-who! source-table-ref - (lambda (st src default) - (unless ($source-table? st) ($oops who "~s is not a source table" st)) - (unless (source? src) ($oops who "~s is not a source object" src)) - ($source-table-ref st src default))) - - (set-who! source-table-set! - (lambda (st src val) - (unless ($source-table? st) ($oops who "~s is not a source table" st)) - (unless (source? src) ($oops who "~s is not a source object" src)) - (set-cdr! ($source-table-cell st src #f) val))) - - (set-who! source-table-delete! - (lambda (st src) - (unless ($source-table? st) ($oops who "~s is not a source table" st)) - (unless (source? src) ($oops who "~s is not a source object" src)) - ($source-table-delete! st src))) - - (set-who! source-table-cell - (lambda (st src default) - (unless ($source-table? st) ($oops who "~s is not a source table" st)) - (unless (source? src) ($oops who "~s is not a source object" src)) - ($source-table-cell st src default))) - - (set-who! source-table-dump - (lambda (st) - (unless ($source-table? st) ($oops who "~s is not a source table" st)) - (let* ([vsrc-ht (hashtable-values (source-table-ht st))] - [n (vector-length vsrc-ht)]) - (do ([i 0 (fx+ i 1)] - [dumpit* '() - (let-values ([(vsrc vcount) (hashtable-entries (vector-ref vsrc-ht i))]) - (let ([n (vector-length vsrc)]) - (do ([i 0 (fx+ i 1)] - [dumpit* dumpit* - (cons (cons (vector-ref vsrc i) (vector-ref vcount i)) dumpit*)]) - ((fx= i n) dumpit*))))]) - ((fx= i n) dumpit*))))) - - (set-who! put-source-table - (lambda (op st) - (unless (and (output-port? op) (textual-port? op)) ($oops who "~s is not a textual output port" op)) - (unless ($source-table? st) ($oops who "~s is not a source table" st)) - (fprintf op "(source-table") - (let-values ([(vsfd vsrc-ht) (hashtable-entries (source-table-ht st))]) - (vector-for-each - (lambda (sfd src-ht) - (let-values ([(vsrc vval) (hashtable-entries src-ht)]) - (let ([n (vector-length vsrc)]) - (unless (fx= n 0) - (fprintf op "\n (file ~s ~s" - (source-file-descriptor-name sfd) - (source-file-descriptor-checksum sfd)) - (let ([v (vector-sort (lambda (x1 x2) (< (vector-ref x1 0) (vector-ref x2 0))) - (vector-map (lambda (src val) (vector (source-bfp src) (source-efp src) val)) vsrc vval))]) - (let loop ([i 0] [last-bfp 0]) - (unless (fx= i n) - (let ([x (vector-ref v i)]) - (let ([bfp (vector-ref x 0)] [efp (vector-ref x 1)] [val (vector-ref x 2)]) - (let ([offset (- bfp last-bfp)] [len (- efp bfp)]) - (fprintf op " (~s ~s ~s)" offset len val)) - (loop (fx+ i 1) bfp)))))) - (fprintf op ")"))))) - vsfd vsrc-ht)) - (fprintf op ")\n"))) - - (set-who! get-source-table! - (rec get-source-table! - (case-lambda - [(ip st) (get-source-table! ip st #f)] - [(ip st combine) - (define (nnint? x) (and (integer? x) (exact? x) (nonnegative? x))) - (define (token-oops what bfp) - (if bfp - ($oops who "expected ~a at file position ~s of ~s" what bfp ip) - ($oops who "malformed source table reading from ~a" ip))) - (define (next-token expected-type expected-value? what) - (let-values ([(type val bfp efp) (read-token ip)]) - (unless (and (eq? type expected-type) (expected-value? val)) (token-oops what bfp)) - val)) - (unless (and (input-port? ip) (textual-port? ip)) ($oops who "~s is not a textual input port" ip)) - (unless ($source-table? st) ($oops who "~s is not a source table" st)) - (unless (or (not combine) (procedure? combine)) ($oops who "~s is not a procedure" combine)) - (next-token 'lparen not "open parenthesis") - (next-token 'atomic (lambda (x) (eq? x 'source-table)) "identifier 'source-table'") - (let file-loop () - (let-values ([(type val bfp efp) (read-token ip)]) - (unless (eq? type 'rparen) - (unless (eq? type 'lparen) (token-oops "open parenthesis" bfp)) - (next-token 'atomic (lambda (x) (eq? x 'file)) "identifier 'file'") - (let* ([path (next-token 'atomic string? "string")] - [checksum (next-token 'atomic nnint? "checksum")]) - (let ([sfd (#%source-file-descriptor path checksum)]) - (let entry-loop ([last-bfp 0]) - (let-values ([(type val bfp efp) (read-token ip)]) - (unless (eq? type 'rparen) - (unless (eq? type 'lparen) (token-oops "open parenthesis" bfp)) - (let* ([bfp (+ last-bfp (next-token 'atomic nnint? "file position"))] - [efp (+ bfp (next-token 'atomic nnint? "file position"))] - [val (get-datum ip)]) - (next-token 'rparen not "close parenthesis") - (let ([a ($source-table-cell st (make-source-object sfd bfp efp) #f)]) - (set-cdr! a - (if (and (cdr a) combine) - (combine (cdr a) val) - val))) - (entry-loop bfp))))))) - (file-loop))))]))) - - (set-who! with-profile-tracker - (rec with-profile-tracker - (case-lambda - [(thunk) (with-profile-tracker #f thunk)] - [(include-existing-counts? thunk) - (define extract-covered-entries - (lambda (profile-ct) - (let ([covered-ct ($make-source-table)]) - (source-table-for-each - (lambda (src cc) - (let ([count (cc-total cc)]) - (unless (eqv? count 0) - ($source-table-cell covered-ct src count)))) - profile-ct) - covered-ct))) - (unless (procedure? thunk) ($oops who "~s is not a procedure" thunk)) - (let* ([profile-ct ($make-source-table)] - [tracker (make-tracker profile-ct)]) - (unless include-existing-counts? - ; set preceding corresponding to each src to a total of its dumpit counts - ; set total to zero, since we don't want to count anything from before - (for-each - (lambda (count.src*) - (let ([count (car count.src*)]) - (for-each - (lambda (src) - (let ([a ($source-table-cell profile-ct src #f)]) - (let ([cc (cdr a)]) - (if cc - (cc-preceding-set! cc (count+ (cc-preceding cc) count)) - (set-cdr! a (make-cc #f 0 0 count)))))) - (cdr count.src*)))) - (profile-counts))) - ; register for possible adjustment by profile-clear and profile-release-counters - (let-values ([v* (fluid-let ([*local-profile-trackers* (cons tracker *local-profile-trackers*)]) (thunk))]) - ; increment the recorded counts by the now current counts. - ((snapshot who (profile-counts) '()) tracker) - (apply values (extract-covered-entries profile-ct) v*)))])))) - -(let () - (include "types.ss") - - (define check-dump - (lambda (who x) - (unless (and (list? x) - (andmap (lambda (x) - (and (pair? x) - (source-object? (car x)) - (let ([x (cdr x)]) - (and (integer? x) (exact? x))))) - x)) - ($oops who "invalid dump ~s" x)))) - - (define-record-type filedata - (fields - (immutable sfd) - (immutable ip) - (mutable entry*) - ; remaining fields are ignored by profile-dump-list - (mutable max-count) - (mutable ci) - (mutable htmlpath) - (mutable htmlfn) - (mutable winid)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (sfd ip) - (new sfd ip '() #f #f #f #f #f))))) - - (define-record-type entrydata - (fields - (immutable fdata) - (immutable bfp) - (immutable efp) - (mutable count) - (mutable line) - (mutable char) - ; ci is ignored by profile-dump-list - (mutable ci)) - (nongenerative) - (sealed #t) - (protocol - (lambda (new) - (lambda (fdata bfp efp count) - (new fdata bfp efp count #f #f #f))))) - - (define (gather-filedata who warn? dumpit*) - ; returns list of fdata records, each holding a list of entries - ; the entries are sorted based on their (unique) bfps - (let ([fdata-ht (make-hashtable - (lambda (x) (source-file-descriptor-crc x)) - (lambda (x y) - ; there's no way to make this foolproof, so we identify paths with - ; same crc, length, and last component. this can cause problems - ; only if two copies of the same file are loaded and used. - (or (eq? x y) - (and (= (source-file-descriptor-crc x) - (source-file-descriptor-crc y)) - (= (source-file-descriptor-length x) - (source-file-descriptor-length y)) - (string=? - (path-last (source-file-descriptor-name x)) - (path-last (source-file-descriptor-name y)))))))]) - (define (open-source sfd) - (cond - [(hashtable-ref fdata-ht sfd #f)] - [($open-source-file sfd) => - (lambda (ip) - (let ([fdata (make-filedata sfd ip)]) - (hashtable-set! fdata-ht sfd fdata) - fdata))] - [else - (when warn? - (warningf who - "unmodified source file ~s not found in source directories" - (source-file-descriptor-name sfd))) - (let ([fdata (make-filedata sfd #f)]) - (hashtable-set! fdata-ht sfd fdata) - fdata)])) - (for-each - (lambda (dumpit) - (let ([source (car dumpit)]) - (assert (source? source)) - (let ([bfp (source-bfp source)]) - (when (>= bfp 0) ; weed out block-profiling entries, whose bfps are negative - (let ([fdata (open-source (source-sfd source))]) - (filedata-entry*-set! fdata - (cons (make-entrydata fdata bfp (source-efp source) (cdr dumpit)) - (filedata-entry* fdata)))))))) - dumpit*) - (let ([fdatav (hashtable-values fdata-ht)]) - (vector-for-each - (lambda (fdata) - (let ([entry* (sort (lambda (x y) - (or (> (entrydata-bfp x) (entrydata-bfp y)) - (and (= (entrydata-bfp x) (entrydata-bfp y)) - (< (entrydata-efp x) (entrydata-efp y))))) - (filedata-entry* fdata))]) - #;(assert (not (null? entry*))) - (let loop ([entry (car entry*)] [entry* (cdr entry*)] [new-entry* '()]) - (if (null? entry*) - (filedata-entry*-set! fdata (cons entry new-entry*)) - (if (and (= (entrydata-bfp (car entry*)) (entrydata-bfp entry)) - (= (entrydata-efp (car entry*)) (entrydata-efp entry))) - (begin - (entrydata-count-set! entry - (+ (entrydata-count entry) - (entrydata-count (car entry*)))) - (loop entry (cdr entry*) new-entry*)) - (loop (car entry*) (cdr entry*) (cons entry new-entry*))))))) - fdatav) - (vector->list fdatav)))) - - (let () - (define (scan-file fdata) - (let ([ip (filedata-ip fdata)] [line 1] [char 1]) - (define (read-until bfp next) - (let loop ([bfp bfp]) - (unless (= bfp next) - (cond - [(eqv? (read-char ip) #\newline) - (set! line (+ line 1)) - (set! char 1)] - [else (set! char (+ char 1))]) - (loop (+ bfp 1))))) - (let ([entry* (filedata-entry* fdata)]) ; already sorted by gather-filedata - (let f ([bfp 0] [entry* entry*]) - (unless (null? entry*) - (let ([entry (car entry*)] [entry* (cdr entry*)]) - (let ([next (entrydata-bfp entry)]) - (read-until bfp next) - (entrydata-line-set! entry line) - (entrydata-char-set! entry char) - (f next entry*)))))))) - - (set-who! profile-dump-list - ; return list of lists of: - ; - count - ; - path ; current if line and char are not #f - ; - bfp - ; - efp - ; - line ; may be #f - ; - char ; may be #f - (rec profile-dump-list - (case-lambda - [() (profile-dump-list #t)] - [(warn?) (profile-dump-list warn? (profile-dump))] - [(warn? dumpit*) - (check-dump who dumpit*) - (let ([fdata* (gather-filedata who warn? dumpit*)]) - (for-each scan-file (remp (lambda (x) (not (filedata-ip x))) fdata*)) - (let ([ls (map (lambda (entry) - (let ([fdata (entrydata-fdata entry)]) - (list - (entrydata-count entry) - (cond - [(filedata-ip fdata) => port-name] - [else (source-file-descriptor-name - (filedata-sfd fdata))]) - (entrydata-bfp entry) - (entrydata-efp entry) - (entrydata-line entry) - (entrydata-char entry)))) - (sort - (lambda (x y) (> (entrydata-count x) (entrydata-count y))) - (apply append (map filedata-entry* fdata*))))]) - (for-each - (lambda (fdata) (cond [(filedata-ip fdata) => close-input-port])) - fdata*) - ls))])))) - - (let () - (define-record-type profilit - (nongenerative #{profilit iw9f7z5ovg4jjetsvw5m0-2}) - (sealed #t) - (fields sfd bfp efp weight)) - (define make-profile-database - (lambda () - (make-hashtable - source-file-descriptor-crc - (lambda (x y) - (or (eq? x y) - (and (= (source-file-descriptor-crc x) - (source-file-descriptor-crc y)) - (= (source-file-descriptor-length x) - (source-file-descriptor-length y)) - (string=? - (path-last (source-file-descriptor-name x)) - (path-last (source-file-descriptor-name y))))))))) - - (define profile-database #f) - (define profile-source-data? #f) - (define profile-block-data? #f) - (define update-sfd! - (lambda (cell sfd) - ; if the recorded sfd is the same but not eq, it's likely from an earlier session. - ; overwrite so remaining hashtable equality-procedure checks are more likely to - ; succeed at the eq? check - (unless (eq? (car cell) sfd) - (set-car! cell sfd)))) - (set-who! profile-clear-database - (lambda () - (set! profile-database #f))) - (set-who! profile-dump-data - (rec profile-dump-data - (case-lambda - [(ofn) (profile-dump-data ofn (profile-dump))] - [(ofn dumpit*) - (check-dump who dumpit*) - (let ([op ($open-file-output-port who ofn (file-options replace))]) - (on-reset (delete-file ofn #f) - (on-reset (close-port op) - (let* ([dump dumpit*] [max-count (inexact (fold-left max 1 (map cdr dump)))]) - (for-each - (lambda (dumpit) - (let ([source (car dumpit)] [count (cdr dumpit)]) - (fasl-write - (make-profilit (source-sfd source) (source-bfp source) (source-efp source) - ; compute weight as % of max count - (fl/ (inexact count) max-count)) - op))) - dump))) - (close-port op)))]))) - (set! $profile-source-data? (lambda () profile-source-data?)) - (set! $profile-block-data? (lambda () profile-block-data?)) - (set-who! profile-load-data - (lambda ifn* - (define populate! - (lambda (x) - (unless (profilit? x) ($oops who "invalid profile data element ~s" x)) - (unless profile-database (set! profile-database (make-profile-database))) - (let ([ht (let* ([sfd (profilit-sfd x)] - [cell (hashtable-cell profile-database sfd #f)]) - (update-sfd! cell sfd) - (or (cdr cell) - (let ([ht (make-hashtable values =)]) - (set-cdr! cell ht) - ht)))]) - ; each ht entry is an alist mapping efp -> (weight . n) where n is - ; the number of contributing entries so far for this sfd, bfp, and efp. - ; n is used to compute the average weight of the contributing entries. - (let ([bfp.alist (hashtable-cell ht (profilit-bfp x) '())]) - (cond - [(assv (profilit-efp x) (cdr bfp.alist)) => - (lambda (a) - (let ([weight.n (cdr a)]) - (let ([weight (car weight.n)] [n (cdr weight.n)]) - (let ([new-n (fl+ n 1.0)]) - (set-car! weight.n (fl/ (fl+ (* weight n) (profilit-weight x)) new-n)) - (set-cdr! weight.n new-n)))))] - [else (set-cdr! bfp.alist (cons (cons* (profilit-efp x) (profilit-weight x) 1.0) (cdr bfp.alist)))]))) - (if (fxnegative? (profilit-bfp x)) - (set! profile-block-data? #t) - (set! profile-source-data? #t)))) - (define (load-file ifn) - (let ([ip ($open-file-input-port who ifn)]) - (on-reset (close-port ip) - (let f () - (let ([x (fasl-read ip)]) - (unless (eof-object? x) - (with-tc-mutex (populate! x)) - (f))))) - (close-port ip))) - (for-each - (lambda (ifn) - (unless (string? ifn) ($oops who "~s is not a string" ifn))) - ifn*) - (for-each load-file ifn*))) - (set! $profile-show-database - (lambda () - (when profile-database - (let-values ([(sfd* ht*) (hashtable-entries profile-database)]) - (vector-for-each - (lambda (sfd ht) - (printf "~a:\n" (source-file-descriptor-name sfd)) - (let-values ([(bfp* alist*) (hashtable-entries ht)]) - (vector-for-each - (lambda (bfp alist) - (for-each - (lambda (a) (printf " ~s, ~s: ~s\n" bfp (car a) (cadr a))) - alist)) - bfp* alist*))) - sfd* ht*))))) - (set! profile-query-weight - (lambda (x) - (define src->weight - (lambda (src) - (cond - [(and profile-database - (let* ([sfd (source-object-sfd src)] - [ht (hashtable-ref profile-database sfd #f)]) - (and ht - (begin - ; could do just one lookup if we had a nondestructive variant of - ; hashtable-cell to call above - (update-sfd! (hashtable-cell profile-database sfd #f) sfd) - ht)))) => - (lambda (ht) - (let ([alist (hashtable-ref ht (source-object-bfp src) '())]) - (cond - [(assv (source-object-efp src) alist) => cadr] - [(and (fxnegative? (source-object-bfp src)) (not (null? alist))) - ($oops #f "block-profiling info is out-of-date for ~s" - (source-file-descriptor-name (source-object-sfd src)))] - ; no info for given bfp, efp...assume dead code and return 0 - [else 0.0])))] - ; no info for given sfd...assume not profiled and return #f - [else #f]))) - (if (source? x) - (src->weight x) - (let ([x (syntax->annotation x)]) - (if (annotation? x) - (src->weight (annotation-source x)) - #f)))))) - - (let () - ;;; The following copyright notice goes with the %html module. - - ;;; Copyright (c) 2005 R. Kent Dybvig - - ;;; Permission is hereby granted, free of charge, to any person obtaining a - ;;; copy of this software and associated documentation files (the "Software"), - ;;; to deal in the Software without restriction, including without limitation - ;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, - ;;; and/or sell copies of the Software, and to permit persons to whom the - ;;; Software is furnished to do so, subject to the following conditions: - - ;;; The above copyright notice and this permission notice shall be included in - ;;; all copies or substantial portions of the Software. - - ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - ;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - ;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - ;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - ;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - ;;; DEALINGS IN THE SOFTWARE. - - (module %html (( <*> attribute $tag) - ( <*> attribute $tag) - ( <*> attribute $tag) - (