GNU Smalltalk version 1.2 by Steve Byrne *** NOTE *** THIS DOCUMENT IS OUT OF DATE FOR 1.2 *** SEE README-1.2 FOR A QUICK INTRO TO 1.2 FEATURES The files in this directory and its subdirectories constitute the complete source code for GNU Smalltalk. The files are organized as follows: . The source files, both .st (Smalltalk) and C files config Various supported platforms contrib Contributed software examples Some working example Smalltalk files test Regression testing files stix SmallTalk Interface to X About GNU Smalltalk GNU Smalltalk attempts to be a reasonably faithful implementation of Smalltalk-80 {tm ParcPlace Systems} as described in the "Blue Book", also known as "Smalltalk-80: the Language and its Implementation", by Adele Goldberg and David Robson. The syntax that the language accepts and the byte codes that the virtual machine interprets are exactly as they appear in the Blue Book. Most of the primitives are the same as well, although due to the differing nature of the implementation some of the primitives haven't been implemented, and other new ones have been. The current implementation has the following features: * Incremental garbage collector * Binary image save capability * C-callout (allows Smalltalk to invoke user-written C code and pass parameters to it) * GNU Emacs editing mode * Highly portable C code implementation * Optional byte code compilation tracing and byte code execution tracing * Automatically loaded per-user initialization files Installing GNU Smalltalk Please see the file mst.texinfo which contains the information on how to install GNU Smalltalk, and general documentation about the features of the system. Bugs To report bugs or suggestions (or even offer assistance :-) ), send mail to bug-gnu-smalltalk@prep.ai.mit.edu. If there is sufficient traffic, I will set up a gnu.smalltalk newsgroup as well.
Brief overview of new features with version 1.2: Emacs editing * bugs fixed * many Smalltalk mode commands are now available in the Smalltalk "shell" mode * new browser mode once Smalltalk is built, you can invoke the browser from a Smalltalk mode buffer by doing C-C C-B C-H (Browse Hierarchy). Commands in first window are: space (browse all instance methods) d (browse direct methods), i (browse indirect only methods), c (browse class methods (all)). From the generated method browser window, use space to select the definition of the particular method, move to a different line, hit space again to see that method's definition, etc. The key bindings are likely to change to get more regular with time, and there may be a way to see the class definition. * C-c C-s shows all classes where the selector that's under the cursor is defined, type a space to jump to the definition in the chosen class. * Do c-c c-b c-o to load class names, then c-c c-b c-d browses direct methods of a class (reads class name with completion) c-c c-b c-i browses indirect methods c-c c-b c-c browses class methods * C-c c-t defines a map which toggles various tracing facilities in the running Smalltalk: c-d for declaration tracing c-e for execution tracing c-v for verbose executation tracing * there are probably other undiscovered treasures waiting to be found in the emacs editing mode. c-c d is your friend!!! Initialization files * $HOME/.stpre is loaded before building the basic mst.im image * $HOME/.stinit is loaded each time smalltalk starts up, whether or not it build the saved mst.im image during the run, and is loaded after the binary image has been saved. Sun examples C Pointer hacking * provides direct access to C data structures including o long (unsigned too) o short (unsigned too) o char (unsigned too) & byte type o float (and double) o string (NUL terminated sequence of char * ) o arrays of any type o pointers to any type (I'm not happy with the semantics of this; it's likely to change) o structs containing any fixed size types Example struct decl in C: (see sun/Sound.st for example usage) struct audio_prinfo { unsigned channels; unsigned precision; unsigned encoding; unsigned gain; unsigned port; unsigned _xxx[4]; unsigned samples; unsigned eof; unsigned char pause; unsigned char error; unsigned char waiting; unsigned char _ccc[3]; unsigned char open; unsigned char active; }; struct audio_info { audio_prinfo_t play; audio_prinfo_t record; unsigned monitor_gain; unsigned _yyy[4]; }; Equivalent in Smalltalk: CStruct newStruct: #AudioPrinfo declaration: #((sampleRate uLong) (channels uLong) (precision uLong) (encoding uLong) (gain uLong) (port uLong) (xxx (array uLong 4)) (samples uLong) (eof uLong) (pause uChar) (error uChar) (waiting uChar) (ccc (array uChar 3)) (open uChar) (active uChar)) ! CStruct newStruct: #AudioInfo declaration: #((play AudioPrinfo) (record AudioPrinfo) (monitorGain uLong) (yyy (array uLong 4)) ) ! C Callin * needs no explicit initialization * can initialize with command line arguments if desired (so as to control when the smalltalk initialization occurs) * smalltalk need not be main Stix * Provides full access to X protocol * doesn't currently have support for resources * ICCCM support not working yet * See stix/README Dynamic Linking * based on the GNU DLD library * allows Smalltalk to dynamically load and reference C code * Has an example of use at the bottom
$Revision: 1.3 $ Dear Alpha People: Here is the Alpha 5 release. It contains: * Brad Diller's GUI Based Browser (finally). See the README in blox for details on how to run it. This looks, acts, etc. like the traditional Smalltalk class browser. Brad has done a tremendous job, both in the actual writing of this code, and taking care of the thousand-and-one detail with ensuring that it can be released without complications. Congratulations Brad!!! * WindowNT/Visual C++ port now available: smalltalk-nt-1.2.alpha5.tar.gz Be sure to untar it onto a file system which understands long file names (i.e. not a regular DOS file system). * Optimization via the --with-optimize flag to configure. Once you've configured optimization on, compiles from then on will use the -O flag and define the OPTIMIZE preprocessor symbol * The system has compiled on OS/2 -- I haven't integrated the makefile changes completely yet back into the source base. * Most of the system dependencies have been moved into sysdep.c. * Calling #new: on a non-indexable array now generates an error; sending #new to an indexable array now generates an error * I believe indexing outside of the bounds of an array now causes an error * defining a C function which has not been registered via defineCFunc now prints a warning message. * the .info file is now part of the distribution -- you no longer need to run makeinfo to get it. * added the -g flag to suppress GC flip messages. * lots of clean up to the make files * uses the Makefiles.defs/Makefiles.rules to factor out the common parts of Makefiles, and puts Makefile.body in the subdirectories which just contains the subdirectory specific targets. * makeinfo is not required -- system should deal gracefully if makeinfo is not present. * added extra X location configure functionality; previously, it wasn't finding some of the X includes on Solaris. * configure now understands -enable-gc-torture. This causes the garbage collector to run with *each* allocation of storage. * if you use the GC torture (using the --enable-gc-torture config operation, you can arrange for the GC torturing to run only for a given range of code. startGCTorture (only defined when GC torturing is present) begins the torture test, and stopGCTorture stops it. Invocations of these functions can be nested; the outermost ones dominate. ====================================================================== [Here's the section on the new incubator support from oop.h. Incubator support. The incubator concept provides a mechanism to protect newly created objects from being accidentally garbage collected before they can be attached to some object which is reachable from the root set. [It is very likely that this interface will move to gstpub.h as part of the public interface at some point in the future.] When to use this interface. --------------------------- If you are creating some set of objects which will not be immediately (that means, before the next object is allocated from the Smalltalk memory system) be attached to an object which is still "live" (reachable from the root set of objects), you'll need to use this interface. The interface provides the following operations: void incAddOOP(OOP anOOP) Adds a new object to the protected set. IncPtr incSavePointer() Retrieves the current incubator pointer. Think of the incubator as a stack, and this operation returns the current stack pointer for later use (restoration) with the incSetPointer function. void incRestoresPointer(IncPtr ptr) Sets (restores) the incubator pointer to the given pointer value. Usage: Typically, when you are within a function which allocates more than one object at a time, either directly or indirectly, you'd want to use the incubator mechanism. First you'd save a copy of the current pointer in a local variable. Then, for each object you allocate (except the last, if you want to be optimal), after you create the object you add it to the incubator's list. When you return, you need to restore the incubator's pointer to the value you got with incSavePointer using the incRestorePointer function. Here's an example from cint.c: The old code was (the comments are added for this example): desc = (CFuncDescriptor)newInstanceWith(cFuncDescriptorClass, numArgs); desc->cFunction = cObjectNew(funcAddr); // 1 desc->cFunctionName = stringNew(funcName); // 2 desc->numFixedArgs = fromInt(numArgs); desc->returnType = classifyTypeSymbol(returnTypeOOP, true); for (i = 1; i <= numArgs; i++) { desc->argTypes[i - 1] = classifyTypeSymbol(arrayAt(argsOOP, i), false); } return (allocOOP(desc)); "desc" is originally allocated via newInstance with. At "1", more storage is allocated, and the garbage collector has the potential to run and free (since no live object is referring to it) desc's storage. At "2" another object is allocated, and again the potential for losing both desc and desc->cFunction is there if the GC runs (this actually happened!). To fix this code to use the incubator, modify it like this: OOP descOOP; IncPtr ptr; incPtr = incSavePointer(); desc = (CFuncDescriptor)newInstanceWith(cFuncDescriptorClass, numArgs); descOOP = allocOOP(desc); incAddOOP(descOOP); desc->cFunction = cObjectNew(funcAddr); incAddOOP(desc->cFunction); desc->cFunctionName = stringNew(funcName); // since none of the rest of the function (or the functions it calls) // allocates any storage, we don't have to add desc->cFunctionName // to the incubator's set of objects, although we could if we wanted // to be completely safe against changes to the implementations of // the functions called from this function. desc->numFixedArgs = fromInt(numArgs); desc->returnType = classifyTypeSymbol(returnTypeOOP, true); for (i = 1; i <= numArgs; i++) { desc->argTypes[i - 1] = classifyTypeSymbol(arrayAt(argsOOP, i), false); } incRestorePointer(ptr); return (descOOP); Note that it is permissible for a couple of functions to cooperate with their use of the incubator. For example, say function A allocates some objects, then calls function B which allocates some more objects, and then control returns to A where it does some more execution with the allocated objects. If B is only called by A, B can leave the management of the incubator pointer up to A, and just register the objects it allocates with the incubator. When A does a incRestorePointer, it automatically clears out the objects that B has registered from the incubator's set of objects as well; the incubator doesn't know about functions A & B, so as far as it is concerned, all of the registered objects were registered from the same function. [Implementation note: Macros are only used here for speed, since this is used in relatively busy code and function call overhead would have measurable impact on the system's performance. Three global variables are used instead of one global struct for similar reasons.] ====================================================================== Next on the agenda: Alpha6 * switch to new context model (another a big size reduction) * document new C type model Alpha7 * finish DEC Alpha work * tcp abstraction * argc smalltalk-accessible and modifyable from Smalltalk * need to complete Smalltalk in Smalltalk compiler Alpha8 * port blox to Windows * some other Windows hacks. * finish updating DLD integration Alpha9 * add long integer support * write documentation * finish callin interface Still to do: * browser * fix st.el bugs. * extend test suite NOTE: You'll receive 1 warning message when compiling on Solaris (maybe it's fixed by 2.4 or 2.5) about gettimeofday not being defined. It's their bug -- their man page says it's defined by sys/time.h, but it's not; in fact, it's not defined *anywhere* in /usr/include or any of its subdirectories! NOTE: If you rerun autoconf, you'll see these messages: configure.in:98: warning: AC_TRY_RUN called without default to allow cross compiling configure.in:122: warning: AC_TRY_RUN called without default to allow cross compiling configure.in:123: warning: AC_TRY_RUN called without default to allow cross compiling These are coming from high level macros within the autoconf system that I don't seem to be able to override. They are harmless, according to the autoconf documentation, so just ignore them. [Since it's not included in the documentation yet, here's the blurb on the C data representation stuff again. In addition: CObjects holds a pointer to a C type variable. The variable have been allocated from Smalltalk by doing "<type> new", where <type> is a CType subclass instance, or it may have been returned through the C callout mechanism as a return value. Thinking about this facet of the implementation (that CObject point to C objects) tends to confuse me when I'm thinking about having CObjects which are of type (say) long* ... so I try to think of CObject as just representing a C data object and not thinking about the implementation. To talk about the *type* "long*", you'd create an instance of CPtrCType, since all CType instances represent C types (not C objects), via CPtrCType elementType: CLongType. "use the existing CLongCType instance" To allocate one of these C objects, you'd do: longPtr _ (CPtrCType elementType: CLongType) new. Now you have a C variable of type "long*" accessible from longPtr. CStructs are CType subclasses, because their instances describe C data types. Right now, you can create a CStruct instance using: CStruct newStruct: #AudioPrinfo declaration: #((sampleRate uLong) "unsigned long sampleRate;" (channels uLong) "unsigned long channels;" (precision uLong) (encoding uLong) (gain uLong) (port uLong) (xxx (array uLong 4)) "unsigned long xxx[4]" (samples uLong) (eof uLong) (pause uChar) "unsigned char pause" (error uChar) (waiting uChar) (ccc (array uChar 3)) (open uChar) (active uChar)) ! This creates a new subclass of CStruct called AudioPrinfo with the given fields. For simple scalar types, just list the type name after the variable. Here's the set of scalars names: typeMap at: #long put: #CLongType; at: #uLong put: #CULongType; at: #char put: #CCharType; at: #uChar put: #CUCharType; at: #short put: #CShortType; at: #uShort put: #CUShortType; at: #float put: #CFloatType; at: #double put: #CDoubleType; at: #string put: #CStringType. AudioPrinfo has methods defined on it like: #sampleRate #channels etc. These access the various data members. The array element accessors (xxx, ccc) just return a pointer to the array itself. To have a pointer to a type, use: (example (ptr long)) The objects returned by using the fields are CObjects; there is no implicit value fetching currently. For example, suppose you somehow got ahold of an instance of class AudioPrinfo as described above (the instance is a CObject subclass and points to a real C structure somewhere). Let's say you stored this object in variable "audioInfo". To get the current gain value, do audioInfo gain value to change the gain value in the structure, do audioInfo gain value: 255 The structure member message just answers a CObject instance, so you can hang onto it to directly refer to that structure member, or you can use the #value or #value: methods to access or change the value of the member. Note that this is the same kind of access you get if you use the #addressAt: method on CStrings or CArrays or CPtrs -- they return a CObject which points to a C object of the right type and you need to use #value and #value: to access and modify the actual C variable. ] Here's a brief tour of the new C data type manipulation system: CType -- used to represent C data types themselves (no storage, just the type). There are subclasses called things like C<mumble>CType, one for each of the C "scalar" types (includes strings, pointers, and arrays). The instances can answer their size and alignment. Their "valueType" is the underlying type of data. It's either an integer, which is interpreted by the interpreter as the scalar type, or the underlying element type, which is another CType subclass instance. To make life easier, there are global variables which hold onto instances of the basic C scalar types: C<mumble>Type (not C<mumble>*C*Type). These can be used whereever a C datatype is used. If you had an array of strings, the elements would be CStringType's (a specific instance of a C data type). CObject is the base class of the instances of C data. It has a subclass called CScalar, which has subclasses called C<mumble>. These subclasses can answer size and alignment information. Scalars fetch their value when sent the #value message, and change their value when sent the #value: message. CStrings can be indexed using #at: (with a zero based index, which returns a Smalltalk Character instance corresponding to the indexed element of the string. To change the value at a given index, use #at:put:. To produce a pointer to a character, use #addressAt:. To dereference the string (like *(char *)foo), use #deref -- returns an object of type CChar (not a Character instance). To replace the first character in the string, use #deref: and pass in a CChar instance. These operations aren't real useful for CStrings, but they are present for completeness and for symmetry with pointers (after all, you can say "*string" in C and get the first character of the string, and you can say "*string = 'f'). #+ (integer) returns a CChar object pointing to *integer* bytes from the start of the string. #- (intOrPtr) if integer is given, acts like #+. If pointer is given, returns the difference between the two pointers. #incr, #decr, #incrBy:, #decrBy: adjusts the string forward, backward by either 1 or by n characters. Only the pointer to the string is changed; the actual characters in the string remain untouched. #replaceWith: aString replaces the string the instance points to with the new string. Actually copies the bytes from the Smalltalk String instance aString into the C string object, and null terminates. Be sure that the C string has enough room! You can also use a Smalltalk ByteArray as the data source. CArrays represent an array of some C data. The underlying element type is provided by the CType subclass instance associated with the CArray instance. They have #at: and #at:put: operations just like Strings. #at: returns a Smalltalk datatype for the given element of the array (if the element type is a scalar, otherwise it returns a CObject subclass instance whose type is that of the element type); #at:put: works similarly. #addressAt: returns a CObject subclass instance no matter what, which you then can send #value or or #value: to get or set its value. CArray's also support #deref, #+ and #- with equivalent semantics to CString. CPtrs work similar to CArrays (as you might expect -- they try to reflect the kinds of operations you can do to the corresponding C types). CPtr's also have #value and #value: which get or change the underlying value that's pointed to. Like CStrings, they have #incr, #decr, #incrBy: and #decrBy:. They also have #+ and #- which do what you'd expect. To create instances of the CObject subclasses, create or use a CType instance, and send it the #new message. Or, have the return type from a C callout function be the desired CType subclass instance. Steve sbb@gnu.ai.mit.edu <A HREF="http://reality.sgi.com/employees/sbb"> Steve's Home Page </A> <A HREF="http://reality.sgi.com/employees/sbb/what-now.html"> Smalltalk Alpha download Page </A>
9 July 1995 This is the first release of GNU Smalltalk which compiles directly on DOS from the same sources as the regular distribution. To build the system, you *must* install the distribution into a top level directory whose name is that of the .tgz or .zip file; i.e. if the file is gst12a4.tgz then the directory you install into must be c:\gst12a4 (or d: or whatever). If you don't do this, the paths in lib\gstpaths.h will be incorrect and if you run Smalltalk from anywhere other than the main Smalltalk directory, it will have problems locating the Smalltalk kernel files and the Smalltalk saved image. You'll need to have the latest DJGPP compiler installed and operating to build GNU Smalltalk on DOS. If you have it installed and working, you should be able to type: buildgst in the top level Smalltalk directory, and GNU Smalltalk should be build without errors or warnings. Since the system is compiled with DJGPP, the amount of memory that Smalltalk can use is limited to the amount of physical memory available PLUS the amount of disk space available in the DJGPP paging area. I've personally let the interpreter grow to 14 M using a program specifically designed to test growing the memory system and the garbage collector; the default memory requirements as shipped are 1M for the Smalltalk main memory (no semispaces anymore) and some amount for the OOP table.
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.