123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663 |
- RANDOM NOTES ON CSL/CCL
- =======================
- The code tries to be in fairly conservative C, but in quite a lot
- of places it depends on "the spirit of C" rather than the letter of
- the language standards.
- "machine.h" contains a catalogue of systems and compilers that the
- code has AT SOME STAGE been at least tested once on. At present the
- most tested configurations are
- Windows, Watcom C 11.5
- Linux x86, gcc
- and other cases may well have glitches remaining. But I hope that the long
- list of tested cases will give encouragement that the code is respectably
- portable. Only the Windows version (using The Microsoft Foundation Classes)
- has a currently-supported windowed interface: other versions use a command-
- line style. Both Mac and X have at times experimenented with the "StdWin"
- application framework but the code here does not guarantee to work with it
- still or well.
- I have adopted an indentation and code layout style that I like. I am aware
- that it is not the default one supported my emacs etc, but I have been using
- it for a long while and feel very set in my ways.
- This Lisp uses an agressive garbage collector that MUST be able to identify
- all root pointers reliably. C local variables are not marked by the GC, and
- because the GC can relocate things a reference held in a simple C variable
- is NOT SAFE across anything that could cause a GC. The macros push() and
- pop() place data on a Lisp-safe stack. The coding conventions needed to make
- GC safe are ones that take a significant time to get used to. They are not
- coder-friendly. If you breach them then the code may work most of the time
- but fail later in a messy way. I can only say "you have been warned"!
- This Lisp needs to control error recovery and general unwinding. Thus any
- function call that could possibly fail MUST be followed by a test to
- see if it did. In some cases this will need to do pop() operations (which are
- NOT automatically balanced across procedure calls: the programmer has to
- take full responsibility for matchiing push and pops). See the code for
- examples of what is needed. Again this is not coder-friendly and errors in
- applying the conventions can have delayed and unpleasant effect. Again "you
- have been warned"
- Common Lisp supports functions that return multiple values. Thus the normal
- simple case MUST use the onevalue() macro to indicate that what is returned
- is a singleton. Failure to do this can mess up error recovery or the
- garbage collector.
- The above three issues lead to significantly ugly and delicate code. They
- are easy for somebody whos is not neurotic enough to overlook. The
- trouble that they can lead to will often be deferred, only showing up
- occasionally on garbage collection or when recovering from an unrelated
- exception. This situation where errors can go undetected for a long while
- makes the need for care over these issues especially high priority!
- For several platforms it seems to be a really good thing to be able to
- respond well to asynchronous events. These may be "^C", or mouse clicks.
- Especially with windowed systems some form of threading would be very very
- helpful. This is hard wrt portability. Thus for essentially all systems I
- use the idea of a "tick stream" of more or less regular events that can
- be used to activate polling etc. Having tried genuine timer-based systems and
- having had a LOT of trouble with them I mostly use a software count-down
- scheme under the guard SOFTWARE_TICKS. If you feel tempted to discard this
- in favour of real threads or of nothing then consider the issues of back-
- porting to (eg) the Mac, or DOS where you must poll before even ^C is
- noticed. I do not want this code to lose portability, please!
- The basic data representation here is that small integers (and characters)
- are represented as value types, with some of the low 3 bits used as tags.
- Cons cells, vectors, big-numbers etc are handled by reference. By arranging
- that all items are stored aligne dto an 8-byte boundary the low 3 bits
- in a pointer are available for use as tags. More details can be seen in
- "tags.h". The most significant bit in a pointer is used for garbage
- collection, so heap memory must all be allocated in one half of the
- machine'e address space (it does not matter which!).
- The Lisp system here was designed for delivery of code that had already
- been developed and was basically working. It was not designed as a
- development environment. This means that in some respects it is
- inflexible! For instance there is a Lisp to C compiler, but it is
- configured so that the generated C is statically linked into the Lisp.
- The Lisp does not have very clever windowed interfaces, browsers etc.
- The Lisp compiler has its master version coded in RLISP (an Algol-like
- surface syntax for Lisp, popularised by the REDUCE algebra system). A
- yacc-based parser can translate this into raw Lisp, but enhancements would
- be better made to the RLISP version.
- I leave a notation that sort-of looks like an attempt to nest comments
- in places in the code where I know there are issues that have not been
- fully resolved. Eg comments such as
- /* /* This is not yet fully up to Common Lisp specification */
- etc etc. I do this because I can then make (some) C compilers generate
- warnings that remind me of these worries. Ideally I would fix them all! Or
- ideally C would have been specified with a #warn as well as and #error
- preprocessor directive!
- The notation "/* Signature ... */" present towards the top of each file
- is maintained using a utility called "filesign". It provides a checksum
- on the file, which I find much more reliable as a way of confirming
- versions than date-stamps, especially when files are copied between
- a number of different machines, perhaps in different time-zones.
- [more random comments follow...]
- double-execute() and undouble-execute() are like trace() and untrace() but
- cause the nominated functions to double their costs. Only at first actually
- does anything for functions with fixed numbers of args.
- PRESERVE optional args. First specifies a restart function
- to be called, the second is a banner to display when the image is reloaded.
- Reduce now uses this mechanism to gets its banner displayed. Third arg can be
- stuff to pass to the restart function - passing is via a text-string interface
- so it is a bit delicate!
- Lexical closures supported in the bytecode compiler (for variable reference
- but not GO or RETURN-FROM) and 3 new opcodes (closure, loadlex, storelex)
- introduced in bytes1.c to support same.
- By default the MSB of pointers is now determined at run time (rather than
- being a manifest value compiled into the code).
- Support for calls to functions with large numbers of arguments is
- improved. In particular in Common Lisp mode it is possible to have
- more than 50 args.
- Line-length overflow checking for printing of big numbers implemented.
- binary printing for numbers, and case fold up as well as down, supported.
- -------------------------------------------------------------------------------
- DATA REPRESENTATION
- ===================
- All objects in CSL are represented by 32-bit words(*), and each object in
- memory is aligned at an 8-byte boundary. The bottom 3 bits of a word
- aare used as tags, and indicate how the rest of the word should be
- interpreted. In some cases the rest of the word is just direct information
- (eg small integers are handled this way) and then the 0x8-bit is used by
- the garbage collecter. In other cases the 32-bit word contains the address
- in memory of some object, and in that case its most significant bit is
- reserved for use by the garbage collector. Thus all valid addresses must have
- the same sign (but this can be either + or -). Many objects in memory have
- a header word at their start that indicates their length and gives more
- details about their type. The encoding of object lengths means that the
- largest possible single object in CSL would be 4 Mbytes long. Also CSL
- memory is allocated in chunks (typically 256 Kbytes) and that puts another,
- usually more severe, limit on maximum object size. This may matter for
- arrays and bignums.
- (*) well on some machines they may be 64-bits but not much changes!
- The coding in the low bits of a word is as follows:
- x x x | x 0 0 0 cons cell (and NIL in Common Lisp mode)
- x x x | G 0 0 1 28-bit integer (G = garbage collector bit)
- x x x | G 0 1 0 characters, vec-hdrs, other oddities (immediate)
- x x x | G 0 1 1 28-bit short float if Common Lisp mode
- x x x | x 1 0 0 a symbol
- x x x | x 1 0 1 bignum. {rational number, complex number}
- x x x | x 1 1 0 Lisp vector (includes strings etc)
- x x x | x 1 1 1 pointer to boxed floating point number
- Pointers reserve the 0x80000000L bit for the garbage collector,
- assuming that all addresses are in the same half of the space. This
- of course is a slightly dodgy assumption that may be false on some
- computers. On 64-bit machines it is again the top bit that is used by
- the GC.
- Header words in the vector heap
- If the bottom 3 bits of a word are 010 (TAG_ODDS) the word is
- treated as immediate data. In that case the 1000 bit (GC_BIT_I)
- is kept free for use as a mark bit. The next bits up classify the
- object:
- | x x 0 0 | * 0 1 0 valid immediate date in heap
- but can also be used as vector headers
- | x x 0 1 | * 0 1 0 symbol headers
- | x x 1 0 | * 0 1 0 number headers
- | x x 1 1 | * 0 1 0 vector headers
- Data that could be in the heap or on the stack decodes further:
- x x | 0 0 0 0 | * 0 1 0 character
- x x | 0 1 0 0 | * 0 1 0 handle/offset to BPS page
- x x | 1 0 0 0 | * 0 1 0 [handle/offset to literal vector]
- x x | 1 1 0 0 | * 0 1 0 special marker (SPID) left on stack
- to help interpreter
- The remaining 24 bits of the word are available for data. The BPS and
- literal vector handles in this case are for a segmented memory
- implementation, and the 24 bit address has its top 10 bits identifying
- a page number, then 14 bits giving a WORD offset into the associated
- page, which can thus be up to 64 Kbytes large. Or more depending on
- PAGE_BITS. Literal vectors done this way are not used at present.
- For Standard Lisp only 8 bits of character information is needed - the
- remaining bits are there to support font etc information in a Common
- Lisp world.
- . . . . | g f 0 1 | * 0 1 0 symbol header
- g global variable
- f fluid (special) variable
- The remaining bits in the word are used as follows
- 00000100 symbol names a special form
- 00000200 symbol has a definition as a macro
- 00000400 an unprinted gensym (so print-name is not complete yet)
- 00000800 has a definition in C from the C-coded kernel
- 00001000 just carries a code-pointer (codep test)
- 00002000 any gensym, printed or not
- 000fc000 fastget code in this is used as a p-list indicator
- 00100000 traced
- 00200000 is external in its home package
- ffc00000 reachability in first 10 packages!!!
- The remaining header words hold the length (in bytes) of the object
- (including the length of the header word) in the upper 22 bits of the
- word. This puts a limit of 4 Mbytes on the largest possible single
- object in this Lisp.
- 0 0 | 0 0 1 0 | * 0 1 0 bignum header word
- 0 0 | 0 1 1 0 | * 0 1 0 ratnum
- 0 0 | 1 0 1 0 | * 0 1 0 complex number
- 0 0 | 1 1 1 0 | * 0 1 0 NOT USED (non-float number)
- 0 1 | 0 0 1 0 | * 0 1 0 single float
- 0 1 | 0 1 1 0 | * 0 1 0 double float
- 0 1 | 1 0 1 0 | * 0 1 0 long float
- 0 1 | 1 1 1 0 | * 0 1 0 NOT USED (floating number)
- Note that headers for numbers are 0x|xx10|x010 and the 0x100 bit flags
- floating point cases
- n n | n 0 1 1 | * 0 1 0 bitvector with nnn bits in last byte
- 0 0 | 0 1 1 1 | * 0 1 0 string
- 0 0 | 1 0 1 1 | * 0 1 0 (bitvector)
- 0 0 | 1 1 1 1 | * 0 1 0 simple vector
- 0 1 | 0 0 1 1 | * 0 1 0 (bitvector)
- 0 1 | 0 1 1 1 | * 0 1 0 BPS
- 0 1 | 1 0 1 1 | * 0 1 0 (bitvector)
- 0 1 | 1 1 1 1 | * 0 1 0 hash table
- 1 0 | 0 0 1 1 | * 0 1 0 (bitvector)
- 1 0 | 0 1 1 1 | * 0 1 0 SPARE contains binary data
- 1 0 | 1 0 1 1 | * 0 1 0 (bitvector)
- 1 0 | 1 1 1 1 | * 0 1 0 Common Lisp array (header block)
- 1 1 | 0 0 1 1 | * 0 1 0 (bitvector)
- 1 1 | 0 1 1 1 | * 0 1 0 encapsulated stack pointer
- 1 1 | 1 0 1 1 | * 0 1 0 (bitvector)
- 1 1 | 1 1 1 1 | * 0 1 0 Common Lisp structure
- (use BPS for vector of 8-bit ints)
- 1 0 | 0 0 1 0 | * 0 1 0 vector of 16-bit integers
- 1 0 | 0 1 1 0 | * 0 1 0 vector of 32-bit integers
- 1 0 | 1 0 1 0 | * 0 1 0 MIXED1 [3 words of pointers, then binary]
- 1 0 | 1 1 1 0 | * 0 1 0 MIXED2
- 1 1 | 0 0 1 0 | * 0 1 0 vector of single-precision floats
- 1 1 | 0 1 1 0 | * 0 1 0 vector of double-precision floats
- 1 1 | 1 0 1 0 | * 0 1 0 MIXED3
- 1 1 | 1 1 1 0 | * 0 1 0 Stream handle (aka MIXED4)
- -------------------------------------------------------------------------------
- FAST PROPERTY ACCESS IN CSL/CCL
- ===============================
- The "fast-get" facility in CSL arranges that for a number of user-specified
- property names (used with both GET and FLAGP) the access has constant cost.
- Normally access to a property involves searching a property list, and if one
- symbol has many properties this can be tedious - with a worst case in the
- fairly common circumstance that the property is not found.
- To speed up CSL I allocate 6 bits in a symbol header that influence how that
- symbol is treated when used as a property name. One code is reserved to
- mean "use a normal property list", leaving 63 codes for fast access. The
- first of these is reserved for a property called 'NONCOM because the built-in
- ORDERP function wants to use this for compatibility with REDUCE(!!).
- A tag must be marked as "fast" before any properties with that indicated are
- set up. If this constraint is not adhered to then properties can end up
- stored in inconsistent or redundant forms. The protocol is to select an
- integer in the range 0 to 63 for each tag to be handled specially, and then
- to make a call such as
- (symbol-make-fastget 'noncom 0)
- (symbol-make-fastget 'my_property_name 1)
- (flag '(a b c) 'noncom)
- (put 'x 'my_property_name 'y)
- or (setf (get 'x 'my_property_name) 'y)
- The fast-get status of a symbol can be inspected using
- (symbol-fast-get 'x nil)
- or reset to have no special treatment (please do not do this!)
- (symbol-fast-get 'x -1)
- When a symbol is given a "fast" property a vector of length 63 is created
- and a word in the symbol's header is made to point to it. The vector contains
- either property values ir a marker that indicates that no property is
- present. A call (symbol-fastgets 'x) can retrieve the vector and can be
- useful while debugging, maybe.
- If you inspect the property list of an object (using the PLIST function) then
- any fast properties are extracted from the vector and built onto the front
- of the property list as returned. Of course this means that altering the
- property list using RPLACx may not be useful!
- The function GET retrieves a property. In Common Lisp mode the three-argument
- version (GET a b c) allows c to be returned as a default value if the
- property sought is not present. The two-argument version can not distinguish
- between a property whose value is NIL and not having a property present
- at all. The function FLAGP returns T if a property is present (whatever
- value is associated, including the case where the stored value is NIL). The
- function FLAG just sets properties, giving them the value T in a somewhat
- arbitrary way.
- Clearly use of fast gets consumes memory, but because many of the extra
- vectors contain many NIL elements they compress well in image files, which
- therefore do not grow too badly. To decide which properties are most
- critical you can run tests using the profiled version of the bytecode
- interpreter (bytes.c rather than bytes1.c), and after a run call the
- function (BYTECOUNTS). You need to adjust your build sequence so that
- the file bytes.c is compiled with RECORD_GET defined, e.g. by putting
- -DRECORD_GET
- among the flags passed to your C compiler. Note that this option will slow
- things down noticeably. The output from BYTECOUNTS indicates which property
- tags were used, and how many unsuccessful searches for each tag occurred. This
- latter information is collected because unsuccessful searches are the worst
- case for a traditional property list search.
- Note that when a property is handled "fast" it is not stored on the regular
- property list (the only information about it is in the vector). Thus if the
- most commonly used properties have been handled this way the average length
- of property lists will shrink and so access to all other properties is
- slightly speeded up too.
- By editing FASTGET_SIZE in the source file "tags.h" if would be possible to
- make the symbol extension vectors smaller than 63 items long, so in
- cases where a much smaller set of tags is important the system can
- be configured to save some memory.
- -----------------------------------------------------------------------
- [This issue was responded to during the Axiom customisation process]
- Subject: Interface for dynamic opening and closing of libraries
- Arthur:
- I've discussed the specification of the "dynamic libraries" interface with
- Barry and this is what we think we need. For a user's own code, we will
- always know the full pathname of the library it is in, so we can load the
- module explicitly.
- 1. A function that loads a particular module from a particular library, e.g.
- (load-module <module> <pathname>)
- The library need not be open for input. You might wish to have separate
- open-library, load-module, and close-library operations if that is more
- efficient.
- 2. A function that opens a library for output, e.g.
- (open-library <pathname>)
- The function need not be responsible for checking if the library is open
- already.
- 3. A function that reads a lisp source file, translates it into byte codes,
- and writes the results into a named library, e.g.
- (fasl-out <filename> <library>)
- This could either:
- (a) Overwrite an existing module with the same name (our preferred option),
- or
- (b) replace the entire library if it already exists.
- 4. A function that closes an open library and, if option 3a above is
- implemented, does all the necessary tidying-up, compaction etc, e.g.
- (close-library <pathname>)
- 5. Facilities for setting the library search path from within Lisp:
- (a) deleting a library from the search path;
- (b) adding a new library to the front of the search path;
- (c) adding a new library to the end of the search path.
- ------------------------------------------------------------------------
- This shows the proportionate use of the various byte opcodes
- on one particular test run. The information was collected while I was
- trying to optimise the bytecode design. If any elaborate bytecode or
- combination of bytecodes was getting very heavy use I might provide
- special-case variants etc. Of course with different test programs the
- profile may end up somewhat different.
- 7.3400 LOADLOC6
- 3.8160 LOADFREE
- 3.6256 CARLOC6
- 2.8646 LOADFREE2
- 2.7618 EXIT
- 2.6747 PUSH
- 2.6054 LOADLOC1
- 2.2990 LITGET
- 2.2175 LOADLOC3
- 2.0495 STOREFREE
- 2.0072 JUMPNIL_L
- 2.0046 CONS
- 1.8176 BUILTIN2
- 1.7415 JUMPNIL
- 1.7210 LOADLOC0
- 1.5494 JUMPST1NI
- 1.5250 BUILTIN1
- 1.4593 JUMPNIL_B
- 1.4564 CALL1
- 1.4206 STORELOC1
- 1.3783 PUSHNIL2
- 1.3783 LOSE2
- 1.3624 FREERSTR
- 1.3624 FREEBIND
- 1.2805 JUMPT
- 1.2565 JUMP_B
- 1.1196 CDR
- 1.0389 LOADLOC5
- 1.0384 VNIL
- 0.9265 STORELOC2
- 0.9265 STORELOC0
- 0.9200 JUMPNEQCA
- 0.8966 CAR
- 0.8812 LOADLOC10
- 0.8712 JUMP_BL
- 0.8607 LOADLOC2
- 0.8244 STOREFREE
- 0.7828 LOADLOC4
- 0.7735 GREATERP
- 0.7659 JUMPNFLAG
- 0.7408 JUMPLITNE
- 0.7264 CALL2_1
- 0.7089 LOADLIT
- 0.6966 ADD1
- 0.6903 CARLOC2
- 0.6749 LOADLOC7
- 0.6739 JUMPT_BL
- 0.6556 CADR
- 0.6501 JUMPNATOM
- 0.6448 JUMPFLAGP
- 0.6395 CALL2
- 0.6369 JUMPLITEQ
- 0.6357 LOSE
- 0.6287 STORELOC
- 0.6274 SWOP
- 0.6003 LOADLIT4
- 0.5577 STORELOC5
- 0.5397 APPLY1
- 0.5004 LOADLOC9
- 0.4910 CDRLOC2
- 0.4772 JUMPL2T
- 0.4630 CARLOC10
- 0.4404 LOADLIT1
- 0.4196 CARLOC0
- 0.4178 CDRLOC0
- 0.4173 JUMPNIL_B
- 0.4029 JUMPFREE3
- 0.3861 STORELOC4
- 0.3767 STORELOC3
- 0.3659 NCONS
- 0.3613 LOADLOC8
- 0.3589 PUSHNIL
- 0.3164 JUMPB2NIL
- 0.3108 JUMPFREEN
- 0.3030 JUMPATOM
- 0.2955 JUMPFREET
- 0.2879 PUSHNILS
- 0.2823 LOADLOC
- 0.2672 CALL1_3
- 0.2587 CARLOC1
- 0.2554 CDDR
- 0.2515 CARLOC5
- 0.2469 CALL1_1
- 0.2457 LOADLOC11
- 0.2298 LOSES
- 0.2275 PUSHNIL3
- 0.2109 JUMPLIT2N
- 0.2024 NUMBERP
- 0.2013 CALL3
- 0.2004 JUMPT_L
- 0.1952 JUMPL0T
- 0.1930 CALL2R
- 0.1910 JUMPLIT1N
- 0.1840 JUMPL1T
- 0.1835 LOSE3
- 0.1789 STORELOC7
- 0.1785 CALL2_4
- 0.1706 CALL1_2
- 0.1696 CAARLOC2
- 0.1673 POP
- 0.1645 JUMPL1NIL
- 0.1582 LOADFREE1
- 0.1533 JCALL
- 0.1516 JUMPNE
- 0.1512 CARLOC4
- 0.1463 LOADLIT2
- 0.1418 JUMPL1NAT
- 0.1414 CARLOC11
- 0.1382 CDRLOC1
- 0.1373 CDRLOC5
- 0.1352 JUMPL0NIL
- 0.1350 JUMPB1NIL
- 0.1251 LOADLIT3
- 0.1238 LOADLIT5
- 0.1180 LOADFREE3
- 0.1173 CDAR
- 0.1163 CARLOC7
- 0.1127 CAAR
- 0.1120 JUMPST0NI
- 0.1108 ACONS
- 0.1080 LOADLIT6
- 0.1077 XCONS
- 0.1061 CALLN
- 0.0986 JUMPT_B
- 0.0973 CALL1_5
- 0.0959 CARLOC9
- 0.0890 LOADFREE4
- ----------------------------------------------------------------------
- [some comments from when NAG were getting Axiom support fully up to
- scratch: these are now probably only of historical interest!]
- 15 May [PAB] sys*.c: get_truename should preserve '/' at end of string
- print.c: fix memory leak in Ltruename
- 21 May [PAB] syscwin.c: use STARTF_USESTDHANDLES
- 17 Jun [MCD] scandir.c: Changed the NT version of scan_files to check
- for a trailing '\' before adding '\*.*'.
- 12 Aug [MCD] all files: merged with latest version from ACN.
- 14 Aug [MCD] fns3.c: Added C-coded version of subseq and auxilliaries.
- 22 Aug [TTT] arith03.c arith11.c: changed quotib,Cremainder to treat
- properly the case (DIVIDE -134217728 134217728)
- 23 Aug [TTT] fns1.c: changed a comment to refer to *break-loop* not *break-function*
- 30 Aug [TTT] machine.h: SYS_TIMES macro name changed because of collision
- with system-defined macro in HP/UX
- also affected :sys.h restart.c sysunix.c sysvms.c sysxwin.c
- 20 Sep [TTT] fns3.c: added hashtable-flavour thingies
- 9 Oct [TTT] sockets.c: added glnag calls for all platforms
- added NANQ support
- 28 Oct [TTT] scandir.c: use realloc_wnull instead of realloc
- to cure SunOS4.1.2 problems with realloc(0,...)
- 20 Nov [TTT] read.c: typo Lrdfn Lddfn fixed
- 20 Nov [TTT] read.c: Lrdf4 : changed the Lopen to honour :if-does-not-exist
- keyword
- 21 Nov [MCD] All files: merged latest changes from Arthur.
- 2 Dec [TTT] gc.c : added timnag_ license management call in reclaim
- 2 Dec [TTT] csl.c: added init_lm call in ENTRYPOINT
- 3 Dec [TTT] sockets.c: changed product codes to AX???23NA
- added nullary init_lm function
- ------1997
- 24 Jan [TTT] sysunix.c: changed mkdir(filename,0770) to
- mkdir(filename,0777) to respect world setting of umask
- in create_directory.
- 23 April [MCD] externs.h restart.c csl.c fasl.c fns1.c fns2.c eval2.c
- Introduced mechanism (using symbol_protect_flag) to toggle
- protection of symbols in kernel.
- 10 July [MCD] csl.c Added initialisation of symbol_protect_flag to 1
- syscwin.c: Fixed bug in truename which stuck extra trailing
- slashes on directory names, causing directoryp to fail.
- 19 Sep [MCD] csl.c : Disabled CCL break messages on interrupt
- 3 Dec [PAB] read.c, gc.c: Added call-counting mode to mapstore
- (yes, it is a hack).
- -------------------------------------------------------------------------
- I have just manufactured a version of CSL that is (perhaps) easy to call
- from other C code. What follows is the main chunk of code that shows
- what the interface is. What this means wrt REDUCE is that I will want to
- manufacture an alternative to (BEGIN) that reads-simplifies-prints just
- one REDUCE expression/command at a time rather than the current single
- function that gobbles things for ever....
- /*
- * The next fragment of code is to help with the use of CSL (and hence
- * packages written in Lisp and supported under CSL) as OEM products
- * embedded within larger C-coded packages. There is (of course) a
- * significant issue about clashes between the names of external symbols
- * if CSL is to be linked with anything else, but I will not worry about that
- * just yet.
- * The protocol for calling Lisp code from C is as follows:
- *
- * cslstart(argc, argv, writer);allocate memory and Lisp heap etc. Args
- * should be "as if" CSL was being called
- * directly and this was the main entrypoint.
- * The extra arg accepts output from this
- * stage. Use NULL to get standard I/O.
- * execute_lisp_function(fname, reader, writer);
- * fname is a (C) string that names a Lisp
- * function of 0 args. This is called with
- * stdin/stdout access redirected to use the
- * two character-at-a-time functions passed
- * down. [Value returned indicates if
- * the evaluation succeeded?]
- * cslfinish(writer); Tidies up ready to stop.
- */
-
- int execute_lisp_function(char *fname,
- character_reader *r, character_writer *w)
- {
- Lisp_Object nil;
- Lisp_Object ff = make_undefined_symbol(fname);
- nil = C_nil;
- if (exception_pending()) return 1; /* Failed to make the symbol */
- procedural_input = r;
- procedural_output = w;
- Lapply0(nil, ff);
- procedural_input = NULL;
- procedural_output = NULL;
- nil = C_nil;
- if (exception_pending()) return 2; /* Failure during evaluation */
- return 0;
- }
- #ifdef SAMPLE_OF_PROCEDURAL_INTERFACE
- static char ibuff[100], obuff[100];
- static int ibufp = 0, obufp = 0;
- static int iget()
- {
- int c = ibuff[ibufp++];
- if (c == 0) return EOF;
- else return c;
- }
- static void iput(int c)
- {
- if (obufp < sizeof(obuff)-1)
- { obuff[obufp++] = c;
- obuff[obufp] = 0;
- }
- }
- #endif
- int MS_CDECL main(int argc, char *argv[])
- {
- cslstart(argc, argv, NULL);
- #ifdef SAMPLE_OF_PROCEDURAL_INTERFACE
- strcpy(ibuff, "(print '(a b c d))");
- execute_lisp_function("oem-supervisor", iget, iput);
- printf("Buffered output is <%s>\n", obuff);
- #else
- cslaction();
- #endif
- my_exit(cslfinish(NULL));
- return 0;
- }
- ...............................end
- Arthur Norman. 2002
|